如何保留Rails3中的关联顺序?

时间:2010-12-27 21:06:34

标签: ruby-on-rails view associations nested-forms

我有一系列地点

locations = ["california", "new york", "florida"]

我有一个名为foobar的模型has_many :placesPlace模型belongs_to :foobar并且有一个相关列 - name:string

我有一个嵌套的表单,允许我选择适用于foobar的位置。 为了提供选项,我根据控制器中的位置列表构建了位置:

class FoobarController < ApplicationController
  def edit
    @foobar = Foobar.find(params[:id])
    APP_CONFIG['locations'].each do |location|
       @foobar.places.find_by_name(location) || @foobar.places.build(:name => location)
    end
  end
end

这几乎没有问题。我包含编辑方法的原因是因为这是有问题的。已填充的地点列表,但已存在的Foobar地点显示在顶部。


示例时间! :)

  1. 我创建了一个新的Foobar。在我的形式 我向下滚动到地方,我看到了 选项“加利福尼亚”,“纽约” 和“佛罗里达”。我检查“加州” 和“佛罗里达”并创建Foobar。

  2. 接下来我去编辑Foobar。再一次,我 向下滚动到我看到的地方 我检查了两个选项。那是 很棒,除了订单 选项出现的是 “加利福尼亚”,“佛罗里达”,“纽约” - 经过检查的地方位于顶部。

  3. 如何保留原始阵列中位置的顺序?

    谢谢!


    更新:视图代码:

    <%= f.fields_for :places do |place| %>
        <div class="place">
            <%= place.hidden_field :name %>
            <%= place.check_box :checked %>
            <%= place.label :checked, place.object.name %>
        </div>
    <% end %>
    

2 个答案:

答案 0 :(得分:1)

你不能......至少不是你这样做的方式。想想铁路的作用。它会自动按表的id(PK)列排序。由于您正在建造的记录不会有ID,因此每次都会将它们放在最后。你可能会使用CREATE和fudge id,但这很麻烦,可能会遇到严重的问题。

为了维持秩序(双关语),你需要某种数组指针系统:

class FoobarController < ApplicationController
  def edit
    @foobar = Foobar.find(params[:id])
    @places = Array.new
    APP_CONFIG['locations'].each do |location|
      @places << @foobar.places.build(:name => location)
    end
  end
end

然后,在您的视图中,您需要遍历数组并手动 构建表单。我建议先查看源代码并查看嵌套表单的显示方式。

以下是我接近它的方法 - 每次构建(没有find_by_name)。然后,在您想要的模型中:

class Foo < ActiveRecord
  has_many :places

  accepts_nested_attributes_for :places, :reject_if => { |a| !APP_CONFIG['locations'].include?(a) || Place.find_by_name(a).nil? || !Place.find_by_name_and_foo_id(a, self.id).nil? }
end

现在,我还没有完全根据你的情况测试该代码,所以我会将其分解;

1。)拒绝提交的属性是否不在全局数组中(更多是安全问题)

2。)如果名称不是有效的地方(再次,安全),则拒绝

3。)拒绝该foo的地方是否存在ALREADY(您的班级为has_many:places)

答案 1 :(得分:0)

查看acts_as_list&gt;&gt; https://github.com/rails/acts_as_list,它明确地将项目的顺序存储在名为“position”的列中的has_many集合中。