Rails has_many belongs_to with foreign_key和class_name

时间:2014-07-22 19:30:22

标签: ruby-on-rails foreign-keys rails-activerecord has-many belongs-to

我正在尝试为UserMessage s系统建模。 Messageaddresser个和addressee个。 Usersent_message个和received_messages

现在测试失败了,因为它似乎找不到addressee_id和addresser_id。我想知道我是否已正确建模,以及如何通过用户创建消息。

编辑:测试的输出

ActiveRecord :: UnknownAttributeError:未知属性:addressee_id

在消息规范中的before语句中弹出。

用户模型

class User < ActiveRecord::Base
  has_many :sent_messages, class_name: "Message", foreign_key: "addresser_id"
  has_many :received_messages, class_name: "Message", foreign_key: "addressee_id" 

消息模型

class Message < ActiveRecord::Base
  validates :addresser_id, presence: true
  validates :addressee_id, presence: true
  belongs_to :addresser, class_name: "User", foreign_key: "addresser_id"
  belongs_to :addressee, class_name: "User", foreign_key: "addressee_id"
end

移植

class CreateMessages < ActiveRecord::Migration
  def change
    create_table :messages do |t|
      t.string :content     
      t.integer :addresser_id
      t.integer :addressee_id
      t.timestamps
    end
  add_index :messages, [:addressee_id, :addresser_id, :created_at]
  end
end

模式

create_table "messages", force: true do |t|
    t.string   "content"
    t.integer  "addresser"
    t.integer  "addressee"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  add_index "messages", ["addressee", "addresser", "created_at"], name: "index_messages_on_addressee_and_addresser_and_created_at"

message_spec

require 'spec_helper'

describe Message do
  let(:user1) { FactoryGirl.create(:user) }
  let(:user2) { FactoryGirl.create(:user) }
  before { @message = user1.sent_messages.build(content: "Lorem ipsum", addressee_id: user2.id) }

  subject { @message }

  it { should respond_to(:content) }
  it { should respond_to(:addresser_id) }
  it { should respond_to(:addressee_id) }
  its(:addresser) { should eq user1 }

  it { should be_valid }

  describe "when addresser is not present" do
    before { @message.addresser = nil }
    it { should_not be_valid }
  end

  describe "when addressee is not present" do
    before { @message.addressee = nil }
    it { should_not be_valid }
  end
end

2 个答案:

答案 0 :(得分:0)

尝试替换它:

describe Message do
  ...
  before { @message = user1.sent_messages.build(content: "Lorem ipsum", addressee_id: user2.id) }
  subject { @message }
  ...
end

有了这个:

describe Message do
  ...
  let(:message){ user1.sent_messages.build(content: "Lorem ipsup", addressee_id: user2.id) }
  subject { message }
  ...
end

还要检查迁移是否在测试环境中运行。

编辑: ActiveRecord :: UnknownAttributeError表示数据库中缺少一列。迁移似乎没问题,但架构和Message.column_names的输出却没有。

似乎你的addressee_id / addresser_id实际上是在数据库中命名为addressee / addresser。在运行db:migrate之后编辑了迁移文件吗?

尝试运行rake db:migrate:redo STEP = 1(如果这不是您上次的迁移,请更改步骤)

答案 1 :(得分:0)

我更喜欢这样做

class User < ActiveRecord::Base
  has_many :sent_messages, class_name: "Message", as: :addressor
  has_many :received_messages, class_name: "Message", as: :addressee

class Message < ActiveRecord::Base
  belongs_to :addressor, class_name: "User", foreign_key: :addressor_id
  belongs_to :addressee, class_name: "User", foreign_key: :addressee_id