class Fixtures

def self.cache_fixtures(connection, fixtures_map)

def self.cache_fixtures(connection, fixtures_map)
  cache_for_connection(connection).update(fixtures_map)
end

def self.cache_for_connection(connection)

def self.cache_for_connection(connection)
  @@all_cached_fixtures[connection.object_id] ||= {}
  @@all_cached_fixtures[connection.object_id]
end

def self.cached_fixtures(connection, keys_to_fetch = nil)

def self.cached_fixtures(connection, keys_to_fetch = nil)
  if keys_to_fetch
    fixtures = cache_for_connection(connection).values_at(*keys_to_fetch)
  else
    fixtures = cache_for_connection(connection).values
  end
  fixtures.size > 1 ? fixtures : fixtures.first
end

def self.create_fixtures(fixtures_directory, table_names, class_names = {})

def self.create_fixtures(fixtures_directory, table_names, class_names = {})
  table_names = [table_names].flatten.map { |n| n.to_s }
  connection  = block_given? ? yield : ActiveRecord::Base.connection
  table_names_to_fetch = table_names.reject { |table_name| fixture_is_cached?(connection, table_name) }
  unless table_names_to_fetch.empty?
    ActiveRecord::Base.silence do
      connection.disable_referential_integrity do
        fixtures_map = {}
        fixtures = table_names_to_fetch.map do |table_name|
          fixtures_map[table_name] = Fixtures.new(connection, File.split(table_name.to_s).last, class_names[table_name.to_sym], File.join(fixtures_directory, table_name.to_s))
        end
        all_loaded_fixtures.update(fixtures_map)
        connection.transaction(:requires_new => true) do
          fixtures.reverse.each { |fixture| fixture.delete_existing_fixtures }
          fixtures.each { |fixture| fixture.insert_fixtures }
          # Cap primary key sequences to max(pk).
          if connection.respond_to?(:reset_pk_sequence!)
            table_names.each do |table_name|
              connection.reset_pk_sequence!(table_name)
            end
          end
        end
        cache_fixtures(connection, fixtures_map)
      end
    end
  end
  cached_fixtures(connection, table_names)
end

def self.fixture_is_cached?(connection, table_name)

def self.fixture_is_cached?(connection, table_name)
  cache_for_connection(connection)[table_name]
end

def self.identify(label)

Identifiers are positive integers less than 2^32.
Returns a consistent, platform-independent identifier for +label+.
def self.identify(label)
  Zlib.crc32(label.to_s) % MAX_ID
end

def self.instantiate_all_loaded_fixtures(object, load_instances = true)

def self.instantiate_all_loaded_fixtures(object, load_instances = true)
  all_loaded_fixtures.each do |table_name, fixtures|
    Fixtures.instantiate_fixtures(object, table_name, fixtures, load_instances)
  end
end

def self.instantiate_fixtures(object, table_name, fixtures, load_instances = true)

def self.instantiate_fixtures(object, table_name, fixtures, load_instances = true)
  object.instance_variable_set "@#{table_name.to_s.gsub('.','_')}", fixtures
  if load_instances
    ActiveRecord::Base.silence do
      fixtures.each do |name, fixture|
        begin
          object.instance_variable_set "@#{name}", fixture.find
        rescue FixtureClassNotFound
          nil
        end
      end
    end
  end
end

def self.reset_cache(connection = nil)

def self.reset_cache(connection = nil)
  connection ||= ActiveRecord::Base.connection
  @@all_cached_fixtures[connection.object_id] = {}
end

def column_names

def column_names
  @column_names ||= @connection.columns(@table_name).collect(&:name)
end

def csv_file_path

def csv_file_path
  @fixture_path + ".csv"
end

def delete_existing_fixtures

def delete_existing_fixtures
  @connection.delete "DELETE FROM #{@connection.quote_table_name(table_name)}", 'Fixture Delete'
end

def erb_render(fixture_content)

def erb_render(fixture_content)
  ERB.new(fixture_content).result
end

def has_primary_key_column?

def has_primary_key_column?
  @has_primary_key_column ||= model_class && primary_key_name &&
    model_class.columns.find { |c| c.name == primary_key_name }
end

def inheritance_column_name

def inheritance_column_name
  @inheritance_column_name ||= model_class && model_class.inheritance_column
end

def initialize(connection, table_name, class_name, fixture_path, file_filter = DEFAULT_FILTER_RE)

def initialize(connection, table_name, class_name, fixture_path, file_filter = DEFAULT_FILTER_RE)
  @connection, @table_name, @fixture_path, @file_filter = connection, table_name, fixture_path, file_filter
  @name = table_name # preserve fixture base name
  @class_name = class_name ||
                (ActiveRecord::Base.pluralize_table_names ? @table_name.singularize.camelize : @table_name.camelize)
  @table_name = "#{ActiveRecord::Base.table_name_prefix}#{@table_name}#{ActiveRecord::Base.table_name_suffix}"
  @table_name = class_name.table_name if class_name.respond_to?(:table_name)
  @connection = class_name.connection if class_name.respond_to?(:connection)
  read_fixture_files
end

def insert_fixtures

