2013-05-09 52 views
0

我已經運行遷移以引入新的has_manyhas many :through關聯。 「標準」通過「layers_assoc」具有_many「圖層」。新功能可以在現有標準下正常工作,但創建新標準時不會創建新圖層或圖層_assocs。Rails has_many未在創建時填充

儘管創建了關聯和具有默認值的遷移,但是在創建標準時是否必須創建關聯的實例?

下面是layers_assocs表

class CreateLayersAssocs < ActiveRecord::Migration 
    def up 
    create_table :layers_assocs do |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 do |standard| 
     Layer.all.each do |layer| 
     begin 
      LayersAssoc.create!(
      standard_id: standard.id, 
      layer_id: layer.id, 
      visible: true 
     ) 
     rescue 
      puts "== Failed to populate standard_id: #{standard.id} with layer_id: #{layer.id} " 
      continue 
     end 
     end 
    end 
    puts "== Finished Populating LayersAssoc table ===================" 
    end 

    def down 
    drop_table :layers_assocs 
    end 
end 

遷移那裏面有一些額外的東西,以幫助的情況下遷移出錯生產。創建標準後,它說undefined method 'visible'。然後檢查數據庫,我可以看到最新的標準不在layers_assocs表中。

這裏是模型。 standard.rb的部位說事:

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 

更新2: 我所有,但解決這個問題。 LayersAssocs會以默認值創建,但我沒有爲標準建立默認圖層關聯。我已經在新方法中將這些默認關聯寫入了before_filter,它工作得很好。但是,儘管保存了標準layer_id,但保存標準時,層ID將消失。

例LayersAssoc後LayersAssoc.new循環:

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

在standard.save:

Mysql2::Error: Column 'layer_id' cannot be null: INSERT INTO `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) 

這確實是混雜。

+0

請提供您用於創建的代碼。 – wintermeyer 2013-05-09 20:15:54

+0

已添加。我會在標準模型創建動作中插入'LayersAssoc.create'模塊,但這樣做不必要。 – Archonic 2013-05-09 21:07:54

+0

我認爲它與標準,圖層或layers_assoc模型中某處缺少'attr_writter'有關。 – Archonic 2013-05-09 22:21:56

回答

0

LayersAssocs對象可以使用它們的默認值創建,但我沒有建立默認圖層(通過圖層關聯)。在遷移,此代碼建立了現有的標準默認:

Standard.all.each do |standard| 
    Layer.all.each do |layer| 
    begin 
     LayersAssoc.create!(
     standard_id: standard.id, 
     layer_id: layer.id, 
     visible: true 
    ) 
    rescue 
     puts "== Failed to populate standard_id: #{standard.id} with layer_id: #{layer.id} " 
     continue 
    end 
    end 

該默認需要被翻譯成標準的控制器上的新動作。雖然我錯過了各種Rails約定,但花了我幾天的時間才弄明白。創建動作都初始化將對象保存到數據庫。新操作只是初始化對象,然後調用.save將其提交給數據庫。所以,在上一個before_filter標準控制器新動作:

<%= form_for(@standard) do |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 do |assoc| %> 
     <%= form.fields_for :layers_assocs, assoc do |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> 
... 

注意隱藏:

@standard = Standard.new 
@organization = Organization.find(params[:organization_id]) 
@standard.organization = @organization 

# Create default layers associations 
@default_layers = [] 
for i in 1..5 do 
    @default_layers << LayersAssoc.new(layer_id: i) 
end 
@standard.layers_assocs = @default_layers 

一旦這些LayerAssocs對象initilized,你可以在新的頁面上顯示的形式爲他們字段爲:layer_id提交給標準模型創建的唯一東西是表單的值。如果你在before過濾器中初始化layer_id,那麼不要將它包含在表單中,當調用standard.save時它將爲零,並且創建一個新的標準將不起作用。

希望能幫助別人!