【问题标题】:Add Relation / Association model value to Base model将关系/关联模型值添加到基本模型
【发布时间】:2014-07-09 18:47:56
【问题描述】:

我有两个对象,AB。每个都有很多其他的,使用relationshipArelationshipA 有一个属性 propertyA。我可以在执行提取时合并relationshipAAB 的属性吗?

例如

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 具有属性 prop1prop2prop3RelationshipA 具有 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'>]>

【问题讨论】:

  • 如果我对您的理解正确,我认为您需要根据id 查询A,然后将includes(:b) 添加到调用中,以便包含所有Bs。所以A.includes(:b).find(params[:id])
  • @CWitty 我需要能够根据 id 找到 A。然后我需要使用RelationshipA 获取与A 关联的所有Bs。但是,这只会返回一个Bs 数组,但我需要一个包含BRelationshipAs 值的哈希数组。
  • 结帐guides.rubyonrails.org/… 可能会有所帮助。我推荐的建议应该包括A的A对象和B对象。
  • 在您的控制台示例中,我认为您仍然需要在 a1.bs = [b1, b2] 之后调用 a1.save

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


【解决方案1】:

我看到 2 个问题:

  1. 如何生成自定义 json
  2. 如何带回对象以生成自定义 json?

定义一个自定义的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 会给你一个或两个查询。

如果您需要知道如何带回BB,那么您可能需要将attr_accessor :prop4 添加到B,并将“扩展”块添加到Relationship 的@ 987654329@子句设置B的:prop4

【讨论】:

  • 我用控制台示例更新了我的问题。希望它可以帮助澄清。我尝试了您的两个示例,但都没有帮助。
【解决方案2】:

似乎我能做的最好的事情是对值进行哈希处理,但不是通过初始查询或任何内置函数。 @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

【讨论】:

    猜你喜欢
    • 2013-03-01
    • 2016-10-22
    • 2021-08-02
    • 2017-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多