【问题标题】:Rails 3 serialized model field form_for and field_for not generating correct nameRails 3 序列化模型字段 form_for 和 field_for 没有生成正确的名称
【发布时间】:2015-01-07 16:12:55
【问题描述】:

我有这个模型:

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 按预期工作。

【问题讨论】:

    标签: ruby ruby-on-rails-3 haml


    【解决方案1】:

    这里有一些信息,供所有像我一样没有正确理解 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
    

    这个定义让我可以通过给出参数的哈希值来创建带有许多LarodiFoo。例如:

    x = Foo.create(name: 'Josh', larodi_attributes: [ {name: 'Wayne'} ]
    x.larodis.map(&:name) # ['Wayne']
    

    现在是#field_for 了解我们是否有嵌套属性可以使用的部分。我们通过寻找name_attributes= 方法来检查这一点。如果它被定义#fields_for 生成&lt;input ... name=object[name][INDEX][method]&gt;... 类型的形式,其中索引只是一个整数。

    请记住,在实现自定义 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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多