Ruby on rails 如何访问ActiveRecord关联方法内部的原始模型

Ruby on rails 如何访问ActiveRecord关联方法内部的原始模型,ruby-on-rails,ruby,ruby-on-rails-3,activerecord,associations,Ruby On Rails,Ruby,Ruby On Rails 3,Activerecord,Associations,我一直在使用ActiveRecord关联方法(如本文中所述)来执行一些更复杂的二级关联,同时最小化查询计数。例如,我使用以下关联从用户关注的每个人中提取所有活动(follow是一个仅包含用户标识和跟随用户标识的模型): 然而,这a)感觉非常粗糙,b)在没有任何follow记录时引发异常(新用户总是这样)。如何获取用户ID?如中所示,您可以使用&操作符合并两个关系,因此类似的操作应该可以: @followed_activities ||= Activity

我一直在使用ActiveRecord关联方法(如本文中所述)来执行一些更复杂的二级关联,同时最小化查询计数。例如,我使用以下关联从用户关注的每个人中提取所有活动(follow是一个仅包含用户标识和跟随用户标识的模型):

然而,这a)感觉非常粗糙,b)在没有任何follow记录时引发异常(新用户总是这样)。如何获取用户ID?

如中所示,您可以使用
&
操作符合并两个关系,因此类似的操作应该可以:

@followed_activities    ||= Activity
                             .includes(:user, :comments, :comment_users)
                             .where(:user_id.in => (self.collect {|e| e.followed_user_id})
@current_users_activity ||= Activity
                             .includes(:user, :comments, :comment_users)
                             .where(:user_id.in => [self.first.user_id] )
@all_activities         ||= (@followed_activities & @current_users_activity).order('activities.created_at DESC')
编辑:

注意:在rails 3.1中,
操作符已被弃用,请改用
关系#合并

做了一些有趣的研究。这绝对不是“ruby 101”

实际上,代码中的
self
确实指的是
User
对象与其关联的
Follow
记录之间的关系。当您像这样扩展一个关联时,您就扩展了代理(正如我几乎不理解的那样,块是针对代理类的
instance\u eval

在rails>=3.1中,有一种方法可以在块中获取用户id(请参阅“关联扩展”一节):

因此,您应该能够做到:

class User < ActiveRecord::Base

  has_many :follows do

    def activities( reload = false )
      @followed_activities = nil if reload
      @followed_activities ||= begin
        Activity
          .includes( :user, :comments, :comment_users )
          .where( :user_id.in => [proxy_association.owner.id, *map( &:followed_user_id ) ])
          .order( 'activities.created_at DESC' )
      end
    end

  end

end
class用户[proxy\u association.owner.id,*map(&:followed\u user\u id)])
.order('activities.created_at DESC')
结束
结束
结束
结束

为了给予应有的赞扬,我在pragpub.com.出售的“Advanced Rails Recipes”中发现了这个特别的方法,它看起来很漂亮。今晚我会试试的,让你知道。很抱歉耽搁了这么久,我有其他事情要做。当我使用&(用于合并的别名)时,它会添加两个关系中的条件。例如,如果第一个关系在(2)中包含WHERE
activities
user\u id
=1,第二个关系在(2)中包含WHERE
activities
user\u id
,那么新的sql在(2)中是WHERE
activities
activities
user\u id这将返回零结果。如何将它们合并为“或”而不是“和”?这也不能回答原始问题,因为self.first.user_id将在没有后续内容的情况下引发异常,这是我的原始问题。抱歉,读得太快了。1) 试着在两个陈述中使用一个“IN”子句,它们应该适当地合并2)对这个主题做了研究,学到了很多有趣的东西,相应地编辑了我的答案。谢谢你带来的乐趣!感谢您提供有效的解决方案和匹配的文档!实际的方法是proxy_association,而不是proxy_association。除此之外,它工作得很漂亮!还好我刚升级到3.1.3:)
@followed_activities    ||= Activity
                             .includes(:user, :comments, :comment_users)
                             .where(:user_id.in => (self.collect {|e| e.followed_user_id})
@current_users_activity ||= Activity
                             .includes(:user, :comments, :comment_users)
                             .where(:user_id.in => [self.first.user_id] )
@all_activities         ||= (@followed_activities & @current_users_activity).order('activities.created_at DESC')
proxy_association.owner.id
class User < ActiveRecord::Base

  has_many :follows do

    def activities( reload = false )
      @followed_activities = nil if reload
      @followed_activities ||= begin
        Activity
          .includes( :user, :comments, :comment_users )
          .where( :user_id.in => [proxy_association.owner.id, *map( &:followed_user_id ) ])
          .order( 'activities.created_at DESC' )
      end
    end

  end

end