我有两个对象A
和B
。使用relationshipA
,每个都有许多其他的。 relationshipA
有一个属性propertyA
。执行提取时,是否可以合并relationshipA
以及A
或B
的属性?
例如
A.find(params[:id]).relationshipAs
我希望返回给我Bs
,但也会将relationshipA
中的属性附加到其中,至少在渲染json时。
class A < ActiveRecord::Base
has_many :relationship_a
has_many :b, through: :relationship_a
end
class B < ActiveRecord::Base
has_many :relationship_a
has_many :a, through: :relationship_a
end
class RelationshipA < ActiveRecord::Base
belongs_to :A
belongs_to :B
end
假设B有属性prop1
,prop2
和prop3
以及RelationshipA
有prop4
,我想从以下位置获得json响应:
render json: A.find(params[:id]).bs
我希望:
[{
'prop1' : 'value',
'prop2' : 'value',
'prop3' : 'value',
'prop4' : 'value'
}, ...]
这是一个控制台示例:
a1 = A.create
b1 = B.create
b2 = B.create
a1.bs = [b1, b2]
RelationshipA.where(a_id: a1.id).first.prop4 = 'Hello'
RelationshipA.where(a_id: a1.id).last.prop4 = 'There'
*now output all of a1's bs including the relationships' prop4 value*
#<ActiveRecord::Associations::CollectionProxy [#<B id: 1, prop1: nil, prop2: nil, prop3: nil, created_at: "2014-07-09 20:37:12", updated_at: "2014-07-09 20:37:12", prop4: 'Hello'>, #<B id: 2, prop1: nil, prop2: nil, prop3: nil, created_at: "2014-07-09 20:37:12", updated_at: "2014-07-09 20:37:12", prop4: 'There'>]>
答案 0 :(得分:1)
我看到两个问题:
定义自定义json方法:
class A < ActiveRecord::Base
has_many :relationships, :inverse_of :a
has_many :bs, :through => :relationships
end
class B < ActiveRecord::Base
# prop1
has_many :relationships, :inverse_of :b
has_many :as, :through => :relationships
end
class Relationship < ActiveRecord::Base
# prop4
belongs_to :a, inverse_of: :relationships
belongs_to :b, inverse_of: :relationships
def as_json(options: {})
{
prop1: b.prop1,
prop4: prop4
}
end
end
relationships = A.includes(relationships: :b).find(params[:id]).relationships
puts relationships.to_json
这个问题很抽象。如果您可以坚持使用Relationship
个对象,那么这可能是您最好的选择。使用includes
将为您提供一次或两次查询。
如果您需要B
知道您带回B
的方式,那么您可能希望将attr_accessor :prop4
添加到B
和“扩展程序”阻止Relationship
的{{1}}子句设置B has_many
。
答案 1 :(得分:0)
我能做的最好的是值的哈希,但不是通过初始查询或任何内置函数。 @kbrock有一个可靠的答案,但我更喜欢attributes
方法。
class A < ActiveRecord::Base
has_many :relationships, :inverse_of :a
has_many :bs, :through => :relationships
# returns array of hashes, not json string, of all Relationship's and B's attributes
def relationshipValues
# get all of a's relationships, including `b`s with only 2 queries
relationships = Relationship.includes(:b).where(a_id: :id).all
relationshipValues = []
# I'm not sure if this is optimal, so please offer some advice
@relationships.each do |relationship|
relationshipValues << relationship.attributes.merge(relationship.b.attributes)
end
# simple return - is there better way?
relationshipValues
#just for spacing :)
end
end
class B < ActiveRecord::Base
has_many :relationships, :inverse_of :b
has_many :as, :through => :relationships
end
class Relationship < ActiveRecord::Base
belongs_to :a, inverse_of: :relationships
belongs_to :b, inverse_of: :relationships
def to_json
attributes.merge(b.attributes)
end
end