【问题标题】:Rails 3, has_one / has_many with lambda conditionRails 3,具有 lambda 条件的 has_one / has_many
【发布时间】:2012-11-11 00:00:55
【问题描述】:

这是我的模型:

class User < ActiveRecord::Base
  has_many :bookmarks
end

class Topic < ActiveRecord::Base
  has_many :bookmarks
end

class Bookmark < ActiveRecord::Base
  belongs_to :user
  belongs_to :topic
  attr_accessible :position
  validates_uniqueness_of :user_id, :scope => :topic_id
end

我想获取所有topics,对于current_user,关联的bookmark。提款机,我愿意:

Topic.all.each do |t|
    bookmark = t.bookmarks.where(user_id: current_user.id).last
    puts bookmark.position if bookmark
    puts t.name
end

这很丑陋并且做了太多的数据库查询。我想要这样的东西:

class Topic < ActiveRecord::Base
  has_one :bookmark, :conditions => lambda {|u| "bookmarks.user_id = #{u.id}"}
end

Topic.includes(:bookmark, current_user).all.each do |t| # this must also includes topics without bookmark
    puts t.bookmark.position if t.bookmark
    puts t.name
end

这可能吗?我有其他选择吗?

谢谢!

【问题讨论】:

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


    【解决方案1】:

    *嗯,我不确定我是否理解您的问题,但这可能会对您有所帮助:

    # code
    class Topic < ActiveRecord::Base
      scope :for_user, lambda { |user| includes(:bookmarks).where(bookmarks: { user_id: user.try(:id) || user} ) }
    
    # call
    Topic.for_user(current_user) # => Array of Topics
    

    如您所见,for_user 范围的参数可以是用户对象或用户ID

    希望这会有所帮助!

    类似问题:

    【讨论】:

    • includes 不包括未添加书签的 topics。根据您的想法,我将其更改为joinsscope :for_user, lambda { |user| select('topics.*, bookmarks.position as position).joins("LEFT JOIN bookmarks ON bookmarks.topic_id = topics.id AND bookmarks.user_id = #{user.try(:id) || user}") }。然后在代码中:Topic.for_user(current_user)joins 似乎默认不选择属性。我正在寻找一个更清洁的解决方案,但它确实有效。谢谢你:)
    猜你喜欢
    • 2012-09-18
    • 1970-01-01
    • 2018-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多