Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Ticket #1911: more_flexible_fixture_architecture-2.patch

File more_flexible_fixture_architecture-2.patch, 22.4 kB (added by duane.johnson@gmail.com, 3 years ago)

This patch makes a more intelligent assumption about fixtures: that the file names are almost always the same as the group names. It also uses the model to guess the table name, rather than relying solely on inflection.

  • test/fixtures_test.rb

    old new  
    6868    end 
    6969  end 
    7070 
     71  def test_fixtures_not_found 
     72    assert_raise(Fixture::FixtureError) { 
     73      Fixtures.new(nil, File.join(File.dirname(__FILE__), 'fixtures'), FixtureGroup.new("bad_extension")) 
     74    } 
     75  end 
     76 
    7177  def test_deprecated_yaml_extension 
    7278    assert_raise(Fixture::FormatError) { 
    73       Fixtures.new(nil, 'bad_extension', File.join(File.dirname(__FILE__), 'fixtures')) 
     79      Fixtures.new(nil, File.join(File.dirname(__FILE__), 'fixtures', 'bad_fixtures'), FixtureGroup.new("deprecated")) 
    7480    } 
    7581  end 
    7682 
     
    101107  end 
    102108 
    103109  def test_empty_yaml_fixture 
    104     assert_not_nil Fixtures.new( Account.connection, "accounts", File.dirname(__FILE__) + "/fixtures/naked/yml/accounts"
     110    assert_not_nil Fixtures.new( Account.connection, File.dirname(__FILE__) + "/fixtures/naked/yml/", FixtureGroup.new("accounts")
    105111  end 
    106112 
    107113  def test_empty_yaml_fixture_with_a_comment_in_it 
    108     assert_not_nil Fixtures.new( Account.connection, "companies", File.dirname(__FILE__) + "/fixtures/naked/yml/companies"
     114    assert_not_nil Fixtures.new( Account.connection, File.dirname(__FILE__) + "/fixtures/naked/yml/", FixtureGroup.new("companies")
    109115  end 
    110116 
    111117  def test_dirty_dirty_yaml_file 
    112118    assert_raises(Fixture::FormatError) do 
    113       Fixtures.new( Account.connection, "courses", File.dirname(__FILE__) + "/fixtures/naked/yml/courses"
     119      Fixtures.new( Account.connection, File.dirname(__FILE__) + "/fixtures/naked/yml/", FixtureGroup.new("courses")
    114120    end 
    115121  end 
    116122 
    117123  def test_empty_csv_fixtures 
    118     assert_not_nil Fixtures.new( Account.connection, "accounts", File.dirname(__FILE__) + "/fixtures/naked/csv/accounts"
     124    assert_not_nil Fixtures.new( Account.connection, File.dirname(__FILE__) + "/fixtures/naked/csv/", FixtureGroup.new("accounts")
    119125  end 
    120126end 
    121127 
     
    212218 
    213219end 
    214220 
     221class FixturesGroupTest < Test::Unit::TestCase 
     222  def test_get_table_name_from_model_class 
     223    fg = FixtureGroup.new(:filedoesnotexist, :class_name => "DeveloperWithAggregate") 
     224    assert_equal fg.table_name, 'developers' 
     225    assert_equal fg.class_name, 'DeveloperWithAggregate' 
     226  end 
     227   
     228  def test_assume_correct_class_name_from_table_name 
     229    fg = FixtureGroup.new(:developers, :table_name => "tests") 
     230    assert_equal fg.table_name, 'tests' 
     231    assert_equal fg.class_name, 'Test' 
     232  end 
    215233 
     234  def test_file_name_is_a_string 
     235    fg = FixtureGroup.new(:developers) 
     236    assert String === fg.file_name 
     237  end 
     238   
     239  def test_fixture_group_name 
     240    fg = FixtureGroup.new(:developers) 
     241    assert Symbol === fg.group_name 
     242    assert_equal fg.group_name, :developers 
     243     
     244    fg = FixtureGroup.new(:developers, :group_name => "other") 
     245    assert Symbol === fg.group_name 
     246    assert_equal fg.group_name, :other 
     247  end 
     248end 
    216249 
     250class MultipleFixturesForTheSameTableTest < Test::Unit::TestCase 
     251  self.use_instantiated_fixtures = true 
     252  fixture :topics, :class_name => "Topic" 
     253  fixture :topics2, :class_name => "Topic" 
     254   
     255  def test_loaded_fixtures 
     256    assert_equal @topics.size, 2 
     257    assert_equal @topics2.size, 2 
     258    union = Topic.find(:all) 
     259    assert_equal union.size, 4 
     260  end 
     261end 
    217262 
     263class MixSingularAndPluralFixturesTest < Test::Unit::TestCase 
     264  self.use_instantiated_fixtures = true 
     265  fixtures :topics, :developers, :accounts 
     266  fixture :topics2, :table_name => "topics" 
     267   
     268  def test_loaded_fixtures 
     269    assert_equal @topics.size, 2 
     270    assert_equal @topics2.size, 2 
     271    union = Topic.find(:all) 
     272    assert_equal union.size, 4 
     273  end 
     274end 
    218275 
    219  
     276class AlternateFileFixturesTest < Test::Unit::TestCase 
     277  self.use_instantiated_fixtures = true 
     278  fixture :topics2, :class_name => "Topic" 
     279   
     280  def test_alternate_fixture_file_was_loaded 
     281    assert_equal @topics2.size, 2 
     282    assert_nil @first 
     283    assert_nil @second 
     284    assert_equal @third.id, 3 
     285    assert_equal @fourth.id, 4 
     286    topics = Topic.find(:all) 
     287    assert_equal @topics2.size, 2 
     288  end 
     289end 
  • test/fixtures/topics2.yml

    old new  
     1third: 
     2  id: 3 
     3  title: The Third Topic 
     4  author_name: Duane 
     5  author_email_address: david@loudthinking.com 
     6  written_on: 2003-07-16t15:28:00.00+01:00 
     7  last_read: 2004-04-15 
     8  bonus_time: 2005-01-30t15:28:00.00+01:00 
     9  content: Have a nice day 
     10  approved: 0 
     11  replies_count: 0 
     12 
     13fourth: 
     14  id: 4 
     15  title: The Fourth topic 
     16  author_name: John 
     17  written_on: 2003-07-15t15:28:00.00+01:00 
     18  content: Have a nice day 
     19  approved: 1 
     20  replies_count: 2 
     21  parent_id: 1 
  • lib/active_record/fixtures.rb

    old new  
    22require 'yaml' 
    33require 'csv' 
    44 
     5# A FixtureGroup is a set of fixtures identified by a name.  Normally, this is the name of the 
     6# corresponding table in the database.  For example, when you declare the use of fixtures in a 
     7# TestUnit class, like so: 
     8#   fixtures :users 
     9# you are creating a FixtureGroup whose name is 'users', and whose defaults are set such that the 
     10# +class_name+, +file_name+ and +table_name+ are guessed from the FixtureGroup's name. 
     11class FixtureGroup 
     12  attr_accessor :table_name, :class_name, :connection 
     13  attr_reader :group_name, :file_name 
     14 
     15  def initialize(file_name, optional_names = {}) 
     16    self.file_name = file_name 
     17    self.group_name = optional_names[:group_name] || file_name 
     18    if optional_names[:table_name] 
     19      self.table_name = optional_names[:table_name] 
     20      self.class_name = optional_names[:class_name] || Inflector.classify(@table_name.to_s.gsub('.','_')) 
     21    elsif optional_names[:class_name] 
     22      self.class_name = optional_names[:class_name] 
     23      if Object.const_defined?(@class_name) 
     24        model_class = Object.const_get(@class_name) 
     25        self.table_name = model_class.table_name 
     26      end 
     27    end 
     28 
     29    # In case either :table_name or :class_name was not set: 
     30    self.table_name ||= @group_name.to_s 
     31    self.class_name ||= Inflector.classify(@table_name.to_s.gsub('.','_')) 
     32  end 
     33 
     34  def file_name=(name) 
     35    @file_name = name.to_s 
     36  end 
     37   
     38  def group_name=(name) 
     39    @group_name = name.to_sym 
     40  end 
     41 
     42  def class_file_name 
     43    Inflector.underscore(@class_name) 
     44  end 
     45   
     46  # Instantiate an array of FixtureGroup objects from an array of strings (table_names) 
     47  def self.array_from_names(names) 
     48    names.collect { |n| FixtureGroup.new(n) } 
     49  end 
     50   
     51  def hash 
     52    @group_name.hash 
     53  end 
     54   
     55  def eql?(other) 
     56    @group_name.eql? other.group_name 
     57  end 
     58end 
     59 
    560# Fixtures are a way of organizing data that you want to test against; in short, sample data. They come in 3 flavours: 
    661# 
    762#   1.  YAML fixtures 
     
    194249class Fixtures < Hash 
    195250  DEFAULT_FILTER_RE = /\.ya?ml$/ 
    196251 
    197   def self.instantiate_fixtures(object, table_name, fixtures, load_instances=true) 
    198     old_logger_level = ActiveRecord::Base.logger.level 
    199     ActiveRecord::Base.logger.level = Logger::ERROR 
    200  
    201     object.instance_variable_set "@#{table_name.to_s.gsub('.','_')}", fixtures 
    202     if load_instances 
    203       fixtures.each do |name, fixture| 
    204         if model = fixture.find 
    205           object.instance_variable_set "@#{name}", model 
    206         end 
    207       end 
    208     end 
    209  
    210     ActiveRecord::Base.logger.level = old_logger_level 
    211   end 
    212    
    213   def self.instantiate_all_loaded_fixtures(object, load_instances=true) 
    214     all_loaded_fixtures.each do |table_name, fixtures| 
    215       Fixtures.instantiate_fixtures(object, table_name, fixtures, load_instances) 
    216     end 
    217   end 
    218    
    219252  cattr_accessor :all_loaded_fixtures 
    220253  self.all_loaded_fixtures = {} 
    221254 
    222   def self.create_fixtures(fixtures_directory, *table_names) 
    223     connection = block_given? ? yield : ActiveRecord::Base.connection 
    224     old_logger_level = ActiveRecord::Base.logger.level 
     255  attr_accessor :connection, :fixtures_directory, :file_filter 
     256  attr_accessor :fixture_group 
    225257 
    226     begin 
    227       ActiveRecord::Base.logger.level = Logger::ERROR 
    228  
    229       fixtures_map = {} 
    230       fixtures = table_names.flatten.map do |table_name| 
    231         fixtures_map[table_name] = Fixtures.new(connection, File.split(table_name.to_s).last, File.join(fixtures_directory, table_name.to_s)) 
    232       end                
    233       all_loaded_fixtures.merge! fixtures_map   
    234        
    235       connection.transaction do 
    236         fixtures.reverse.each { |fixture| fixture.delete_existing_fixtures } 
    237         fixtures.each { |fixture| fixture.insert_fixtures } 
    238       end 
    239        
    240       reset_sequences(connection, table_names) if connection.is_a?(ActiveRecord::ConnectionAdapters::PostgreSQLAdapter) 
    241  
    242       return fixtures.size > 1 ? fixtures : fixtures.first 
    243     ensure 
    244       ActiveRecord::Base.logger.level = old_logger_level 
    245     end 
    246   end 
    247  
    248   # Work around for PostgreSQL to have new fixtures created from id 1 and running. 
    249   def self.reset_sequences(connection, table_names) 
    250     table_names.flatten.each do |table| 
    251       table_class = Inflector.classify(table.to_s) 
    252       if Object.const_defined?(table_class) 
    253         pk = eval("#{table_class}::primary_key") 
    254         if pk == 'id' 
    255           connection.execute( 
    256             "SELECT setval('#{table.to_s}_id_seq', (SELECT MAX(id) FROM #{table.to_s}), true)",  
    257             'Setting Sequence' 
    258           ) 
    259         end 
    260       end 
    261     end 
    262   end 
    263  
    264   attr_reader :table_name 
    265  
    266   def initialize(connection, table_name, fixture_path, file_filter = DEFAULT_FILTER_RE) 
    267     @connection, @table_name, @fixture_path, @file_filter = connection, table_name, fixture_path, file_filter 
    268     @class_name = Inflector.classify(@table_name) 
    269  
     258  def initialize(connection, fixtures_directory, fixture_group, file_filter = DEFAULT_FILTER_RE) 
     259    @connection, @fixtures_directory = connection, fixtures_directory 
     260    @fixture_group = fixture_group 
     261    @file_filter = file_filter 
    270262    read_fixture_files 
    271263  end 
    272264 
    273265  def delete_existing_fixtures 
    274     @connection.delete "DELETE FROM #{@table_name}", 'Fixture Delete' 
     266    @connection.delete "DELETE FROM #{@fixture_group.table_name}", 'Fixture Delete' 
    275267  end 
    276268 
    277269  def insert_fixtures 
    278270    values.each do |fixture| 
    279       @connection.execute "INSERT INTO #{@table_name} (#{fixture.key_list}) VALUES (#{fixture.value_list})", 'Fixture Insert' 
     271      @connection.execute "INSERT INTO #{@fixture_group.table_name} (#{fixture.key_list}) VALUES (#{fixture.value_list})", 'Fixture Insert' 
    280272    end 
    281273  end 
    282274 
    283275  private 
    284276    def read_fixture_files 
    285277      if File.file?(yaml_file_path) 
    286         # YAML fixtures 
    287         begin 
    288           yaml = YAML::load(erb_render(IO.read(yaml_file_path))) 
    289           yaml.each { |name, data| self[name] = Fixture.new(data, @class_name) } if yaml 
    290         rescue Exception=>boom 
    291           raise Fixture::FormatError, "a YAML error occured 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  #{boom.class}: #{boom}" 
    292         end 
     278        read_yaml_fixture_files 
    293279      elsif File.file?(csv_file_path) 
    294         # CSV fixtures 
    295         reader = CSV::Reader.create(erb_render(IO.read(csv_file_path))) 
    296         header = reader.shift 
    297         i = 0 
    298         reader.each do |row| 
    299           data = {} 
    300           row.each_with_index { |cell, j| data[header[j].to_s.strip] = cell.to_s.strip } 
    301           self["#{Inflector::underscore(@class_name)}_#{i+=1}"]= Fixture.new(data, @class_name) 
    302         end 
     280        read_csv_fixture_files 
    303281      elsif File.file?(deprecated_yaml_file_path) 
    304282        raise Fixture::FormatError, ".yml extension required: rename #{deprecated_yaml_file_path} to #{yaml_file_path}" 
     283      elsif File.directory?(File.join(@fixtures_directory, @fixture_group.file_name)) 
     284        read_standard_fixture_files 
    305285      else 
    306         # Standard fixtures 
    307         Dir.entries(@fixture_path).each do |file| 
    308           path = File.join(@fixture_path, file) 
    309           if File.file?(path) and file !~ @file_filter 
    310             self[file] = Fixture.new(path, @class_name) 
    311           end 
     286        raise Fixture::FixtureError, "Couldn't find a yaml, csv or standard file to load at #{@fixtures_directory}." 
     287      end 
     288    end 
     289 
     290    def read_yaml_fixture_files 
     291      # YAML fixtures 
     292      begin 
     293        yaml = YAML::load(erb_render(IO.read(yaml_file_path))) 
     294        yaml.each { |name, data| self[name] = Fixture.new(data, @fixture_group.class_name) } if yaml 
     295      rescue Exception=>boom 
     296        raise Fixture::FormatError, "a YAML error occured 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  #{boom.class}: #{boom}" 
     297      end 
     298    end 
     299 
     300    def read_csv_fixture_files 
     301      # CSV fixtures 
     302      reader = CSV::Reader.create(erb_render(IO.read(csv_file_path))) 
     303      header = reader.shift 
     304      i = 0 
     305      reader.each do |row| 
     306        data = {} 
     307        row.each_with_index { |cell, j| data[header[j].to_s.strip] = cell.to_s.strip } 
     308        self["#{fixture_group.class_file_name}_#{i+=1}"]= Fixture.new(data, @fixture_group.class_name) 
     309      end 
     310    end 
     311 
     312    def read_standard_fixture_files 
     313      # Standard fixtures 
     314      path = File.join(@fixtures_directory, @fixture_group.file_name) 
     315      Dir.entries(path).each do |file| 
     316        path = File.join(@fixtures_directory, file) 
     317        if File.file?(path) and file !~ @file_filter 
     318          self[file] = Fixture.new(path, @fixture_group.class_name) 
    312319        end 
    313320      end 
    314321    end 
    315322 
    316323    def yaml_file_path 
    317       "#{@fixture_path}.yml" 
     324      fixture_path_with_extension ".yml" 
    318325    end 
    319326 
    320327    def deprecated_yaml_file_path 
    321       "#{@fixture_path}.yaml" 
     328      fixture_path_with_extension ".yaml" 
    322329    end 
    323330 
    324331    def csv_file_path 
    325       @fixture_path + ".csv" 
     332      fixture_path_with_extension ".csv" 
    326333    end 
    327334 
    328     def yaml_fixtures_key(path
    329       File.basename(@fixture_path).split(".").first 
    330     end 
     335    def fixture_path_with_extension(ext
     336      File.join(@fixtures_directory, @fixture_group.file_name + ext) 
     337    end       
    331338 
    332339    def erb_render(fixture_content) 
    333340      ERB.new(fixture_content).result 
    334341    end 
     342 
     343    #def yaml_fixtures_key(path) 
     344    #  File.basename(@fixture_path).split(".").first 
     345    #end 
     346 
     347  public 
     348    class << self 
     349      def instantiate_fixtures(object, fixture_group_name, fixtures, load_instances=true) 
     350        old_logger_level = ActiveRecord::Base.logger.level 
     351        ActiveRecord::Base.logger.level = Logger::ERROR 
     352 
     353        # table_name.to_s.gsub('.','_') replaced by 'fixture_group_name' 
     354        object.instance_variable_set "@#{fixture_group_name}", fixtures 
     355        if load_instances 
     356          fixtures.each do |name, fixture| 
     357            if model = fixture.find 
     358              object.instance_variable_set "@#{name}", model 
     359            end 
     360          end 
     361        end 
     362 
     363        ActiveRecord::Base.logger.level = old_logger_level 
     364      end 
     365 
     366      def instantiate_all_loaded_fixtures(object, load_instances=true) 
     367        all_loaded_fixtures.each do |fixture_group_name, fixtures| 
     368          Fixtures.instantiate_fixtures(object, fixture_group_name, fixtures, load_instances) 
     369        end 
     370      end 
     371 
     372 
     373      def create_fixtures(fixtures_directory, *fixture_groups) 
     374        connection = block_given? ? yield : ActiveRecord::Base.connection 
     375        old_logger_level = ActiveRecord::Base.logger.level 
     376        fixture_groups.flatten! 
     377         
     378        # Backwards compatibility: Allow an array of table names to be passed in, but just use them 
     379        # to create an array of FixtureGroup objects 
     380        if not fixture_groups.empty? and fixture_groups.first.is_a?(String) 
     381          fixture_groups = FixtureGroup.array_from_names(fixture_groups) 
     382        end 
     383 
     384        begin 
     385          ActiveRecord::Base.logger.level = Logger::ERROR 
     386 
     387          fixtures_map = {} 
     388          fixtures = fixture_groups.map do |group| 
     389            fixtures_map[group.group_name] = Fixtures.new(connection, fixtures_directory, group) 
     390          end                
     391          # Make sure all refs to all_loaded_fixtures use group_name as hash index, not table_name 
     392          all_loaded_fixtures.merge! fixtures_map   
     393 
     394          connection.transaction do 
     395            fixtures.reverse.each { |fixture| fixture.delete_existing_fixtures } 
     396            fixtures.each { |fixture| fixture.insert_fixtures } 
     397          end 
     398 
     399          reset_sequences(connection, fixture_groups) if connection.is_a?(ActiveRecord::ConnectionAdapters::PostgreSQLAdapter) 
     400 
     401          return fixtures.size > 1 ? fixtures : fixtures.first 
     402        ensure 
     403          ActiveRecord::Base.logger.level = old_logger_level 
     404        end 
     405      end 
     406 
     407      # Work around for PostgreSQL to have new fixtures created from id 1 and running. 
     408      def reset_sequences(connection, fixture_groups) 
     409        fixture_groups.flatten.each do |group| 
     410          if Object.const_defined?(group.class_name) 
     411            pk = eval("#{group.class_name}::primary_key") 
     412            if pk == 'id' 
     413              connection.execute( 
     414                "SELECT setval('#{group.table_name}_id_seq', (SELECT MAX(id) FROM #{group.table_name}), true)",  
     415                'Setting Sequence' 
     416              ) 
     417            end 
     418          end 
     419        end 
     420      end 
     421    end 
    335422end 
    336423 
    337424class Fixture #:nodoc: 
     
    399486    class TestCase #:nodoc: 
    400487      include ClassInheritableAttributes 
    401488 
    402       cattr_accessor :fixture_path 
    403       class_inheritable_accessor :fixture_table_name
     489      cattr_accessor :fixtures_directory 
     490      class_inheritable_accessor :fixture_group
    404491      class_inheritable_accessor :use_transactional_fixtures 
    405492      class_inheritable_accessor :use_instantiated_fixtures   # true, false, or :no_instances 
    406493      class_inheritable_accessor :pre_loaded_fixtures 
    407494 
    408       self.fixture_table_names = [] 
     495      self.fixture_groups = [] 
    409496      self.use_transactional_fixtures = false 
    410497      self.use_instantiated_fixtures = true 
    411498      self.pre_loaded_fixtures = false 
    412499 
    413500      @@already_loaded_fixtures = {} 
    414501 
    415       def self.fixtures(*table_names) 
    416         table_names = table_names.flatten 
    417         self.fixture_table_names |= table_names 
    418         require_fixture_classes(table_names) 
    419         setup_fixture_accessors(table_names) 
     502      # Backwards compatibility 
     503      def self.fixture_path=(path); self.fixtures_directory = path; end 
     504      def self.fixture_path; self.fixtures_directory; end 
     505      # It would be more appropriate to call this 'fixture_group_names', but it's for back compat. 
     506      def fixture_table_names; fixture_groups.collect { |g| g.group_name }; end 
     507 
     508      def self.fixture(file_name, options = {}) 
     509        self.fixture_groups |= [FixtureGroup.new(file_name, options)] 
     510        require_fixture_classes 
     511        setup_fixture_accessors 
    420512      end 
    421513 
    422       def self.require_fixture_classes(table_names=nil) 
    423         (table_names || fixture_table_names).each do |table_name|  
     514      def self.fixtures(*file_names) 
     515        self.fixture_groups |= FixtureGroup.array_from_names(file_names.flatten) 
     516        require_fixture_classes 
     517        setup_fixture_accessors 
     518      end 
     519 
     520      def self.require_fixture_classes(override_fixture_groups=nil) 
     521        (override_fixture_groups || fixture_groups).each do |group|  
    424522          begin 
    425             require Inflector.singularize(table_name.to_s) 
     523            require group.class_file_name 
    426524          rescue LoadError 
    427525            # Let's hope the developer has included it himself 
    428526          end 
    429527        end 
    430528      end 
    431529 
    432       def self.setup_fixture_accessors(table_names=nil) 
    433         (table_names || fixture_table_names).each do |table_name
    434           table_name = table_name.to_s.tr('.','_') 
    435           define_method(table_name) do |fixture, *optionals| 
     530      def self.setup_fixture_accessors(override_fixture_groups=nil) 
     531        (override_fixture_groups || fixture_groups).each do |group
     532          # table_name = table_name.to_s.tr('.','_') 
     533          define_method(group.group_name) do |fixture, *optionals| 
    436534            force_reload = optionals.shift 
    437             @fixture_cache[table_name] ||= Hash.new 
    438             @fixture_cache[table_name][fixture] = nil if force_reload 
    439             @fixture_cache[table_name][fixture] ||= @loaded_fixtures[table_name][fixture.to_s].find 
     535            @fixture_cache[group.group_name] ||= Hash.new 
     536            @fixture_cache[group.group_name][fixture] = nil if force_reload 
     537            @fixture_cache[group.group_name][fixture] ||= @loaded_fixtures[group.group_name][fixture.to_s].find 
    440538          end 
    441539        end 
    442540      end 
     
    519617      private 
    520618        def load_fixtures 
    521619          @loaded_fixtures = {} 
    522           fixtures = Fixtures.create_fixtures(fixture_path, fixture_table_names) 
     620          fixtures = Fixtures.create_fixtures(fixtures_directory, fixture_groups) 
    523621          unless fixtures.nil? 
    524622            if fixtures.instance_of?(Fixtures) 
    525               @loaded_fixtures[fixtures.table_name] = fixtures 
     623              @loaded_fixtures[fixtures.fixture_group.group_name] = fixtures 
    526624            else 
    527               fixtures.each { |f| @loaded_fixtures[f.table_name] = f } 
     625              fixtures.each { |f| @loaded_fixtures[f.fixture_group.group_name] = f } 
    528626            end 
    529627          end 
    530628        end 
     
    536634          if pre_loaded_fixtures 
    537635            raise RuntimeError, 'Load fixtures before instantiating them.' if Fixtures.all_loaded_fixtures.empty? 
    538636            unless @@required_fixture_classes 
    539               self.class.require_fixture_classes Fixtures.all_loaded_fixtures.keys 
     637              groups = Fixtures.all_loaded_fixtures.values.collect { |f| f.group_name } 
     638              self.class.require_fixture_classes groups 
    540639              @@required_fixture_classes = true 
    541640            end 
    542641            Fixtures.instantiate_all_loaded_fixtures(self, load_instances?) 
    543642          else 
    544643            raise RuntimeError, 'Load fixtures before instantiating them.' if @loaded_fixtures.nil? 
    545             @loaded_fixtures.each do |table_name, fixtures| 
    546               Fixtures.instantiate_fixtures(self, table_name, fixtures, load_instances?) 
     644            @loaded_fixtures.each do |fixture_group_name, fixtures| 
     645              Fixtures.instantiate_fixtures(self, fixture_group_name, fixtures, load_instances?) 
    547646            end 
    548647          end 
    549648        end