Ответ 1
Ahhh старый добрый вопрос how do I access my extra join table attributes
. Борясь с этим за МЕСЯЦ, пока мы не придумали решение
-
Расширения ассоциации ActiveRecord
Проблема заключается в том, что Rails просто использует foreign_keys
в вашей таблице соединений для загрузки необходимых вам ассоциативных данных. Если вы действительно не загружаете модель соединения напрямую, она не даст вам доступ к атрибутам соединения
Некоторые подкасты ведут нас к ActiveRecord Association Extensions
- способу доступа к промежуточным данным между различными ассоциациями ActiveRecord (с использованием коллекции под названием proxy_association
). Это позволит вам получить доступ к дополнительным атрибутам из модели объединения, добавив их к вашей "оригинальной" модели:
#app/models/ingredient.rb
class Ingredient < ActiveRecord::Base
attr_accessor :amount #-> need a setter/getter
end
#app/models/meal.rb
class Meal < ActiveRecord::Base
has_many :meal_ingredients
has_many :ingredients, through: :meal_ingredients, extend: IngredientAmount
end
#app/models/concerns/ingerdient_amount.rb
module IngredientAmount
#Load
def load
amounts.each do |amount|
proxy_association.target << amount
end
end
#Private
private
#Amounts
def amounts
return_array = []
through_collection.each_with_index do |through,i|
associate = through.send(reflection_name)
associate.assign_attributes({amount: items[i]}) if items[i].present?
return_array.concat Array.new(1).fill( associate )
end
return_array
end
#######################
# Variables #
#######################
#Association
def reflection_name
proxy_association.source_reflection.name
end
#Foreign Key
def through_source_key
proxy_association.reflection.source_reflection.foreign_key
end
#Primary Key
def through_primary_key
proxy_association.reflection.through_reflection.active_record_primary_key
end
#Through Name
def through_name
proxy_association.reflection.through_reflection.name
end
#Through
def through_collection
proxy_association.owner.send through_name
end
#Captions
def items
through_collection.map(&:amount)
end
#Target
def target_collection
#load_target
proxy_association.target
end
end
Теперь это должно добавить атрибут amount
к вашим объектам ingredient
, что позволит вам выполнить:
@meal = Meal.find 1
@meal.ingredients.each do |ingredient|
ingredient.amount
end