映射表的rails范围

时间:2013-10-16 16:10:42

标签: mysql ruby-on-rails scopes

我有以下型号:

class Message < ActiveRecord::Base

  has_many :read_messages

   module Scopes
    def by_read_status(read_status, user_id)
      case read_status
        when 'Unread'

        when 'Read'
          joins(:read_messages).where(:read_messages => {:read => true, :admin_user_id => user_id})
        else
          where('1 = 1') # no scope necessary

      end
    end
  end
  extend Scopes

end

和...

class ReadMessage < ActiveRecord::Base

  has_many :admin_users
  has_many :messages

end

我有一个名为'mark_as_read'的控制器方法用于消息。它只是创建一个带有该消息ID的新read_message记录,以及标记为已读的人的admin用户ID。由于消息是全局的,我希望系统的每个用户能够单独管理读取状态(这就是我在那里有额外层的原因)。因此,您可以通过我的范围看到,by_read_status('Read',user_id)将返回所有记录,其中它找到一个读取为true的映射记录。问题是,我该怎么做? (返回找不到地图记录的所有记录,或者地图记录:read设置为false)?

我正在使用这样的范围:

@search = Message.search(params[:q])
messages = @search.result.accessible_by(current_ability)
messages = messages.by_company(session[:company_filter]) if session[:company_filter] && session[:company_filter] > 0
messages = messages.by_campaign(session[:campaign_filter]) if session[:campaign_filter] && session[:campaign_filter] > 0
read_filter = params[:read].blank? ? 'Unread' : params[:read]
messages = messages.by_read_status(read_filter, current_admin_user.id)
messages = messages.page(params[:page]).per(20)
@messages = MessageDecorator.new(messages)

所以你可以看到我的范围中间,我有了by_read_status。如果我返回一个数组,或者除了一个范围对象之外的东西,它将会引发一个拟合。任何人都可以帮我弄清楚如何做我的范围的'未读'部分?

谢谢!

已编辑的答案

exclude = Message.by_read_status('Read', user_id).map(&:id)
exclude = [0] unless exclude.size > 0

where("id not in (?)", exclude)

1 个答案:

答案 0 :(得分:1)

where("id not in (?)", by_read_status('Read', user_id))