Rails has_many not populated on create -


i've run migration introduce new has_many , has many :through association. "standard" has _many "layers" through "layers_assoc". new feature works fine on existing standards, creating new standard, no new layers or layers_assocs created.

despite creating association , migration having defaults, have create instances of association when standard created?

here migration layers_assocs table

class createlayersassocs < activerecord::migration   def     create_table :layers_assocs |t|       t.timestamps       t.integer :layer_id, :null => false      # has_many       t.integer :standard_id, :null => false   # has_many       t.boolean :visible, :default => true     end      add_index :layers_assocs, :layer_id     add_index :layers_assocs, :standard_id      layersassoc.reset_column_information      puts "== populating layersassoc table ============================"     standard.all.each |standard|       layer.all.each |layer|         begin           layersassoc.create!(             standard_id: standard.id,              layer_id: layer.id,              visible: true           )         rescue           puts "== failed populate standard_id: #{standard.id} layer_id: #{layer.id} "           continue         end       end     end     puts "== finished populating layersassoc table ==================="   end    def down     drop_table :layers_assocs   end end 

there's stuff in there in case migration goes wrong on production. after creating standard, says undefined method 'visible'. checking database can see recent standard not in layers_assocs table.

here's models. parts of standard.rb matter:

has_many :layers_assocs has_many :layers, :through => :layers_assocs accepts_nested_attributes_for :layers_assocs 

layers.rb:

has_many :layers_assocs has_many :standards, :through => :layers_assocs 

layers_assoc.rb:

belongs_to :standard belongs_to :layer 

update 2: i've solved issue. layersassocs created defaults fine, had nothing establishing default layer associations standards. i've written default associations before_filter on new method , works fine. however, despite having populated layer_id, when standard saved, layer id disappears.

example layersassoc after layersassoc.new loop:

#<layersassoc id: nil, created_at: nil, updated_at: nil, layer_id: 1, standard_id: nil, visible_authors: true, visible_reviewers: true> 

upon standard.save:

mysql2::error: column 'layer_id' cannot null: insert `layers_assocs` (`created_at`, `layer_id`, `standard_id`, `updated_at`, `visible_authors`, `visible_reviewers`) values ('2013-05-13 21:49:36', null, 112, '2013-05-13 21:49:36', 1, 1) 

this confounding.

the layersassocs objects created defaults fine, had nothing establish default layers (through layers associations). in migration, code established default existing standards:

standard.all.each |standard|   layer.all.each |layer|     begin       layersassoc.create!(         standard_id: standard.id,          layer_id: layer.id,          visible: true       )     rescue       puts "== failed populate standard_id: #{standard.id} layer_id: #{layer.id} "       continue     end   end 

that default needed translated new action on standards controller. missing sorts of rails conventions though , took me few days figure out. create action both initializes and saves object database. new action initializes objects , calling .save commits db. so, in standards controller on before_filter new action:

@standard = standard.new @organization = organization.find(params[:organization_id]) @standard.organization = @organization  # create default layers associations @default_layers = [] in 1..5   @default_layers << layersassoc.new(layer_id: i) end @standard.layers_assocs = @default_layers 

once layerassocs objects initilized, can show form them on new page:

<%= form_for(@standard) |form| %>   ...  <%= form.label t('standard.layers') %>  <table class="table table-striped span4">    <thead>      <tr>        <td><strong><%= t('standard.layer') %></strong></td>        <td><strong><%= t('type.authors') %></strong></td>        <td><strong><%= t('type.reviewers') %></strong></td>      </tr>    </thead>    <tbody>      <% @standard.layers_assocs.each |assoc| %>        <%= form.fields_for :layers_assocs, assoc |layer_field| %>          <tr>            <%= layer_field.hidden_field :layer_id, :value => assoc.layer_id %>            <td><%= t(assoc.layer.name, :default => assoc.layer.name) %></td>            <% if assoc.layer_id == 1 %>              <td><%= layer_field.check_box :visible_authors, :disabled => true %></td>              <td><%= layer_field.check_box :visible_reviewers, :disabled => true %></td>            <% else %>              <td><%= layer_field.check_box :visible_authors %></td>              <td><%= layer_field.check_box :visible_reviewers %></td>            <% end %>          </tr>        <% end %>      <% end %>    </tbody>  </table>  ... 

notice hidden field :layer_id. the thing submitted standard model creation values of form. if initialize layer_id in before filter don't include on form, nil when standard.save called , creating new standard won't work.

hope helps someone!


Comments

Popular posts from this blog

linux - xterm copying to CLIPBOARD using copy-selection causes automatic updating of CLIPBOARD upon mouse selection -

c++ - qgraphicsview horizontal scrolling always has a vertical delta -