使用has_many关联以嵌套形式进行对象反射的问题

时间:2016-03-22 17:43:33

标签: ruby-on-rails ruby activerecord coffeescript

我正在尝试实施" Ruby on Rails Nested Attributes"中显示的has_many模式。我将它与我自己的一些方法结合起来,并确切地知道它引发异常的原因以及原因。我只是不知道如何解决它。我正在使用accepts_nested_attributes。我有一个名为ProfilePhones的班级。

在profile_email.rb中:

def self.attrs
  column_names.map(&:to_sym) - [:created_at, :updated_at]
end

将上述内容用于嵌套属性,因此如果模型更改,则不会破坏其他控制器。在profiles_controller.rb中,我有:

def profile_params
  params.require(:profile).permit(.... profile_phones_attributes: ProfilePhone.attrs)

在Profile views文件夹中,我有_profile_email_fields.html.erb,其中包含ProfilePhone记录的字段:

<%= f.text_field :kind, placeholder: "Type" %>
<%= f.text_field :email_address, placeholder: "Email" %>

这部分还有一点,但我简化了它,因为部分功能很好。在主_form部分我有以下内容:

<%= f.fields_for :profile_emails do |f| %>
  <%= render 'profile_email_fields', f: f %>
  <%= link_to_add_fields('Add Another Email', f, :profile_emails) %>
<% end %>

在application_helper.rb中:

 def link_to_add_fields(name = nil, f = nil, association = nil, options = nil, html_options = nil, &block)
   f, association, options, html_options = name, f, association, options if block_given?

   options = {} if options.nil?
   html_options = {} if html_options.nil?

   if options.include? :locals
     locals = options[:locals]
   else
     locals = { }
   end

   if options.include? :partial
     partial = options[:partial]
   else
     partial = association.to_s.singularize + '_fields'
   end

   new_object = f.object.class.reflect_on_association(association).klass.new
   fields = f.fields_for(association, new_object, child_index: 'new_record') do |builder|
     render(partial, locals.merge!( f: builder))
   end

   html_options['data-form-prepend'] = raw CGI::escapeHTML( fields )
   html_options['href'] = '#'

   content_tag(:a, name, html_options, &block)
end

最后,在profiles.coffee中:

$('[data-form-prepend]').click (e) ->
  obj = $($(this).attr('data-form-prepend'))
  obj.find('input, select, textarea').each ->
    $(this).attr 'name', ->
      $(this).attr('name').replace 'new_record', (new Date).getTime()
    return
  obj.insertBefore this
  false

问题出在上面application_helper方法中的以下一行:

 new_object = f.object.class.reflect_on_association(association).klass.new

f.object.class返回:

ProfileEmail(id: integer, kind: string, email_address: string, profile_id: integer, created_at: datetime, updated_at: datetime)

关联设置为:profile_emails。问题是这会产生Nil。另外,我需要反思它属于Profile的模型。当我切换出:

Profile.reflect_on_association(association).klass.new

它返回:

->  #<ProfileEmail id: nil, kind: nil, email_address: nil, profile_id: nil, created_at: nil, updated_at: nil>

这就是我想要的。但是,当我转到视图并点击“添加其他电子邮件”时,没有任何关系。这可能是我的coffeescript或明确调用Profile的结果的问题。我不确定。

我的两个问题是:

  1. 在我的反思方法中,我应该反思个人资料而不是个人资料电子邮件,但我不确定如何解决它。我可以获取一个配置文件名称的字符串,但这没有帮助。

  2. 当我在帮助方法中显式调用Profile时,没有任何反应。

1 个答案:

答案 0 :(得分:0)

一个问题似乎是你在这里有form_builder参数的阴影变量名:

<%= f.fields_for :profile_emails do |f| %>
  <%= render 'profile_email_fields', f: f %>
  <%= link_to_add_fields('Add Another Email', f, :profile_emails) %>
<% end %>

尝试更改为

<%= f.fields_for :profile_emails do |ff| %>
  <%= render 'profile_email_fields', f: ff %>
  <%= link_to_add_fields('Add Another Email', f, :profile_emails) %>
<% end %>