【问题标题】:Rails: Belongs_to and Has_many associations in Rails EnginesRails:Rails 引擎中的 Belongs_to 和 Has_many 关联
【发布时间】:2021-05-20 04:18:22
【问题描述】:

所以我使用 Rails 6 构建了一个应用程序。我已经使用 Rails Engines 实现了该应用的一些核心功能。

引擎的名称 Baseblog,我有 2 个模型,分别称为 AuthorPost

一个author 有多个posts,而一个post 属于一个author。以下是我的模型实现:

作者模型

module Baseblog
  class Author < ApplicationRecord
    has_many :posts, dependent: :destroy

    validates :name, presence: true
    validates :address, presence: true
  end
end

后模型

module Baseblog
  class Post < ApplicationRecord
    belongs_to :author

    validates :name, presence: true
  end
end

这是我对 Author 模型的 rspec 测试:

作者规范

require 'rails_helper'

module Baseblog
  RSpec.describe Author, type: :model do
    describe 'associations' do
      it { is_expected.to have_many(:posts) }
    end

    describe "validations" do
      it { is_expected.to validate_presence_of(:name) }
      it { is_expected.to validate_presence_of(:address) }
    end
  end
end

作者工厂机器人

FactoryBot.define do
  factory :school do
    name { "MyString" }
    address { "MyText" }
  end
end

帖子架构

create_table "baseblog_posts", force: :cascade do |t|
  t.string "name"
  t.text "description"
  t.bigint "baseblog_author_id", null: false
  t.datetime "created_at", precision: 6, null: false
  t.datetime "updated_at", precision: 6, null: false
  t.index ["baseblog_author_id"], name: "index_baseblog_posts_on_baseblog_author_id"
  end

但是,当我为 Author 模型运行测试时,我得到了错误:

Failures:

  1) Baseblog::Author associations is expected to have many posts
     Failure/Error: it { is_expected.to have_many(:posts) }
       Expected Baseblog::Author to have a has_many association called posts (Baseblog::Post does not have a author_id foreign key.)
     # ./spec/models/baseblog/author_spec.rb:6:in `block (3 levels) in <module:Baseblog>'

Finished in 0.29222 seconds (files took 2.9 seconds to load)
6 examples, 1 failure

如何定义 Author 模型和 Post 模型之间的 has_many 和 belongs_to 关联?任何形式的帮助都将受到高度赞赏。

更新

Author 模型的测试规范在我使用dedypuji's answer 修改后现在通过了:

作者模型

module Baseblog
  class Author < ApplicationRecord
    has_many :posts, class_name: 'Baseblog::Post', foreign_key: :baseblog_author_id, dependent: :destroy

    validates :name, presence: true
    validates :address, presence: true
  end
end

后模型

module Baseblog
  class Post < ApplicationRecord
    belongs_to :author, class_name: 'Baseblog::Author', foreign_key: :baseblog_author_id

    validates :name, presence: true
  end
end

但是,Post 模型的规范测试仍然失败:

发布规范

需要'rails_helper'

模块基础博客 RSpec.describe Post, 类型: :model do 描述“协会”做 它 { is_expected.to 属于_to(:author) } 结束

describe 'validations' do
  it { is_expected.to validate_presence_of(:name) }
  it { is_expected.to validate_presence_of(:author_id) }
end

结束 结束

Post 规范的工厂机器人

FactoryBot.define do
  factory :post do
    name { "MyString" }

    association :author
  end
end

但是,当我为 Post 运行规范测试时,我收到以下错误:

Failures:

  1) Baseblog::Post associations is expected to belong to author required: true
     Failure/Error: it { is_expected.to belong_to(:author) }
     
     NoMethodError:
       undefined method `author_id' for #<Baseblog::Post:0x000056397e47dc50>
       Did you mean?  author
                      author=
     # ./spec/models/baseblog/post_spec.rb:6:in `block (3 levels) in <module:Baseblog>'

Baseblog::Post validations is expected to validate that :author_id cannot be empty/falsy
     Failure/Error: it { is_expected.to validate_presence_of(:author_id) }
     
     Shoulda::Matchers::ActiveModel::AllowValueMatcher::AttributeDoesNotExistError:
       The matcher attempted to set :author_id on the Baseblog::Post to
       nil, but that attribute does not exist.
     # ./spec/models/baseblog/post_spec.rb:19:in `block (3 levels) in <module:Baseblog>'

【问题讨论】:

  • 你的架构中有 Baseblog::Post 中的 author_id 吗?
  • 是的。我刚刚将其添加到问题中

标签: ruby-on-rails ruby rails-engines


【解决方案1】:

你可以试试这个吗?

module Baseblog
  class Author < ApplicationRecord
    has_many :posts, class_name: 'Baseblog::Post', foreign_key: :baseblog_author_id, dependent: :destroy

    validates :name, presence: true
    validates :address, presence: true
  end
end
module Baseblog
  class Post < ApplicationRecord
    belongs_to :author, class_name: 'Baseblog::Author', foreign_key: :baseblog_author_id

    validates :name, presence: true
  end
end

【讨论】:

  • 这对我有用。太感谢了。我认为这里需要注意的是,Author 模型和 Post 模型的foreign_key 是相同的。
  • 是的,不过我也遇到了同样的问题,我这样做是因为 Rails 可能必须为模块中的模型指定类名和外键。也许你能找到更好的解决方案
  • 我在测试时遇到了一些其他问题,我已经更新了问题@dedypuji,你能帮忙吗?
  • 如果使用 id 直接分配,则使用 baseblog_author_id 而不是 author_id,如果使用 BaseBlog::Author 实例,则可以使用作者关联进行分配
猜你喜欢
  • 1970-01-01
  • 2015-04-17
  • 1970-01-01
  • 1970-01-01
  • 2013-10-09
  • 1970-01-01
  • 2015-09-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多