class Fixation::FixtureTable
Attributes
class_name[R]
connection[R]
filename[R]
fixture_name[R]
loaded_at[R]
table_name[R]
Public Class Methods
erb_content(filename)
click to toggle source
# File lib/fixation/fixture_table.rb, line 5 def self.erb_content(filename) template = File.read(filename) render_context = ActiveRecord::FixtureSet::RenderContext.create_subclass.new.get_binding ERB.new(template).result(render_context) end
new(filename, basename, connection, loaded_at)
click to toggle source
# File lib/fixation/fixture_table.rb, line 11 def initialize(filename, basename, connection, loaded_at) @filename = filename @connection = connection @loaded_at = loaded_at @fixture_name = basename.gsub('/', '_') @class_name = basename.classify begin @klass = @class_name.constantize @klass = nil unless @klass < ActiveRecord::Base rescue NameError ActiveRecord::Base.logger.warn "couldn't load #{class_name} for fixture table #{table_name}: #{$!}" end if @klass @table_name = @klass.table_name @primary_key = @klass.primary_key @record_timestamps = @klass.record_timestamps @inheritance_column = @klass.inheritance_column else @table_name = basename.gsub('/', '_') end end
Public Instance Methods
add_row(name, attributes)
click to toggle source
# File lib/fixation/fixture_table.rb, line 121 def add_row(name, attributes) embellish_fixture(name, attributes) embellished_rows[name] = attributes end
columns_hash()
click to toggle source
# File lib/fixation/fixture_table.rb, line 36 def columns_hash @columns_hash ||= connection.columns(table_name).index_by(&:name) end
embellish_fixture(name, attributes)
click to toggle source
# File lib/fixation/fixture_table.rb, line 61 def embellish_fixture(name, attributes) # populate the primary key column, if not already set if @primary_key && columns_hash[@primary_key] && !attributes.has_key?(@primary_key) attributes[@primary_key] = Fixation.identify(name, columns_hash[@primary_key].type) end # substitute $LABEL into all string values attributes.each do |column_name, value| attributes[column_name] = value.gsub("$LABEL", name) if value.is_a?(String) end # populate any timestamp columns, if not already set if @record_timestamps %w(created_at updated_at).each do |column_name| attributes[column_name] = loaded_at if columns_hash[column_name] && !attributes.has_key?(column_name) end %w(created_at updated_at).each do |column_name| attributes[column_name] = loaded_at.to_date if columns_hash[column_name] && !attributes.has_key?(column_name) end end # convert enum names to values @klass.defined_enums.each do |name, values| attributes[name] = values.fetch(attributes[name], attributes[name]) if attributes.has_key?(name) end if @klass.respond_to?(:defined_enums) # convert any association names into the identity column equivalent - following code from activerecord's fixtures.rb nonexistant_columns = attributes.keys - columns_hash.keys if @klass && nonexistant_columns.present? # If STI is used, find the correct subclass for association reflection reflection_class = if attributes.include?(@inheritance_column) attributes[@inheritance_column].constantize rescue @klass else @klass end nonexistant_columns.each do |column_name| association = reflection_class.reflect_on_association(column_name) if association.nil? raise ActiveRecord::Fixture::FormatError, "No column named #{column_name} found in table #{table_name}" elsif association.macro != :belongs_to raise ActiveRecord::Fixture::FormatError, "Association #{column_name} in table #{table_name} has type #{association.macro}, which is not currently supported" else value = attributes.delete(column_name) if association.options[:polymorphic] && value.is_a?(String) && value.sub!(/\s*\(([^\)]*)\)\s*$/, "") # support polymorphic belongs_to as "label (Type)" attributes[association.foreign_type] = $1 end fk_name = (association.options[:foreign_key] || "#{association.name}_id").to_s attributes[fk_name] = value ? ActiveRecord::FixtureSet.identify(value) : value end end end end
embellished_rows()
click to toggle source
# File lib/fixation/fixture_table.rb, line 55 def embellished_rows @embellished_rows ||= parsed_rows.each do |name, attributes| embellish_fixture(name, attributes) end end
fixture_ids()
click to toggle source
# File lib/fixation/fixture_table.rb, line 126 def fixture_ids embellished_rows.each_with_object({}) do |(name, attributes), ids| ids[name] = attributes['id'] || attributes['uuid'] end end
parsed_rows()
click to toggle source
# File lib/fixation/fixture_table.rb, line 40 def parsed_rows result = YAML.load(self.class.erb_content(filename)) result ||= {} # for completely empty files unless (result.is_a?(Hash) || result.is_a?(YAML::Omap)) && result.all? { |name, attributes| name.is_a?(String) && attributes.is_a?(Hash) } raise ActiveRecord::Fixture::FormatError, "#{filename} needs to contain a hash of fixtures" end result.delete('DEFAULTS') result rescue ArgumentError, Psych::SyntaxError => error # we use exactly the same error class and message as ActiveRecord::FixtureSet in case anyone was depending on it raise ActiveRecord::Fixture::FormatError, "a YAML error occurred parsing #{filename}. 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}", error.backtrace end
quote_value(column, value)
click to toggle source
# File lib/fixation/fixture_table.rb, line 164 def quote_value(column, value) connection.quote(value) rescue TypeError connection.quote(YAML.dump(value)) end
statements()
click to toggle source
# File lib/fixation/fixture_table.rb, line 132 def statements statements = ["DELETE FROM #{connection.quote_table_name table_name}"] unless embellished_rows.empty? # first figure out what columns we have to insert into; we're going to need to use the same names for # all rows so we can use the multi-line INSERT syntax columns_to_include = Set.new embellished_rows.each do |name, attributes| attributes.each do |column_name, value| raise ActiveRecord::Fixture::FormatError, "No column named #{column_name.inspect} found in table #{table_name.inspect} (attribute on fixture #{name.inspect})" unless columns_hash[column_name] columns_to_include.add(columns_hash[column_name]) end end # now build the INSERT statement quoted_column_names = columns_to_include.collect { |column| connection.quote_column_name(column.name) }.join(', ') statements << "INSERT INTO #{connection.quote_table_name table_name} (#{quoted_column_names}) VALUES " + embellished_rows.collect do |name, attributes| '(' + columns_to_include.collect do |column| if attributes.has_key?(column.name) quote_value(column, attributes[column.name]) else column.default_function || quote_value(column, column.default) end end.join(', ') + ')' end.join(', ') end statements end