Можете ли вы объяснить, что делает этот фрагмент кода? - PullRequest
1 голос
/ 27 августа 2010

Я только что закончил смотреть эпизод с Railscast # 189 , и он использовал bit_mask для сохранения значения в таблице пользователей.Я пытаюсь реализовать то же самое, но когда я тестирую через 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 ]

3 голосов
/ 27 августа 2010

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

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

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

2 голосов
/ 27 августа 2010

Он использует число как битовое поле.В двоичном коде каждый бит числа представляет флаг.Добавляя 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}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...