我有一个辅导课和一个步骤课。教程有很多步骤,每个步骤都属于一个教程。我在我的模型和路线文件中有这个设置。在教程类的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 %>
答案 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。
我会考虑采取几种方法来纠正这种情况:
第一种方式
您可以保留用于将位置分配给新步骤的代码,但是当从教程中删除某个步骤时,会更新位置以确保它们是顺序的。这是一个如何工作的草图。
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'