嵌套资源无序加载

时间:2011-10-13 03:29:34

标签: ruby-on-rails

我有一个辅导课和一个步骤课。教程有很多步骤,每个步骤都属于一个教程。我在我的模型和路线文件中有这个设置。在教程类的show动作中,也加载了属于该教程的所有步骤。问题是在创建了几个步骤4-6后,它们将出现故障。例如,加载的第一步是步骤7,但之后步骤按顺序进行。我正在使用postgresql作为数据库,我在我的gemfile中包含了pg gem。 教程模型:

class Tutorial < ActiveRecord::Base
  attr_accessible :name, :summary, :permalink   
  has_many :steps

  validates :name, :presence => true,
               :length => { :maximum => 50 },
               :uniqueness => { :case_sensitive => false }  

  validates :summary, :presence => true,
          :length => { :maximum => 2000 }

  before_create :set_up_permalink

  def to_param
permalink
  end

  private

  def set_up_permalink
    permalink = self.name.gsub(' ', '-').gsub(/[^a-zA-Z0-9\_\-\.]/, '')
  self.permalink = permalink
end

步骤模型:

class Step < ActiveRecord::Base
  attr_accessible :tutorial_id, :body, :position
  belongs_to :tutorial

  validates :body, :presence => true

  before_create :assign_position

  private

  def assign_position
@tutorial = self.tutorial
@position = @tutorial.steps.size
    @position = @position + 1
    self.position = @position
  end
end

路线:

resources :tutorials do
  resources :steps
end

def show
  @tutorial = Tutorial.find_by_permalink(params[:id])
  @steps = @tutorial.steps
  @next = @steps[0]
  @title = "#{@tutorial.name} - A Ruby on Rails tutorial"
  respond_to do |format|
    format.html # show.html.erb
    format.xml  { render :xml => @tutorial }
  end
end

教程展示视图

<%= render :partial => @tutorial.steps %>

2 个答案:

答案 0 :(得分:3)

您在哪里订单?你可以这样做:

@steps = @tutorial.steps.order('position')

或者甚至更好,因为我想不出任何你希望步骤不按顺序的情况:

在您的步骤模型中:

default_scope order('position')

或者,您可以在关联定义上定义顺序:

在您的教程模型中:

has_many :steps, :order => 'position'

编辑,只是为了它,这是一个更简洁的方式来编写assign_position方法:

  def assign_position
    self.position = tutorial.steps.size + 1
  end

答案 1 :(得分:0)

如果可以任意添加和删除步骤,则分配位置的逻辑是有缺陷的。

E.g。

  • 我创建了一个教程和3个步骤,位置为[1,2,3]。
  • 然后我删除了位置2的步骤。
  • 现在还有两个位置[1,3]。
  • 稍后我创建另一个步骤,分配位置3.
  • 现在有三个步骤,但他们的位置是[1,3,3]。那不对!

我会考虑采取几种方法来纠正这种情况:

第一种方式

您可以保留用于将位置分配给新步骤的代码,但是当从教程中删除某个步骤时,会更新位置以确保它们是顺序的。这是一个如何工作的草图。

class Tutorial
  def rectify_step_positions
    # reassign positions so that all the steps form a sequence
    # E.g. step positions [1,3,4] become [1,2,3]
  end
end

class Step
  after_destroy :trigger_rectify_positions

  def trigger_rectify_positions
    tutorial.rectify_step_positions
  end
end

第二种方式

创建新步骤时,您可以在所有现有步骤中将其位置指定为大于最大位置的位置。

def assign_position
  self.position = tutorial.steps.order("position DESC").first.position + 1
end

这种方法比第一种方法更容易实现。当然,现在这些职位没有那么多意义,因为它们不一定是顺序的。位置10的步骤可能是本教程的第2步。

<强>结论

一旦解决了仓位问题,您就可以简单地订购这些步骤。 Bricker已经展示了几种方法。我个人喜欢has_many :steps, :order => 'position'