Как проверить named_scope, который ссылается на атрибут класса, с помощью musta? - PullRequest
0 голосов
/ 22 января 2009

У меня есть следующие классы ActiveRecord:

class User < ActiveRecord::Base
  cattr_accessor :current_user
  has_many :batch_records
end

class BatchRecord < ActiveRecord::Base
  belongs_to :user

  named_scope :current_user, lambda {
    { :conditions => { :user_id => User.current_user && User.current_user.id } }
  }
end

и я пытаюсь проверить named_scope :current_user с помощью Следует , но следующее не работает.

class BatchRecordTest < ActiveSupport::TestCase
  setup do
    User.current_user = Factory(:user)
  end

  should_have_named_scope :current_user,
                          :conditions => { :assigned_to_id => User.current_user }
end

Причина, по которой это не работает, заключается в том, что вызов User.current_user в методе should_have_named_scope оценивается, когда определяется класс, и я изменяю значение current_user впоследствии в setup блокировать при запуске теста.

Вот что я сделал, чтобы проверить этот named_scope:

class BatchRecordTest < ActiveSupport::TestCase
  context "with User.current_user set" do
    setup do
      mock_user = flexmock('user', :id => 1)
      flexmock(User).should_receive(:current_user).and_return(mock_user)
    end

    should_have_named_scope :current_user,
                            :conditions => { :assigned_to_id => 1 }
  end
end

Итак, как бы вы проверили это, используя Если ?

Ответы [ 2 ]

1 голос
/ 22 января 2009

Я думаю, вы поступаете неправильно. Во-первых, зачем вам использовать именованную область? Разве это просто сделать?

class BatchRecord < ActiveRecord::Base
  belongs_to :user

  def current_user
    self.user.class.current_user
  end
end

В этом случае тестирование будет тривиальным. НО! WTF вы определяете current_user как атрибут класса? Теперь, когда Rails 2.2 является «потокобезопасным», что произойдет, если вы запустите приложение в двух отдельных потоках? Один пользователь войдет в систему, установив current_user для ВСЕХ User экземпляров. Теперь другой пользователь с правами администратора входит в систему и current_user переключается на свой экземпляр. Когда первый пользователь перейдет на следующую страницу, он / она получит доступ к учетной записи других лиц с правами администратора! Шок! Ужас!

В этом случае я рекомендую либо создать новый метод контроллера current_user, который возвращает экземпляр пользователя текущего пользователя. Вы также можете сделать еще один шаг и создать модель оболочки, например:

class CurrentUser

  attr_reader :user, :session

  def initialize(user, session)
    @user, @session = user, session
  end

  def authenticated?
    ...
  end

  def method_missing(*args)
    user.send(*args) if authenticated?
  end

end

О, и, кстати, теперь я снова смотрю на ваш вопрос, возможно, одна из причин, по которой он не работает, состоит в том, что строка User.current_user && User.current_user.id вернет логическое значение, а не целое число, которое вы хотите . РЕДАКТИРОВАТЬ Я идиот.

Именованная область видимости - это абсолютно неправильный способ сделать это. Именованная область действия предназначена для возврата коллекций, а не отдельных записей (что является еще одной причиной, по которой это не удается). Это также делает ненужный вызов БД, в результате чего вам не нужен запрос.

0 голосов
/ 22 января 2009

Я только что понял, что ответ смотрит прямо на меня. Я должен работать с другой стороны ассоциации, которая была бы current_user.batch_records. Затем я просто тестирую named_scope на модели User и все в порядке.

@ Крис Ллойд - Что касается проблемы безопасности потоков, атрибут current_user устанавливается в before_filter в моем ApplicationController, поэтому он изменяется по запросу. Я понимаю, что все еще существует вероятность катастрофы, если я выбрал работу в многопоточной среде (что в настоящее время не так). Это решение, я полагаю, было бы совершенно другой темой.

...