开发者

Mongoid Syntax Question

In episode 189 of Railscasts, there is a named scope in the User model which is as follows:

field :roles_mask,      :type => Integer
ROLES = %w[admin moderator author]

named_scope :with_role, lambda { |role| {:conditions => "roles_mask & #{2**ROLES.index(role.to_s)} > 0"} }

 # roles related
 def roles=(roles)
  self.roles_mask = (roles & ROLES).map { |r| 2**ROLES.index(r) }.sum
 end

 def role开发者_如何转开发s
   ROLES.reject { |r| ((roles_mask || 0) & 2**ROLES.index(r)).zero? }
 end

 def role_symbols
  roles.map(&:to_sym)
 end

How would one get it to work on Mongoid as I tried the a number of options and could not get it to work?


That episode of Railscasts was really designed for databases that don't support arrays as native types (which Mongoid does). Then you could just create a scope which uses one of the array query criteria.

For example:

class User
  include Mongoid::Document

  field :email
  field :roles, :type => Array

  ROLES = %w[admin moderator author]

  class << self
    def with_role(*args)
      any_in(:roles => args)
    end
  end
end

This example would allow you to pass in either a single role User.with_role("admin") or an array of roles User.with_role("moderator", "author"), with the latter returning users who are either moderators or authors.


You can use the native map reduce mongoDB machanism which is exposed through mongoid using for_js method http://www.rubydoc.info/github/mongoid/mongoid/Mongoid/Criteria:for_js

ROLES.each_with_index do |role, role_index|
  scope "#{role.to_s.pluralize}", -> { self.for_js("(this.roles_mask & (1 << role_val)) > 0", role_val: role_index) }
end

This will give scopes in the form of:

User.admins
User.moderators
User.authors
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