如何保留 Rails3 中关联的顺序?
我有一个位置数组,
locations = ["california", "new york", "florida"]
我有一个名为 foobar 的模型,它 has_many :places
。 Place
模型 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
地点出现在顶部。
示例时间! :)
我创建了一个新的
Foobar
。以我的形式 我向下滚动到一些地方,然后我看到 选项“加利福尼亚”、“纽约” 和“佛罗里达”。我检查“加利福尼亚州” 和“florida”并创建 Foobar。接下来我去编辑 Foobar。再说一遍,我 向下滚动到这些地方,我看到了 我检查了两个选项。那是 很棒,除了顺序 出现的选项是 “加利福尼亚”、“佛罗里达”、“纽约” - 选中的位置位于顶部。
如何保留原始数组中位置的顺序?
谢谢!
更新:查看代码:
<%= 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 %>
I have an array of locations
locations = ["california", "new york", "florida"]
I have a model called foobar that has_many :places
.
the Place
model belongs_to :foobar
and has one relevant column - name:string
.
I have a nested form that allows me to select locations applicable for the foobar.
To offer the options, I build the places based on my locations list in my controller:
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
This works almost without a problem. The reason I'm including the edit method is because that's the problematic one. The list of places DOES get populated, but the Foobar
places that already existed appear on the top.
Example time! :)
I create a new
Foobar
. In my form
I scroll down to places and I see
the options "california", "new york"
and "florida". I check "california"
and "florida" and create Foobar.Next I go to edit Foobar. Again, I
scroll down to the places and I see
that I checked two options. That's
great, except that the order in
which the options appear is
"california", "florida", "new york" - checked places are on the top.
How can I preserve the order of the locations from my original array?
Thanks!
Update: the view code:
<%= 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 %>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
你不能……至少不能以你现在的方式去做。想想 Rails 的作用。它自动按表的 id (PK) 列进行排序。由于您正在构建的记录不会有 id,因此它们每次都会被放置在末尾。您可以欺骗并使用 CREATE 和 fudge id,但这很混乱并且可能会遇到严重的问题。
为了维持顺序(双关语),您需要某种数组指针系统:
然后,在您看来,您需要循环数组并手动构建表单。我建议首先查看源代码并查看嵌套表单的显示方式。
这是我的处理方法 - 每次都构建(没有 find_by_name)。然后,在您的模型中,您想要:
现在,我实际上还没有完全针对您的情况测试该代码,所以我将对其进行分解;
1.) 如果提交的属性不在全局数组中,则拒绝(更多的是安全问题)
2.) 如果名称不是有效位置,则拒绝(同样,安全)
3.) 如果该位置已存在,则拒绝that foo (你的班级有_many :places)
You can't... At least not the way you are doing it. Think about what rails does. It automatically orders by the id (PK) column of a table. Since the records you are BUILDING wont have an id, they will be placed at the end - every time. You COULD finagle and use CREATE and fudge ids, but that's messy and could run into serious problems.
In order to maintain order (pun), you'll need some kind of array-pointer system:
Then, in your view you'll need to loop over the array and manually build the form. I recommend viewing the source and seeing how the nested form appears first.
Here's how I would approach it - build every time (no find_by_name). Then, in your model you want:
Now, I haven't actually tested that code exactly for your case, so I'll break it down;
1.) Reject if the submitted attribute isn't in the global array (more of a security concern)
2.) Reject if the name isn't a valid place (again, security)
3.) Reject if the place ALREADY exists for that foo (your class that has_many :places)
查看acts_as_list>> https://github.com/rails/acts_as_list,它明确地将项目的顺序存储在 has_many 集合中在名为“位置”的列中。
Check out acts_as_list >> https://github.com/rails/acts_as_list, It explicitly stores the order of items in a has_many collection in a column called "position".