lib/joinfix/fixtures_class.rb in joinfix-0.1.1 vs lib/joinfix/fixtures_class.rb in joinfix-1.0.0

- old
+ new

@@ -1,167 +1,121 @@ class Fixtures - # Class methods to tie fixture joining into the standard process for generating fixtures. class << self - # Called by individual Fixtures instances just before they insert fixtures. - # This allows templating to occur at the correct time (ie after all fixtures - # have been loaded and configured) -- resolution of references naturally requires - # that all join tables are available. - def template_all_loaded_fixtures + # Makes join fixtures for all loaded fixtures. Called just prior to inserting + # fixtures, after all fixtures have been loaded. + # + # After make_join_fixtures completes, entries for tables matching ENV['joinfix_dump'] + # are printed to STDOUT. You can print entries for each loaded fixture by setting + # ENV['joinfix_dump'] = 'true'. By default, no entries are printed. + # + # Note: printing does not affect the creation or loading of fixtures. + def make_join_fixtures all_loaded_fixtures.each_pair do |table_name, fixtures| - fixtures.template_fixtures + fixtures.make_child_entries end + # note indexing and reference resolution must execute after all # fixtures have been templated because you never know which fixture(s) # will recieve new entries. Additionally, indexing and resolution must - # run separately, because reference resolution requires the target ids - # to be set. + # run separately, because reference resolution requires the primary key + # be set for the referenced entry. all_loaded_fixtures.values.each {|fixtures| index_fixtures(fixtures) } all_loaded_fixtures.values.each {|fixtures| resolve_references(fixtures)} + + # Print entries to STDOUT for review, if applicable + joinfix_dump = ENV['joinfix_dump'] + if joinfix_dump + print_all = (joinfix_dump.to_s =~ /^true$/i) + regexp = Regexp.new(joinfix_dump.to_s) + + all_loaded_fixtures.values.each do |fixtures| + table_name = fixtures.klass.table_name + next unless print_all || table_name =~ regexp + + puts "------- #{fixtures.klass.table_name} --------" + puts fixtures.to_hash.to_yaml.gsub(/^---/, '') + "\n" + end + end end - # Retreives the fixture by the given table name. Raises an error if the fixture has - # not yet been loaded. + # Retreives the Fixtures for the given table name. Raises an error if this Fixtures + # has not yet been loaded. def fixture(table_name) fixture = all_loaded_fixtures[table_name.to_s] raise MissingFixtureError.new(table_name) unless fixture fixture end protected - # Sets the primary key in each of the input fixtures, beginning one-past fixtures.offset - # (generally this is 1). If a fixture already has an id assigned, it will be skipped. - def index_fixtures(fixtures) + # Sets the primary key for entries in each of the input Fixtures, beginning + # one past the Fixtures primary key offset (ie 1). Skips entries that already + # have a primary key assigned. + def index_fixtures(fixtures) # :nodoc: id = fixtures.klass.primary_key - # first find entries with an id and record the ids so that they will be skipped + # find entries with the primary key and record these so that they will be skipped skip_indicies = [] fixtures.each_pair do |name, fixture| skip_indicies << fixture[id].to_i if fixture.has_key?(id) end - # next find and index entries that do not have an id defined - index = fixtures.offset + # find and index entries that do not have a primary key defined + index = fixtures.primary_key_offset fixtures.each_pair do |name, fixture| - # skip entries that already have an id defined next if fixture.has_key?(id) - # find the next available index - # note this must happen before the id assignment, - # in case index 1 is marked for skipping + # find the next available index. Note this must happen before + # the assignment, in case '1' is marked for skipping while true index += 1 break unless skip_indicies.include?(index) end fixture[id] = index end end - # Resolves each join reference in the input fixtures - def resolve_references(fixtures) - fixtures.each_pair do |entry_name, fixture| - # search the fixture for join references - fixture.each_pair do |join_ref, join_name| + # Resolves join references in the input Fixtures. + def resolve_references(fixtures) # :nodoc: + fixtures.each_pair do |entry_name, entry| + entry.each_pair do |join_ref, join_name| # next if the key isn't a join reference next unless join_ref.kind_of?(Array) foreign_key = join_ref.first join_table_name = join_ref.last - - # raise an error if the join table isn't loaded; the reference cannot be resolved - unless Fixtures.all_loaded_fixtures.has_key?(join_table_name) - raise ResolveJoinReferenceError.new(fixtures, entry_name, join_table_name, join_name, - "The join table '#{join_table_name}' has not been loaded.") - end - - join_fixtures = Fixtures.all_loaded_fixtures[join_table_name] + + join_fixtures = Fixtures.fixture(join_table_name) id = join_fixtures.klass.primary_key # raise an error if the join entry isn't in the join table; the reference cannot be resolved unless join_fixtures.has_key?(join_name) raise ResolveJoinReferenceError.new(fixtures, entry_name, join_table_name, join_name, "The join entry '#{join_name}' doesn't exist in '#{join_table_name}'.") end join_entry = join_fixtures[join_name] - # raise an exception if a join_id was not found + # raise an exception if the primary key for the join entry is not set unless join_entry.has_key?(id) raise ResolveJoinReferenceError.new(fixtures, entry_name, join_table_name, join_name, "No #{id} present in join entry '#{join_name}'.") end # raise an exception if the foreign key is already set - unless fixture[foreign_key].nil? + unless entry[foreign_key].nil? raise ForeignKeySetError.new(fixtures, entry_name, join_table_name, join_name, "Foreign key <#{foreign_key}> is already set!") end - # set the join id - fixture[foreign_key] = join_entry[id] + # set the foreign key to the joined entry primary key + entry[foreign_key] = join_entry[id] end # delete the join references - fixture.delete_if {|key,value| key.kind_of?(Array) } + entry.delete_if {|key,value| key.kind_of?(Array) } end end end -end - -class MissingFixtureError < RuntimeError # :nodoc: - attr_reader :table_name - def initialize(table_name) - @table_name = table_name - end - - def message - "No fixture loaded for <#{table_name}>\n" + - (advice.nil? ? '' : "#{advice}\n") - end - - def advice - %Q{} - end -end - -class ResolveJoinReferenceError < RuntimeError # :nodoc: - attr_reader :fixtures, :entry_name, :join_table_name, :join_name, :msg - attr_accessor :advice - - def initialize(fixtures, entry_name, join_table_name, join_name, msg=nil) - @fixtures = fixtures - @entry_name = entry_name - @join_table_name = join_table_name - @join_name = join_name - @msg =msg - end - - def message - "Cannot resolve reference to <#{join_table_name}(:#{join_name})> " + - "for <#{fixtures.klass.table_name}(:#{entry_name})> " + - "in <#{fixtures.fixture_path}>.\n" + - (msg.nil? ? '' : "\n#{msg}\n") + - (advice.nil? ? '' : "#{advice}\n") - end -end - -class ForeignKeySetError < ResolveJoinReferenceError # :nodoc: - def advice - %Q{ -This error occurs when you specifiy the foreign key, as well as a join entry. ---- -poem: - title: Poetry of Departures - author_id: 8 - author: larkin - -If you need to specify the foreign key, do so within the entry. ---- -poem: - title: Poetry of Departures - author: - larkin: - id: 8} - end -end +end \ No newline at end of file