【问题标题】:Problems with object reflection in nested form with has_many association具有 has_many 关联的嵌套形式的对象反射问题
【发布时间】:2016-03-23 23:50:37
【问题描述】:

我正在尝试实现“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>

这是我想要的。但是,当我转到视图并单击“添加另一封电子邮件”链接时,没有任何反应。这可能是我的咖啡脚本的问题,或者是显式调用 Profile 的结果。我不确定。

我的两个问题是:

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

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

【问题讨论】:

    标签: ruby-on-rails ruby activerecord coffeescript


    【解决方案1】:

    一个问题似乎是您在此处为 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 %>
    

    【讨论】:

    • 非常感谢。有时问题就在眼前。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-21
    • 1970-01-01
    • 2021-08-05
    相关资源
    最近更新 更多