2016-03-22 11 views
0

Ich versuche, das has_many Muster zu implementieren, das in "Ruby on Rails Nested Attributes" gezeigt wird. Ich kombiniere es mit einigen meiner eigenen Methoden und weiß genau, wo es eine Ausnahme auslöst und warum. Ich weiß einfach nicht, wie ich das beheben soll. Ich verwende accepts_nested_attributes. Ich habe eine Klasse namens ProfilePhones.Probleme mit Objektreflexion in verschachtelter Form mit has_many association

In profile_email.rb:

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

Die Verwendung der oben für verschachtelte Attribute also, wenn sich das Modell ändert es nicht die anderen Controller brechen. Im profiles_controller.rb ich habe:

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

Im Profilaufrufe Ordner habe ich mit den Feldern für die ProfilePhone Datensätze _profile_email_fields.html.erb:

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

Es ist ein bisschen mehr in diesem Teil , aber ich vereinfache es, weil das Teil gut funktioniert. Im Haupt _form Teil habe ich folgendes:

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

In 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 

schließlich im 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 

Das Problem in der application_helper ist Methode oben in der folgenden Zeile:

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

f.object.class kehrt:

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

Verein ist als :profile_emails gesetzt. Das Problem ist, dass dies Nil produziert. Außerdem muss ich über das Modell nachdenken, zu dem es gehört. Wenn ich das Gerät, mit:

Profile.reflect_on_association(association).klass.new 

Es gibt:

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

das ist, was ich will. Wenn ich jedoch zur Ansicht gehe und auf den Link "Eine weitere E-Mail hinzufügen" klicke, passiert nichts. Dies ist wahrscheinlich ein Problem mit meinem coffeescript oder eine Konsequenz des expliziten Aufrufs von Profile. Ich bin mir nicht sicher.

Meine beiden Probleme sind:

  1. In meinem Reflexionsverfahren sollte ich auf Profile werden reflektiert und nicht Profil E-Mail, aber ich bin nicht sicher, wie es zu beheben. Ich kann eine Zeichenfolge des Profilnamens erhalten, aber das hilft nicht.

  2. Wenn ich Profile explizit in der Hilfsmethode aufruft, passiert nichts.

Antwort

0

ein Problem scheint zu sein, dass Sie hier Variablennamen für den form_builder Parameter haben Shadowing:

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

try

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

Thank you so viel zu ändern. Manchmal starrt dich das Problem nur ins Gesicht. – splatoperator

Verwandte Themen