2010-12-30 16 views
1

私は、次のモデルがあります:Ruby on Rails:関連モデルの作成方法

class Product < ActiveRecord::Base 
    belongs_to :brand 
    belongs_to :model 
    accepts_nested_attributes_for :brand, :model 
    ... 
end 

class Brand < ActiveRecord::Base 
    has_many :products 
    has_many :models 
    ... 
end 

class Model < ActiveRecord::Base 
    has_many :products 
    belongs_to :brand 
    accepts_nested_attributes_for :brand 
    ... 
end 

私は新製品を作成するために問題を抱えています。

"brand_attributes"=>{"name"=>"my_new_brand"} 
"model_attributes"=>{"model_no"=>"my_new_model"} 

を、私は次のエラーを得た:

class ProductsController < ApplicationController 
    ... 
    def create 
    @product = Product.new(params[:product]) 
    if @product.save ...  # Here is the error 
    end 
    ... 
end 

ユーザーが新ブランドや新モデルを追加し、params[:product]には次のものが含まれます。ここでは

は、コントローラ内の関連するコードです。

Mysql2::Error: Column 'brand_id' cannot be null: INSERT INTO `models` ... 

モデルには外部キーbrand_idがあるためこれは設定されていません。ブランド(モデルのような)は、製品が作成されたときに即座に作成されるため、設定できません。私は製品の前にブランドを作成したくない、私は製品にエラーがあるので、私は作成されたブランドを削除する必要があります。

は、その後、私はこのようparams[:product]を変更しようとしました:

"brand_attributes"=>{"name"=>"my_new_brand", 
        "model_attributes"=>{"model_no"=>"my_new_model"}} 

が、私はこれで終わる:これを処理する適切な方法は何でしょう

unknown attribute: model_attributes 

答えて

2

1)あなたはあなたです)

2.(私はこれがエラーになる可能性がありますなぜ私はここにあなたの問題としてこれを見ていないが、あなたは、見ることができると思います)モデル名などのモデルを使用しないでください円形のパターンをあまりにも多く参照しています。製品にはモデルがあり、モデルにはブランドがあります。なぜあなたは製品をモデルとブランドに所属させていますか?

class Product < ActiveRecord::Base 
    belongs_to :model 
    accepts_nested_attributes_for :model 
end 

class Brand < ActiveRecord::Base 
    has_many :models 
end 

class Model < ActiveRecord::Base 
    has_many :products 
    belongs_to :brand 
    accepts_nested_attributes_for :brand 
end 

私は少しあなたの根本的な問題であるあなたのデータ構造によって混乱しています。

Product < Model <> Brand 

あなたは上記定義しましたようにあなたは、循環参照を持っている場合は、あなたのモデルがネストされているので、あなたがフォームを入れ子していることができません...

# schema 
create_table :products do |t| 
    t.string :name 
    t.references :model 
end 

create_table :brands do |t| 
    t.string :name 
end 

create_table :models do |t| 
    t.string :name 
    t.references :brand 
end 
+0

ありがとうございます。私はそれを試してみます:) –

+0

問題ありません。お力になれて、嬉しいです – sethvargo

1

最初に、トランザクションで保存をラップすると、トランザクションのどの時点でも失敗するとすべての書き込みがロールバックされるため、ブランドなどには影響しません。

Product.transaction do 
    @product.save 
end 

あなたはこの試みることができる:それは何をしよう

before_create :save_associated 
validates_associated :brand, :model 

def save_associated 
    brand.save if brand.new_record? 
    model.save if model.new_record? 
end 

を使用すると、製品レコードを作成するとき、それは自分自身を検証します、そしてそれは添付のブランドとモデルを検証しますです。すべてうまくいけば、before_saveコールバックに進み、関連付けられているモデルを保存し、製品モデルを保存します。 3つのモデルのいずれかが無効であれば、あなたはsave_associatedになることはありません。また、妄想を感じている場合は、上記のようにトランザクションで保存をラップして、保存に失敗した場合は自動的に変更をロールバックできます。

+0

問題はレールではありませんが、あなたの解決策(私はそう考える)は彼の問題を解決することができます。問題は、データベースの設定が意味をなさないということです。彼はネストされた属性を許さない循環問題の自己参照テーブルです – sethvargo

+0

ああ、heh。私はそれを推測するのに十分注意深く質問を読まなかった。 –

+0

haha​​。私は彼がやっていることをやっていた理由を理解できなかったので...私の答えに根本的な問題を修正しようとしました – sethvargo

関連する問題