你能解释一下这段代码片段的作用吗?

时间:2010-08-26 20:48:47

标签: ruby-on-rails ruby

我刚刚看完一个railscast episode #189并且正在使用bit_mask在users表中存储一个值。我正在尝试实现同样的事情,但是当我通过irb测试时,我遇到了错误。首先,有人可以解释这实际上是什么。我知道第一行正在做什么,第二行的一部分

ROLES = %w[admin moderator author]

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

def roles
  ROLES.reject { |r| ((roles_mask || 0) & 2**ROLES.index(r)).zero? }
end

在irb中我得到了这个:

irb(main):013:0> ROLES = %w[admin moderator author]
(irb):13: warning: already initialized constant ROLES
=> ["admin", "moderator", "author"]
irb(main):014:0> roles = %w[admin author]
=> ["admin", "author"]
irb(main):015:0> roles_mask = (roles & ROLES).map { |r| 2**ROLES.index(r) }.sum
NoMethodError: undefined method `sum' for [1, 4]:Array

2 个答案:

答案 0 :(得分:3)

它在irb中不起作用的原因是sum是在ActiveSupport中定义的,而不是ruby的标准库。如果你require 'active_support'首先(或只是使用脚本/控制台),它将在irb。

中工作

roles=的作用是根据ROLES数组(item)中角色的顺序将角色数组转换为位掩码,然后将该位掩码保存为role_mask。例如,["admin", "author"]将变为5(二进制为0b101)。不在ROLES中的角色将被忽略(例如["admin", "bla"]["admin"]相同)。

roles的作用是将保存的位掩码转换回角色数组。

答案 1 :(得分:2)

他使用数字作为位字段。在二进制中,数字的每个位代表一个标志。通过添加2 ^ n,您可以设置位n,通过减去2 ^ n就可以清除它(假设它是在第一位设置的。)

Array#sum方法可能特定于Rails,或Ruby 1.9的一部分。它所做的就是获取数组中的每个元素并将它们相加。你可以这样做。

roles_mask = (roles & ROLES).map { |r| 2**ROLES.index(r) }.inject(0){|m,n| m + n}