2010-08-26 2 views
1

Я только что закончил просмотр railscast episode #189, и он использовал бит_маску для сохранения значения в таблице 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 
+0

'Enumerable # sum' - это добавление Rails, определенное в' rails/activesupport/lib/active_support/core_ext/enumerable.rb' –

ответ

2

Он использует номер в качестве битового поля. В двоичном формате каждый бит числа представляет собой флаг. Добавив 2^n, вы можете установить бит n, вычитая 2^n, вы можете очистить его (при условии, что он был установлен в первую очередь).

Метод сумм Array # может быть специфичен для Rails или части Ruby 1.9. Все, что он делает, - это взять каждый элемент в массиве и добавить его. Вы можете сделать это таким образом.

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

Причина, по которой он не работает в IRB, что sum определяется в ActiveSupport, не стандартная библиотека рубина. Если сначала вы используете require 'active_support' (или просто используете скрипт/консоль), он будет работать в irb.

Что roles= делает это превращает массив ролей в битовую маску в соответствии с порядком ролей в ROLES массива (пункт), а затем сохраняет эту битовую маску, как role_mask. Например, ["admin", "author"] будет преобразован в 5 (что равно 0b101 в двоичном формате). Роли, которые не находятся в ROLES, будут игнорироваться (например, - это то же самое, что и ["admin"]).

Что делает roles, это превращает сохраненную битмаску в массив ролей.

+0

ActiveSupport добавляет #sum к классу Enumerable: http://apidock.com/rails/ перечислимая/сумма – lsdr