Статические локальные переменные для методов в Ruby? - PullRequest
6 голосов
/ 24 августа 2011

У меня есть это:

def valid_attributes
  { :email => "some_#{rand(9999)}@thing.com" }
end

Для тестирования Rspec, верно? Но я бы хотел сделать что-то вроде этого:

def valid_attributes
  static user_id = 0
  user_id += 1
  { :email => "some_#{user_id}@thing.com" }
end

Я не хочу, чтобы user_id был доступен из любого места, кроме этого метода, это возможно с Ruby?

Ответы [ 5 ]

8 голосов
/ 24 августа 2011

Это закрытый случай.Попробуйте это

lambda {
  user_id = 0

  self.class.send(:define_method, :valid_attributes) do
    user_id += 1
    { :email => "some_#{user_id}@thing.com" }
  end

}.call

Упаковка всего в лямбду позволяет переменным, определенным в лямбде, существовать только в области видимости.Вы также можете добавить другие методы.Удачи!

6 голосов
/ 24 августа 2011

Этот ответ немного шире, чем ваш вопрос, но я думаю, что он лежит в основе того, что вы пытаетесь сделать, и будет самым легким и удобным в обслуживании.

Я думаю, что вы действительно ищете здесь фабрики. Попробуйте использовать что-то вроде factory_girl , что значительно упростит тестирование.

Во-первых, вы должны настроить фабрику для создания любого типа объекта, который вы тестируете, и использовать последовательность для атрибута email:

FactoryGirl.define do
  factory :model do
    sequence(:email) {|n| "person#{n}@example.com" }
    # include whatever else is required to make your model valid
  end
end

Тогда, когда вам нужны действительные атрибуты, вы можете использовать

Factory.attributes_for(:model)

Вы также можете использовать Factory.create и Factory.build для создания сохраненных и несохраненных экземпляров модели.

В документе Начало работы содержится объяснение гораздо большего количества функций, а также инструкции по добавлению фабрик в ваш проект.

5 голосов
/ 24 августа 2011

Вы можете использовать закрытие:

def validator_factory
  user_id = 0
  lambda do
    user_id += 1
    { :email => "some_#{user_id}@thing.com" }
  end
end

valid_attributes = validator_factory

valid_attributes.call  #=>  {:email=>"some_1@thing.com"}
valid_attributes.call  #=>  {:email=>"some_2@thing.com"}

Таким образом, user_id не будет доступен снаружи.

4 голосов
/ 24 августа 2011

Я бы использовал переменную экземпляра:

def valid_attributes
  @user_id ||= 0
  @user_id += 1
  { :email => "some_#{@user_id}@thing.com" }
end
0 голосов
/ 24 августа 2011

Единственными переменными, которые есть в Ruby, являются локальные переменные, переменные экземпляра, переменные класса и глобальные переменные. Ни один из них не подходит для того, что вы ищете.

Что вам, вероятно, понадобится, это синглтон, в котором хранится идентификатор_пользователя и каждый раз выдается новый идентификационный номер. В противном случае ваш код не будет потокобезопасным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...