def insert_fixtures
  now = ActiveRecord::Base.default_timezone == :utc ? Time.now.utc : Time.now
  now = now.to_s(:db)
  # allow a standard key to be used for doing defaults in YAML
  if is_a?(Hash)
    delete('DEFAULTS')
  else
    delete(assoc('DEFAULTS'))
  end
  # track any join tables we need to insert later
  habtm_fixtures = Hash.new do |h, habtm|
    h[habtm] = HabtmFixtures.new(@connection, habtm.options[:join_table], nil, nil)
  end
  each do |label, fixture|
    row = fixture.to_hash
    if model_class && model_class < ActiveRecord::Base
      # fill in timestamp columns if they aren't specified and the model is set to record_timestamps
      if model_class.record_timestamps
        timestamp_column_names.each do |name|
          row[name] = now unless row.key?(name)
        end
      end
      # interpolate the fixture label
      row.each do |key, value|
        row[key] = label if value == "$LABEL"
      end
      # generate a primary key if necessary
      if has_primary_key_column? && !row.include?(primary_key_name)
        row[primary_key_name] = Fixtures.identify(label)
      end
      # If STI is used, find the correct subclass for association reflection
      reflection_class =
        if row.include?(inheritance_column_name)
          row[inheritance_column_name].constantize rescue model_class
        else
          model_class
        end
      reflection_class.reflect_on_all_associations.each do |association|
        case association.macro
        when :belongs_to
          # Do not replace association name with association foreign key if they are named the same
          fk_name = (association.options[:foreign_key] || "#{association.name}_id").to_s
          if association.name.to_s != fk_name && value = row.delete(association.name.to_s)
            if association.options[:polymorphic]
              if value.sub!(/\s*\(([^\)]*)\)\s*$/, "")
                target_type = $1
                target_type_name = (association.options[:foreign_type] || "#{association.name}_type").to_s
                # support polymorphic belongs_to as "label (Type)"
                row[target_type_name] = target_type
              end
            end
            row[fk_name] = Fixtures.identify(value)
          end
        when :has_and_belongs_to_many
          if (targets = row.delete(association.name.to_s))
            targets = targets.is_a?(Array) ? targets : targets.split(/\s*,\s*/)
            join_fixtures = habtm_fixtures[association]
            targets.each do |target|
              join_fixtures["#{label}_#{target}"] = Fixture.new(
                { association.primary_key_name => row[primary_key_name],
                  association.association_foreign_key => Fixtures.identify(target) },
                nil, @connection)
            end
          end
        end
      end
    end
    @connection.insert_fixture(fixture, @table_name)
  end
  # insert any HABTM join tables we discovered
  habtm_fixtures.values.each do |fixture|
    fixture.delete_existing_fixtures
    fixture.insert_fixtures
  end
end

def model_class

def model_class
  unless defined?(@model_class)
    @model_class =
      if @class_name.nil? || @class_name.is_a?(Class)
        @class_name
      else
        @class_name.constantize rescue nil
      end
  end
  @model_class
end

def parse_yaml_string(fixture_content)

def parse_yaml_string(fixture_content)
  YAML::load(erb_render(fixture_content))
rescue => error
  raise Fixture::FormatError, "a YAML error occurred parsing #{yaml_file_path}. Please note that YAML must be consistently indented using spaces. Tabs are not allowed. Please have a look at http://www.yaml.org/faq.html\nThe exact error was:\n  #{error.class}: #{error}"
end

def primary_key_name

def primary_key_name
  @primary_key_name ||= model_class && model_class.primary_key
end

def read_csv_fixture_files

def read_csv_fixture_files
  reader = CSV.parse(erb_render(IO.read(csv_file_path)))
  header = reader.shift
  i = 0
  reader.each do |row|
    data = {}
    row.each_with_index { |cell, j| data[header[j].to_s.strip] = cell.to_s.strip }
    self["#{@class_name.to_s.underscore}_#{i+=1}"] = Fixture.new(data, model_class, @connection)
  end
end

def read_fixture_files

def read_fixture_files
  if File.file?(yaml_file_path)
    read_yaml_fixture_files
  elsif File.file?(csv_file_path)
    read_csv_fixture_files
  end
end

def read_yaml_fixture_files

def read_yaml_fixture_files
  yaml_string = ""
  Dir["#{@fixture_path}/**/*.yml"].select { |f| test(?f, f) }.each do |subfixture_path|
    yaml_string << IO.read(subfixture_path)
  end
  yaml_string << IO.read(yaml_file_path)
  if yaml = parse_yaml_string(yaml_string)
    # If the file is an ordered map, extract its children.
    yaml_value =
      if yaml.respond_to?(:type_id) && yaml.respond_to?(:value)
        yaml.value
      else
        [yaml]
      end
    yaml_value.each do |fixture|
      raise Fixture::FormatError, "Bad data for #{@class_name} fixture named #{fixture}" unless fixture.respond_to?(:each)
      fixture.each do |name, data|
        unless data
          raise Fixture::FormatError, "Bad data for #{@class_name} fixture named #{name} (nil)"
        end
        self[name] = Fixture.new(data, model_class, @connection)
      end
    end
  end
end

def timestamp_column_names

def timestamp_column_names
  @timestamp_column_names ||= %w(created_at created_on updated_at updated_on).select do |name|
    column_names.include?(name)
  end
end

def yaml_file_path

def yaml_file_path
  "#{@fixture_path}.yml"
end

def yaml_fixtures_key(path)

def yaml_fixtures_key(path)
  File.basename(@fixture_path).split(".").first
end