在 Rails 中通过 has_many 添加附加属性

Posted

技术标签:

【中文标题】在 Rails 中通过 has_many 添加附加属性【英文标题】:Add additional attribute on a has_many through in Rails 【发布时间】:2020-10-20 19:51:48 【问题描述】:

我已经建立了以下关联:

class BookLaunch < ApplicationRecord
  has_many :book_launch_locations, dependent: :destroy
  has_many :stores, through: :book_launch_locations
    
....

class Store < ApplicationRecord

  has_many :book_launch_locations
  has_many :book_launch, through: :book_launch_locations

....

class BookLaunchLocation < ApplicationRecord
  belongs_to :book_launch, :touch => true
  belongs_to :store
end

BookLaunchLocation 有一个名为book_price 的属性。

  create_table "book_launch_locations", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t|
    t.integer "book_launch_id", null: false
    t.integer "store_id", null: false
    t.integer "book_price", default: 1, null: false
    ...
    t.index ["book_launch_id", "store_id"], name: "pair_uniqueness", unique: true
    t.index ["book_launch_id"], name: "index_book_launch_locations_on_book_launch_id"
    t.index ["store_id"], name: "index_book_launch_locations_on_store_id"
  end 

我想将 book_price 添加到 BookLaunch 模型中的商店,以便当我调用 @book_launch.stores,它将具有商店的所有属性+book_price属性。

这可能吗?

我是这样使用 fastJsonApi 调用它的:

    options = 
      include: [:book_launch, :'book_launch.properties']
    json = Api::launchSummarySerializer.new(summaryData, options).serialized_json

    render json: json

【问题讨论】:

【参考方案1】:

如果您想创建一个包含多于两个外键列的连接模型行,您需要显式地创建它,而不是隐式地

store = Store.first
book_launch = BookLaunch.first

BookLaunchLocation.create(
  store: store,
  book_launch: book_launch,
  price: 999
)

# or
store.book_launch_locations.create(
  book_launch: book_launch,
  price: 999
)

# or
book_launch.book_launch_locations.create(
  store: store,
  price: 999
)

隐式创建连接模型行是通过间接关联创建它:

Store.first.book_launches.create!(attributes)
BookLaunch.first.stores.create!(attributes)

【讨论】:

抱歉,我真的很讨厌。我只有一个控制器,它找到一个特定的 book_launch 并返回 book_launch.stores。我只想在返回 book_launch.stores 时包含 book_price 属性。你是说这会通过我创建它的方式来解决? 您确实是错误地解决了问题。您想要做的是遍历 book_launch_locations 关联。 book_launch.book_launch_locations.each |bll| puts "#bll.store.name: bll.price" 。如果你找到一个更好的名字,这段代码会少很多尴尬。 我刚刚用我的调用方式更新了我的代码。是的,名字不好。所以听起来我不能将商店与 book_launch_locations 中的属性价格结合起来。我必须打两个单独的电话

以上是关于在 Rails 中通过 has_many 添加附加属性的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Ruby on Rails 中通过关联订购 has_many?

在rails中相同模型的新视图中附加表单部分

如何将记录添加到has_many:通过rails中的关联

Rails has_many :通过简单形式的嵌套形式

在 ruby​​ on rails 3 中通过电子邮件创建订阅

rails内的class关于添加了has_many或者belongs_to后如何动态添加一些额外的方法 ?