【问题标题】:has_many association after_load type callbackhas_many 关联 after_load 类型回调
【发布时间】:2011-04-23 20:16:23
【问题描述】:

我想记录一组个人之间的交互,每个人都被建模为一条消息,发送者和接收者:

class Message < ActiveRecord::Base
  belongs_to :receiver, :class_name => 'Individual', :foreign_key => 'receiver_id'
  belongs_to :sender, :class_name => 'Individual', :foreign_key => 'sender_id'
end

我想添加一个界面,以便我可以记录从个人的角度发送的消息:

@bob.messages.new(:direction => 'to', :correspondent => @jane)

理想情况下,它的行为与 active_record has_many 关联完全一样。我决定子类化消息模型,旨在创建可以以这种方式响应的东西 - 将方法添加到 Message 类似乎不合适,因为对象需要了解它的“主要个体”(在上面的例子中@bob) 以便知道要创建哪个消息。

class Individual < AcitveRecord::Base
  has_many :received_messages, :class_name => 'Message', :foreign_key => 'receiver_id'
  has_many :sent_messages, :class_name => 'Message', :foreign_key => 'sender_id'

  has_many :messages, :class_name => 'MyMessage',
                  :finder_sql =>'SELECT * FROM messages WHERE receiver_id = #{id} OR sender_id = #{id}',
                  :after_add => :set_user

  def set_user(my_message)
    my_message.principal_user = self
  end

  class MyMessage < Message
    attr_accessor :principal_user  
    def correspondent
      @principal_user == receiver ? sender : receiver
    end

    def direction
      @principal_user == receiver ? "to" : "from"
    end
    ... other methods ...
  end
end

这几乎可以满足我的要求。不幸的是,after_add 回调仅在新对象添加到消息集合时触发,而不是在每个对象第一次加载到关联时触发。

据我发现不存在“after_load”关联回调。有没有其他我可以使用的方法,或者有更好的方法来解决这种情况?

【问题讨论】:

  • 你在用MyMessage 对象做什么?它就像一个留言板,人们可以在其中删除收件箱和发件箱中的内容?
  • 所描述的情况是我能想到的最简单的情况,可以解决问题。我实际上并没有尝试创建消息框。想想看,而不是观察人群并记下他们每次互相发送信息的时间。 MyMessage 对象仅用于为创建 Message 对象提供不同的接口,但它知道它所属的对象之一。
  • 什么时候需要从接收者的角度创建消息?消息在发送时创建。
  • 假设您正在为一位高中老师创建一个应用程序,用于记录孩子们何时互相发送笔记。他们可能不知道便条的内容,但他们可能会看到 Bob 将便条传递给 Jane。其中一项规范可能是您使用语法@bob.messages.new(:direction =&gt; 'to', :correspondent =&gt; @jane) 添加它。

标签: ruby-on-rails ruby-on-rails-3 activerecord associations


【解决方案1】:

对于任何有兴趣的人,最后我深入研究了 ActiveRecord 并想出了以下内容:

 has_many :messages, :class_name => 'MyMessage',
                  :finder_sql =>'SELECT * FROM messages WHERE receiver_id = #{id} OR sender_id = #{id}',
                  :after_add => :set_user do
                    def find_target
                      messages = super
                      messages.each {|m| m.principal_user = proxy_owner}
                      messages
                    end
                  end

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-22
    相关资源
    最近更新 更多