Class: Fixation::Fixtures

Inherits:
Object
  • Object
show all
Defined in:
lib/fixation/fixtures.rb

Instance Method Summary collapse

Constructor Details

#initializeFixtures

Returns a new instance of Fixtures.



6
7
8
# File 'lib/fixation/fixtures.rb', line 6

def initialize
  @fixture_tables = {}
end

Instance Method Details

#add_fixture(fixture_for, name, attributes) ⇒ Object



41
42
43
44
45
46
# File 'lib/fixation/fixtures.rb', line 41

def add_fixture(fixture_for, name, attributes)
  raise "Fixtures have already been compiled!  You can only call add_fixture from a file in one of the fixture directories, which is loaded on boot." if baked_fixtures?
  fixture_table = @fixture_tables[fixture_for.to_s] or raise(ArgumentError, "No fixture file for #{fixture_for}") # TODO: consider allowing this
  fixture_table.add_row(name.to_s, attributes.stringify_keys)
  name
end

#apply_fixture_statements(connection) ⇒ Object



71
72
73
74
75
76
77
# File 'lib/fixation/fixtures.rb', line 71

def apply_fixture_statements(connection)
  @statements.each do |table_name, table_statements|
    table_statements.each do |statement|
      connection.execute(statement)
    end
  end
end

#apply_fixtures(connection = ActiveRecord::Base.connection) ⇒ Object



62
63
64
65
66
67
68
69
# File 'lib/fixation/fixtures.rb', line 62

def apply_fixtures(connection = ActiveRecord::Base.connection)
  connection.disable_referential_integrity do
    connection.transaction do
      apply_fixture_statements(connection)
      clear_other_tables(connection) if Fixation.clear_other_tables
    end
  end
end

#bake_fixturesObject



48
49
50
51
52
53
54
55
56
# File 'lib/fixation/fixtures.rb', line 48

def bake_fixtures
  @fixture_ids = {}
  @statements = {}

  @fixture_tables.each do |fixture_name, fixture_table|
    @fixture_ids[fixture_table.fixture_name] = fixture_table.fixture_ids
    @statements[fixture_table.table_name] = fixture_table.statements
  end
end

#baked_fixtures?Boolean

Returns:

  • (Boolean)


58
59
60
# File 'lib/fixation/fixtures.rb', line 58

def baked_fixtures?
  !@fixture_ids.nil? || !@statements.nil?
end

#clear_other_tables(connection) ⇒ Object



79
80
81
82
83
84
# File 'lib/fixation/fixtures.rb', line 79

def clear_other_tables(connection)
  data_sources = connection.respond_to?(:data_sources) ? connection.data_sources : connection.tables
  (data_sources - Fixation.tables_not_to_clear - @statements.keys).each do |table_name|
    connection.execute("DELETE FROM #{connection.quote_table_name table_name}")
  end
end

#compile_fixture_files(connection = ActiveRecord::Base.connection) ⇒ Object



10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/fixation/fixtures.rb', line 10

def compile_fixture_files(connection = ActiveRecord::Base.connection)
  puts "#{Time.now} building fixtures" if Fixation.trace

  @class_names = {}

  @loaded_at = ActiveRecord::Base.default_timezone == :utc ? Time.now.utc : Time.now

  Fixation.paths.each do |path|
    Dir["#{path}/{**,*}/*.yml"].each do |pathname|
      basename = pathname[path.size + 1..-5]
      load_fixture_file(pathname, basename, connection) if ::File.file?(pathname)
    end
  end

  Fixation.paths.each do |path|
    Dir["#{path}/{**,*}/*.rb"].each do |pathname|
      FixtureContent.instance_eval(File.read(pathname)) if ::File.file?(pathname)
    end
  end

  bake_fixtures

  puts "#{Time.now} built fixtures for #{@fixture_ids.size} tables" if Fixation.trace
end

#fixture_methodsObject



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/fixation/fixtures.rb', line 86

def fixture_methods
  fixture_ids = @fixture_ids
  class_names = @class_names

  methods = Module.new do
    def setup_fixtures(config = ActiveRecord::Base)
      if run_in_transaction?
        @@fixated_fixtures_applied ||= false
        unless @@fixated_fixtures_applied
          puts "#{Time.now} applying fixtures" if Fixation.trace
          Fixation.apply_fixtures
          @@fixated_fixtures_applied = true
          puts "#{Time.now} applied fixtures" if Fixation.trace
        end
      else
        @@fixated_fixtures_applied = false
      end
      super
    end

    fixture_ids.each do |fixture_name, fixtures|
      begin
        klass = class_names[fixture_name].constantize
      rescue NameError
        next
      end

      define_method(fixture_name) do |*fixture_names|
        force_reload = fixture_names.pop if fixture_names.last == true || fixture_names.last == :reload

        @fixture_cache[fixture_name] ||= {}

        instances = fixture_names.map do |name|
          id = fixtures[name.to_s]
          raise StandardError, "No fixture named '#{name}' found for fixture set '#{fixture_name}'" if id.nil?

          @fixture_cache[fixture_name].delete(name) if force_reload
          @fixture_cache[fixture_name][name] ||= klass.find(id)
        end

        instances.size == 1 ? instances.first : instances
      end
      private fixture_name

      name_method = :"#{fixture_name.singularize}_fixture_name_for_id"
      define_method(name_method) do |fixture_id|
        fixture_id = fixture_id.to_param
        fixtures.detect do |name, id|
          break name.to_sym if id.to_param == fixture_id
        end or raise ArgumentError, "No fixture with ID #{fixture_id.inspect} in table #{fixture_name}"
      end
      private name_method
    end
  end
end

#load_fixture_file(filename, basename, connection) ⇒ Object



35
36
37
38
39
# File 'lib/fixation/fixtures.rb', line 35

def load_fixture_file(filename, basename, connection)
  fixture_table = FixtureTable.new(filename, basename, connection, @loaded_at)
  @fixture_tables[fixture_table.fixture_name] = fixture_table
  @class_names[fixture_table.fixture_name] = fixture_table.class_name
end