私は Rails の初心者で (Hartl のチュートリアルを終えたばかりです)、これまでに経験したものよりも少し複雑に見えるいくつかの種類の関連付けに問題があります。問題の解決策を求めてGoogleとstackoverflowを閲覧してきましたが、関連する回答がたくさん見つかりましたが、問題を解決する方法がわかりません。
基本的に私がやろうとしているのは、次の関係を実装することです:
それについて調べた結果、私が思いついたのは次のとおりです。
モデル
# models/user.rb
class User < ActiveRecord::Base
attr_accessible :first_name, :last_name, :email …
has_many :speak, :class_name => "Speaks"
has_many :speaks, :through => :speak, :source => :language
has_many :want_to_learn, :class_name => "WantsToLearn"
has_many :wants_to_learn, :through => :want_to_learn, :source => :language
…
end
# models/language.rb
class Language < ActiveRecord::Base
attr_accessible :iso_639_1_code, :name_en, :name_fr, :name_pt
has_many :speak, :class_name => "Speaks"
has_many :users_who_speak, :through => :speak, :source => :user
has_many :want_to_learn, :class_name => "WantsToLearn"
has_many :users_who_want_to_learn, :through => :wants_to_learn, :source => :user
end
# models/speaks.rb
class Speaks < ActiveRecord::Base
set_table_name 'speak'
attr_accessible :level, :language
references :user
references :language
end
# models/wants_to_learn.rb
class WantsToLearn < ActiveRecord::Base
set_table_name 'want_to_learn'
attr_accessible :language
references :user
references :language
end
移行
# db/migrate/20130210153328_create_speak.rb
class CreateSpeak < ActiveRecord::Migration
def change
create_table :speak do |t|
t.references :user
t.references :language
t.integer :level
t.timestamps
end
end
add_index :speak, :user
add_index :speak, :language
end
# db/migrate/20130210153342_create_want_to_learn.rb
class CreateWantToLearn < ActiveRecord::Migration
def change
create_table :want_to_learn do |t|
t.references :user
t.references :language
t.timestamps
end
end
add_index :want_to_learn, :user
add_index :want_to_learn, :language
end
これを実行して実行しようとするとrake:db migrate
、次のエラーが発生します。
-- add_index(:speak, :user)
rake aborted!
An error has occurred, this and all later migrations canceled:
PG::Error: ERROR: relation "speak" does not exist
: CREATE INDEX "index_speak_on_user" ON "speak" ("user")
...
行をコメントアウトするとadd_index
、移行は正常に実行されますが、ユーザーから「話す」関係を作成できません。たとえば、次のように実行すると:
> john = User.new(first_name: "John", last_name: "Doe", email: "john@doe.com"...)
> john.speaks.create!(level: '6', language: '139')
私は得る:
NoMethodError: undefined method `references' for #<Class:0x007ff14c1771a0>
すべての「参照」を「belongs_to」やその他いくつかのものに置き換えようとしましたが、その多くは覚えていませんが、役に立ちませんでした。これにより、次のようないくつかの疑問が頭に浮かびました。
• "references" は本当に "belongs_to" と同じですか? モデルのコンテキストでも?「参照」が移行で使用されているのを見たことがありますが、モデルは使用されていません。
• "class_name" を正しく使用していますか? 本当に自信がありません。これは、私が読んだすべての後に最も理にかなっているものですが、このような関連付けでカスタマイズの例を見たことがありません.
• これらのインデックスを追加することの何が問題になっていますか?
さて、ここでのエチケットが何であるかはわかりませんが、私の最後の質問は次のとおりです。
これをすべて適切に行うにはどうすればよいですか??
前もって感謝します!
------編集------
キーワード「参照」を「belongs_to」に置き換えました。インデックスに関する移行エラーはまったく同じです。インデックス作成行にコメントを付けたら、移行を実行し、ユーザーを作成してからコマンドを試してください
> john.speaks.create!(level: 6, language: 139)
エラーは次のとおりです。
ActiveModel::MassAssignmentSecurity::Error:
Can't mass-assign protected attributes: level, language
ラインにもかかわらずattr_accessible :level, :language
。