2016-01-27 2 views
1

Я использую ActiveRecord с Sinatra вместо Rails, и я хочу использовать приборы в своих тестах. Документация ActiveRecord's FixtureSet говорит, что вы должны использовать fixture_path сказать ему, где арматура файлы:Конфигурирование fixture_path в тестах ActiveRecord

помещен в каталоге, назначенный ActiveSupport :: TestCase.fixture_path = (путь)

Как может Я пишу в эту настройку? Я пробовал @fixture_path и @@fixture_path, но оба они оставили значение nil, когда FixtureSet попытался его прочитать.

Вот единственное, что я мог работать, но это не может быть прав:

# test_helper.rb 
require_relative '../app' 
require 'minitest/autorun' 
require 'active_record' 

ActiveRecord::Base.establish_connection(:test) 

#Set up fixtures and such 
class ActiveSupport::TestCase 
    include ActiveRecord::TestFixtures 
    include ActiveRecord::TestFixtures::ClassMethods 

    class << self 
    def fixtures(*fixture_set_names) 
     self.fixture_path = 'test/fixtures' 
     super *fixture_set_names 
    end 
    end 

    self.use_transactional_fixtures = true 
    self.use_instantiated_fixtures = false 
end 

Полный исходный код размещен в small demo project для ActiveRecord и Синатры.

ответ

2

Я попытался оставить это как комментарий к вашему ответу, но он слишком долго, поэтому я подумал, что могу, как сказать, ответить.

Причина @fixture_path и @@fixture_path не работает, что fixture_path является ActiveSupport class attribute, который, как Руби attr_accessor за исключением он определен как метод одноплодной на классе. Вы можете увидеть, где атрибут fixture_path определен с помощью class_attribute :fixture_path в ActiveRecord::TestFixtures module source.

Атрибуты класса являются частью ActiveSupport и не являются родными для Ruby. Подробнее о них вы можете узнать в справочнике Rails и в API docs и посмотреть, как работает class_attributein the Rails source. Как видно, значение хранится в переменной экземпляра "@#{name}" (например, @fixture_path), но это происходит внутри метода singleton, что означает, что это переменная экземпляра в классе singleton, и вы можете получить доступ к ней только из одного класса.

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

Как вы обнаружили, вам нужно использовать self.fixture_path = вместо fixture_path =, потому что в последнем случае Ruby предполагает, что вы хотите назначить локальную переменную.

+0

Спасибо за объяснение. Я заметил «class_attribute», но не собрал все это вместе. –

2

Я не могу поверить, что не видел этого, но я этого не делал. Мне пришлось использовать self, точно так же, как настройки для транзакционных светильников и экземпляров.

# test_helper.rb 
require_relative '../app' 
require 'minitest/autorun' 
require 'active_record' 

ActiveRecord::Base.establish_connection(:test) 

#Set up fixtures and such 
class ActiveSupport::TestCase 
    include ActiveRecord::TestFixtures 
    include ActiveRecord::TestFixtures::ClassMethods 

    self.fixture_path = 'test/fixtures' 
    self.use_transactional_fixtures = true 
    self.use_instantiated_fixtures = false 
end 

Уловка понимание смысла self в определении класса; это относится к классу, а не к экземпляру класса. Я предполагаю, что когда я перехватываю обезьяны ActiveSupport::TestCase, это единственный способ установить переменную класса. По какой-то причине @fixture_path и @@fixture_path не работают.

Смежные вопросы