将关系/关联模型值添加到基础模型

时间:2014-07-09 18:47:57

标签: ruby-on-rails json ruby-on-rails-4 associations

我有两个对象AB。使用relationshipA,每个都有许多其他的。 relationshipA有一个属性propertyA。执行提取时,是否可以合并relationshipA以及AB的属性?

例如

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有属性prop1prop2prop3以及RelationshipAprop4,我想从以下位置获得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'>]>

2 个答案:

答案 0 :(得分:1)

我看到两个问题:

  1. 如何生成自定义json
  2. 如何恢复对象以生成自定义json?
  3. 定义自定义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