通过未保存的子关联访问父级(has_many)

时间:2014-01-28 09:28:20

标签: ruby-on-rails activerecord

我通过与每笔付款相关联的一笔交易付款。交易可以与付款,存款等相关联,因此我需要:通过关系。

付款类:

class Payment < ActiveRecord::Base
  has_many :payment_transactions
  has_many :transactions, :through => :payment_transactions
end

交易类:

class Transaction < ActiveRecord::Base
  has_one :payment_transaction, :inverse_of => :transaction
  has_one :payment, :through => :payment_transaction
end

最后是PaymentTransaction类:

class PaymentTransaction < ActiveRecord::Base
  belongs_to :payment
  belongs_to :transaction
end

将交易添加到付款时,我希望能够从新创建的交易中访问父信息(付款属性):

2.1.0 :001 > p = Payment.new
 => #<Payment id: nil, state: "new", created_at: nil, updated_at: nil>
2.1.0 :002 > p.save
 => true
2.1.0 :003 > p.transactions.build()
 => #<Transaction id: nil, myid: nil, parent_class_is: nil, created_at: nil, updated_at: nil>
2.1.0 :004 > p.transactions.first.payment
 => nil

我正在寻找一种方法来从与支付相关的新创建的交易中获取付款 - 但没有运气。保存付款,但事务仍未提交到数据库。只有在保存付款并存储关联的交易时,我才能访问父对象:

2.1.0 :005 > p.save
2.1.0 :008 > p.reload
2.1.0 :009 > p.transactions.first.payment
=> #<Payment id: 3, state: "new", created_at: "2014-01-28 09:23:13", updated_at: "2014-01-28 09:23:13">

使用:inverse_of是不可能的:通过关联。 :(


编辑1:

尝试通过代理协会访问父级:

应用程序/关切/ transaction_proxy.rb

module TransactionProxy

  private

  def my_owner
    proxy_association.owner
  end

end

付款方式:

has_many :payment_transactions
has_many :transactions, -> { extending TransactionProxy }, :through => :payment_transactions

加载付款:

2.1.0 :006 > p = Payment.first
  Payment Load (0.2ms)  SELECT "payments".* FROM "payments" ORDER BY "payments"."id" ASC LIMIT 1
 => #<Payment id: 1, state: "new", created_at: "2014-01-28 12:31:11", updated_at: "2014-01-28 12:31:11">

设置交易:

2.1.0 :007 > p.transactions.build()
 => #<Transaction id: nil, myid: nil, parent_class_is: nil, created_at: nil, updated_at: nil>

查询交易:

2.1.0 :005 > p.transactions.first
 => #<Transaction id: nil, myid: nil, parent_class_is: nil, created_at: nil, updated_at: nil>

2.1.0 :007 > p.transactions.first.payment
 => nil

并尝试使用代理:

2.1.0 :006 > p.transactions.first.my_owner
NoMethodError: undefined method `my_owner' for #<Transaction:0x00000103e44450>

我认为交易中的.my_owner应该返回该交易的所有者(付款)吗?

1 个答案:

答案 0 :(得分:0)

你的代码让我感到困惑!


<强>多晶型

我认为你会从交易模型的polymorphic association中受益。这样,您的交易就可以属于paymentsdeposits或任何型号

您使用through关系意味着transactions只能与payments 交易&amp;必须先创建付款对象才能关联它们:

class Transaction < ActiveRecord::Base
  belongs_to :transactable, polymorphic: true
end

class Payment < ActiveRecord::Base
  has_many :transactions, as: :transactable
end

class Deposit < ActiveRecord::Base
  has_many :transactions, as: :transactable
end

class Reward < ActiveRecord::Base
  has_many :transactions, as: :transactable
end

Polymorphic Association


<强> Extrabutes

如果您想保留has_many :through关联,可以使用ActiveRecord Association Extensions proxy_association对象来检索所需的数据

我们制作了一个额外的连接表数据的脚本,您将能够适应拉动子对象属性:

#app/models/concerns/image_caption.rb
module ImageCaption

        #Load
        def load
      captions.each do |caption|
              proxy_association.target << caption
      end
        end

        #Private
        private

        #Captions
        def captions
                return_array = []
                through_collection.each_with_index do |through,i|
                        associate = through.send(reflection_name)
                        associate.assign_attributes({caption: items[i]})
                        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(&:caption)
        end

        #Target
        def target_collection
                #load_target
                proxy_association.target
        end

end

#app/models/message.rb
has_many :image_messages
has_many :images, through: :image_messages, extend: ImageCaption

如果您希望我为您修改此代码,请在评论中提问!