【问题标题】:Rails has_many belongs_to with foreign_key and class_nameRails has_many belongs_to 与 foreign_key 和 class_name
【发布时间】:2014-07-22 19:30:21
【问题描述】:

我正在尝试为Users 和Messages 的系统建模。 Messages 有 addressers 和 addressees。 Users 有sent_messages 和received_messages

现在测试失败了,因为它似乎无法找到 addressee_id 和 addresser_id。我想知道我是否正确地对此进行了建模,以及我应该如何通过用户创建消息。

编辑:测试的输出

ActiveRecord::UnknownAttributeError:unknown attribute: 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

【问题讨论】:

  • “测试失败”是什么意思? “似乎找不到 addressee_id 和 addresser_id”是什么意思?不要只给出表格,给出其余的代码,输入和输出。 PS FK 不属于用户。
  • 我将输出添加到问题中。至于输入,我想不出还有什么要包括的。我也认为 User 中会有 FK 很奇怪,但根据 spacevatican.org/2008/5/6/… 这就是解决方案。 @philipxy
  • 添加的信息有帮助。例如,它必须与表声明一致。 (见答案。)另外:如果它已经编译并运行,输入和输出数据。您没有解释“失败”和“找不到”或给出错误消息,所以我们不知道“失败”时正在做什么。 (介于编译和运行之间。)包含与 minimal 示例相关的所有内容How do I ask a good question?.
  • 知道了,谢谢你的提示。

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


【解决方案1】:

尝试替换这个:

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(如果这不是您最后一次迁移,请更改步骤)

【讨论】:

  • 感谢您的建议,不幸的是它只是将错误更改为另一个错误:NoMethodError: undefined method 'addresser=' for nil:NilClass
  • 您还需要将before { @message.addresser = nil } 的两次出现都更改为before { message.addresser = nil } 是否所有测试都失败了?该模型是否在控制台中工作?
  • 对,完全忘记了那部分。我更改了它,但现在它又回到了相同的旧 ActiveRecord::UnknownAttributeError:unknown 属性:addressee_id。我尝试在控制台中创建消息。有趣的是,Message.create 给了我一个 NoMethodError: undefined method 'addresser_id'
  • 你运行迁移了吗? rake db:migrate
  • 是的,我运行了 db:migrate 和 test:prepare。
【解决方案2】:

我更喜欢这样做

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

【讨论】:

  • 嗯,试过这个,但它不能识别类。未知键:类(ArgumentError)
  • 抱歉,我编辑了答案,应该是 class_name 而不是 class。
  • 另外,为了让它工作,你可以让用户有很多消息,然后使用范围或方法来提取他们的 id 是地址或收件人的消息。
  • 没有ArgumentError,但又回到原来的ActiveRecord::UnknownAttributeError:unknown attribute:addressee_id
  • 这是个好主意,我想我可能会继续这样做。这些关联太痛苦了,无法处理。
猜你喜欢
  • 1970-01-01
  • 2013-08-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-29
  • 1970-01-01
  • 2022-07-08
  • 2011-12-20
相关资源
最近更新 更多