我有这个型号:
class CompanyCrawler < ActiveRecord::Base
....
serialize :entry_pages, Array
def entry_page_objects
entry_pages.map { |url| EntryPage.new(url) }
end
def entry_page_objects_attributes=(attributes)
# ...
end
....
end
此表单用于呈现模型:
.....
%p
%p
= crawler_form.label 'Entry pages'
= crawler_form.text_area :entry_pages_text, size: '80x6'
%ul.entry-pages
= crawler_form.fields_for :entry_page_objects do |entry_page_field|
%li=entry_page_field.text_field :url, size: 80
%a{href: '#', class: 'add-button'} Add Entry Page
我遇到的问题是表单错误地呈现entry_page_object
输入名称(例如company_crawler[entry_page_objects_attributes][0][url]
而不是company_crawler[entry_page_objects][0][url]
)。我真的不确定该怎么做,我已经阅读了文档,示例说明只需定义attr_attributes=(attributes)
和persisted?
我就可以使用fields_for
进行收集用accept_nested_fields
定义的关联。
我见过不同的解决方案,例如只是将String
'entry_page_objects[]'
提供给fields_for
,但我希望与rails命名约定保持一致,我知道我可以使用form_tag
代替form_for
但我想让fields_for
按预期工作。
答案 0 :(得分:0)
以下是所有未正确理解nested_attributes
工作原理的所有信息,例如我。
我所报道的问题实际上是它应该如何运作。当我们拥有这个模型时:
class Foo < ActiveRecord::Base # it has name attribute
has_many :larodis
accepts_nested_attributes_for :larodi
end
class Larodi < ActiveRecord::Base # it has name attribute
belongs_to :foo
end
这个定义让我可以通过给出一个参数哈希来创建Foo
和许多Larodi
的{{1}}。例如:
x = Foo.create(name: 'Josh', larodi_attributes: [ {name: 'Wayne'} ]
x.larodis.map(&:name) # ['Wayne']
如果我们有嵌套属性可以使用#field_for
,那么就会出现这个部分。我们通过查找name_attributes=
方法来检查这一点。如果已定义#fields_for
,则生成<input ... name=object[name][INDEX][method]>...
类型的形式,其中index只是一个整数。
请注意,在实施自定义name_attibutes(attributes)
时,您必须检查属性类型 - 它可以是Array
,例如,此类型可以是Hash
:
{ 1 => { ... } , 2 => { ... } }
就像表示数组的哈希一样,其中键是索引,值是此索引的值。
这件衣服看起来像这样:
_form.html.haml
....
= crawler_form.fields_for :entry_pages do |entry_page_field|
%li
=entry_page_field.text_field :url, size: 80
...
company_crawler.rb
class CompanyCrawler < ActiveRecord::Base
....
serialize :entry_pages, Array
def entry_pages_attributes=(attributes)
self.entry_pages = attributes_collection(attributes).map do |attribute|
EntryPage.new(attribute[:url])
end
end
def entry_pages=(entry_pages)
entry_pages = entry_pages.map do |entry_page|
cast_entry_page_to_entry_page_object(entry_page)
end
write_attribute(:entry_pages, entry_pages)
end
...
private
def attributes_collection(attributes)
case attributes
when Array
attributes
when Hash
attributes.values
end
end
def cast_entry_page_to_entry_page_object(entry_page)
case entry_page
when String
EntryPage.new(entry_page)
when EntryPage
entry_page
end
end
end
为清楚起见,我删除了entry_page_objects
并仅使用entry_pages
。