简体   繁体   English

向基础模型添加关系/关联模型值

[英]Add Relation / Association model value to Base model

I have two objects, A and B . 我有两个对象AB Each have many of the other, using relationshipA . 每一个都有许多其他relationshipA ,使用的是relationshipA relationshipA has a property propertyA . relationshipA具有属性propertyA Can I merge the properties of relationshipA and either A or B when I perform a fetch? 执行提取时是否可以合并relationshipA的属性以及AB

For example 例如

A.find(params[:id]).relationshipAs

I'd like that to return me Bs , but also append the properties from relationshipA into them, at least when rendering the json. 我想让我返回Bs ,但至少在渲染json时,还要将relationshipA的属性附加到它们中。

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

Assuming B has properties prop1 , prop2 and prop3 and RelationshipA has prop4 , I'd like to get a json response from: 假设B有性质prop1prop2prop3RelationshipAprop4 ,我希望得到一个JSON响应:

render json: A.find(params[:id]).bs

I'd like to expect: 我希望:

[{
    'prop1' : 'value',
    'prop2' : 'value',
    'prop3' : 'value',
    'prop4' : 'value'
}, ...]

Here's a console example: 这是一个控制台示例:

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'>]>

I see 2 questions: 我看到两个问题:

  1. How do I generate custom json 如何生成自定义json
  2. How do I bring back objects to generate the custom json? 如何带回对象以生成自定义json?

Defining a custom json method: 定义自定义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

The question is very abstract. 这个问题非常抽象。 If you can stick with Relationship objects, then that is probably your best bet. 如果您可以坚持使用Relationship对象,那可能是最好的选择。 Using includes will give you a single or 2 queries. 使用includes将给您一个或两个查询。

If you need to have a B with the knowledge of how you brought back B , then you probably want to add attr_accessor :prop4 to B and an "extension" block to Relationship 's has_many clause to set B's :prop4 . 如果你需要有B与你怎么带回来的知识B ,那么你可能要添加attr_accessor :prop4B和“扩展”块Relationshiphas_many条款设置B的:prop4

It seems the best that I can do is a hash of the values, but not through the initial query or any built in functions. 看来,我能做的最好的事情是值的散列,而不是通过初始查询或任何内置函数。 @kbrock has a solid answer, but I prefer the attributes approach. @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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM