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



43
44
45
46
47
48
# File 'lib/fixation/fixtures.rb', line 43

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



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

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



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

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



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

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)


60
61
62
# File 'lib/fixation/fixtures.rb', line 60

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

#clear_other_tables(connection) ⇒ Object



81
82
83
84
85
86
# File 'lib/fixation/fixtures.rb', line 81

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
34
35
# 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|
    Fixation.extensions.each do |extension|
      Dir["#{path}/{**,*}/*#{extension}"].each do |pathname|
        basename = pathname[path.size + 1..-(extension.size + 1)]
        load_fixture_file(pathname, basename, connection) if ::File.file?(pathname)
      end
    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



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
141
142
# File 'lib/fixation/fixtures.rb', line 88

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



37
38
39
40
41
# File 'lib/fixation/fixtures.rb', line 37

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