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
Post a Comment