Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Initial Commit

  • Loading branch information...
commit a8d5555d5b65afdf21c99e80e0dbc927925f1b29 0 parents
@brewski authored
20 MIT-LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2009 [name of plugin creator]
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
13 README
@@ -0,0 +1,13 @@
+FixtureExtractor
+================
+
+Introduction goes here.
+
+
+Example
+=======
+
+Example goes here.
+
+
+Copyright (c) 2009 [name of plugin creator], released under the MIT license
23 Rakefile
@@ -0,0 +1,23 @@
+require 'rake'
+require 'rake/testtask'
+require 'rake/rdoctask'
+
+desc 'Default: run unit tests.'
+task :default => :test
+
+desc 'Test the fixture_extractor plugin.'
+Rake::TestTask.new(:test) do |t|
+ t.libs << 'lib'
+ t.libs << 'test'
+ t.pattern = 'test/**/*_test.rb'
+ t.verbose = true
+end
+
+desc 'Generate documentation for the fixture_extractor plugin.'
+Rake::RDocTask.new(:rdoc) do |rdoc|
+ rdoc.rdoc_dir = 'rdoc'
+ rdoc.title = 'FixtureExtractor'
+ rdoc.options << '--line-numbers' << '--inline-source'
+ rdoc.rdoc_files.include('README')
+ rdoc.rdoc_files.include('lib/**/*.rb')
+end
1  init.rb
@@ -0,0 +1 @@
+# Include hook code here
1  install.rb
@@ -0,0 +1 @@
+# Install hook code here
52 lib/fixture_extractor/extractor.rb
@@ -0,0 +1,52 @@
+require 'set'
+
+module FixtureExtractor
+ class Extractor
+ def initialize
+ @fixtures = Set.new
+ @tables = Array.new
+ end
+
+ def add_object(object, *name)
+ raise "Invalid object #{name} (nil)" if (object.nil?)
+
+ if (object.is_a?(Array))
+ object.each { |o| @fixtures << Fixture.new_instance(o) }
+ else
+ @fixtures << Fixture.new_instance(object)
+ end
+ end
+
+ def add_table(table_name)
+ @tables << table_name.to_sym
+ end
+
+ def dump
+ @tables.each do |table_name|
+ Fixture.collect_table(table_name)
+ end
+
+ @fixtures.each do |fixture|
+ fixture.collect_fixture
+ end
+
+ Fixture.fixtures.each_pair do |table, fixtures|
+ write(table) do
+ fixtures.each do |fixture|
+ puts fixture.to_yaml
+ end
+ end
+ end
+ end
+
+ private
+ def write(table)
+ File.open("yml/#{table}.yml", "w") do |io|
+ old_stdout = $stdout
+ $stdout = io
+ yield
+ $stdout = old_stdout
+ end
+ end
+ end
+end
143 lib/fixture_extractor/fixture.rb
@@ -0,0 +1,143 @@
+require 'set'
+require 'base64'
+require 'yaml/encoding'
+
+module FixtureExtractor
+ class Fixture
+
+ @@fixtures = Hash.new
+
+ def Fixture.new_instance(model)
+ begin
+ return ("FixtureExtractor::" + model.class.name + "Fixture").constantize.new(model)
+ rescue
+ return Fixture.new(model)
+ end
+ end
+
+ def Fixture.collect_table(table)
+ class_name = table.to_s.singularize.camelcase
+ table_class = Kernel.const_get(class_name)
+
+ table_class.find(:all).each do |record|
+ Fixture.new_instance(record).collect_fixture
+ end
+ end
+
+ def Fixture.fixtures
+ @@fixtures
+ end
+
+ attr_reader :model
+
+ def initialize(model)
+ @model = model
+ end
+
+ def to_yaml
+ yaml = "#{name}:\n"
+
+ model.class.columns.each do |column|
+ yaml += Fixture.yaml_field(@model, column)
+ end
+
+ return "#{yaml}\n"
+ end
+
+ def name
+ return "#{model.class.table_name.singularize}_#{model.id.to_s}"
+ end
+
+ def table_name
+ return model.class.table_name.to_sym
+ end
+
+ def collect_fixture(options = {})
+ @@fixtures[table_name] ||= SortedSet.new
+
+ if (@@fixtures[table_name].include?(self))
+ return
+ end
+
+ before_collect(options)
+
+ @@fixtures[table_name] << self
+ collect_associations(options) unless (options[:ignore] == :all)
+
+ after_collect(options)
+ end
+
+ def before_collect(options)
+ end
+
+ def after_collect(options)
+ end
+
+ def ignore_associations
+ []
+ end
+
+ def collect_associations(options = {})
+ ignore_associations = options[:ignore] || self.ignore_associations
+ ignore_associations = [ ignore_associations ] unless (ignore_associations.is_a?(Array))
+
+ model.class.reflections.each_value do |reflection|
+ next if (ignore_associations.include?(reflection.name))
+
+ if (reflection.macro == :belongs_to)
+ obj = @model.send(reflection.name)
+ Fixture.new_instance(obj).collect_fixture if (!obj.nil?)
+ elsif (reflection.macro == :has_many)
+ @model.send(reflection.name).each do |obj|
+ Fixture.new_instance(obj).collect_fixture
+ end
+ elsif (reflection.macro == :has_and_belongs_to_many)
+ join_table = reflection.options[:join_table]
+
+ @model.send(reflection.name).each do |obj|
+ JoinTableFixture.new_instance(@model, obj, reflection).collect_fixture
+ end
+ end
+ end
+ end
+
+ def <=>(other)
+ raise "type mismatch!" unless (model.kind_of?(other.model.class))
+ return model.id <=> other.model.id
+ end
+
+ def eql?(other)
+ return model.eql?(other.model)
+ end
+
+ def hash
+ return model.hash
+ end
+
+ protected
+ def Fixture.fixture_name(name)
+ ret = name.gsub(/[#\s(),\\\/-]+/, "_").gsub(/_+/, "_").gsub(/_+$/, "").downcase
+ raise "invalid fixture name '#{ret}': name cannot begin with a number" if (ret =~ /^\d+/)
+ return ret
+ end
+
+ def Fixture.yaml_field(obj, column)
+ field = column.name
+ val = obj.send(field.to_sym)
+
+ return "" if (val.nil?)
+
+ if (column.type == :binary)
+ val = "!!binary \"\\\n#{Base64.encode64(val).rstrip}\""
+ else
+ if (val == true or val == false)
+ val = val ? "1" : "0"
+ end
+
+ val = "\"#{YAML::escape(val.to_s)}\""
+ end
+
+ return " #{field}: #{val}\n"
+ end
+ end
+end
65 lib/fixture_extractor/join_table_fixture.rb
@@ -0,0 +1,65 @@
+module FixtureExtractor
+ class JoinTableFixture < Fixture
+
+ def JoinTableFixture.new_instance(model, association, reflection)
+ join_table = reflection.options[:join_table]
+ begin
+ return Kernel.const_get(join_table + "Fixture").new(model, association, reflection)
+ rescue
+ return JoinTableFixture.new(model, association, reflection)
+ end
+ end
+
+ attr_reader :reflection
+ attr_reader :association
+
+ def initialize(model, association, reflection)
+ @model = model
+ @association = association
+ @reflection = reflection
+ end
+
+ def join_table
+ return @reflection.options[:join_table]
+ end
+
+ def collect_fixture
+ @@fixtures[join_table.to_sym] ||= SortedSet.new
+
+ return if (@@fixtures[join_table.to_sym].include?(self))
+ @@fixtures[join_table.to_sym] << self
+
+ Fixture.new_instance(association).collect_fixture
+ end
+
+
+ def to_yaml
+ yaml = "#{name}:\n"
+ yaml += " #{@reflection.primary_key_name}: #{@model.id}\n"
+ yaml += " #{@reflection.association_foreign_key}: #{association.id}\n\n"
+ return yaml
+ end
+
+ def name
+ return "#{join_table}_#{model.id}_#{association.id}"
+ end
+
+ def <=>(other)
+ raise "type mismatch!" if (!@model.kind_of?(other.model.class) ||
+ (!association.kind_of?(other.association.class)))
+
+ model_cmp = @model.id <=> other.model.id
+ association_cmp = association.id <=> other.association.id
+
+ return model_cmp != 0 ? model_cmp : association_cmp
+ end
+
+ def eql?(other)
+ return @model.eql?(other.model) && association.eql?(other.association)
+ end
+
+ def hash
+ return (@model.id.to_s + association.id.to_s).hash
+ end
+ end
+end
61 lib/fixture_helper.rb
@@ -0,0 +1,61 @@
+module FixtureHelper
+ class FixtureMappings
+ include Singleton
+ attr_reader :mappings
+
+ def self.map_fixtures(&block)
+ yield(FixtureMappings.instance)
+ return FixtureMappings.instance
+ end
+
+ # define a callback to lookup a model by a +model_identifier+ string. See
+ # FixtureMappings::map_fixtures
+ def self.to_lookup(model_class, &block)
+ (@@model_lookups ||= {})[model_class] = block
+ end
+
+ def self.lookup_model(model_class, model_identifier)
+ lookup = @@model_lookups[model_class] || @@model_lookups[:default]
+ return lookup.call(model_class, model_identifier) unless (lookup.nil?)
+ end
+
+ def initialize
+ @mappings = Hash.new { |hash, key| hash[key] = Hash.new }
+ end
+
+ def method_missing(model_name, *args, &block)
+ model_class = model_name.to_s.classify.constantize
+ model_identifier = args.shift
+
+ begin
+ if (model_identifier.is_a?(model_class))
+ model = model_identifier
+ elsif (model_identifier.is_a?(Numeric))
+ model = model_class.find(model_identifier)
+ else
+ model = self.class.lookup_model(model_class, model_identifier)
+ end
+ rescue
+ raise "error mapping model '#{model_name}:#{model_identifier}': " + $!.message
+ end
+
+ raise "could not map model '#{model_name}:#{model_identifier}'" if (model.nil?)
+
+ args.each do |mapping_name|
+ @mappings[model_class][mapping_name] = model
+ end
+ end
+ end
+
+ class InstanceMethods
+ def fixture(model_class, fixture_name)
+ fixture = FixtureMappings.instance.mappings[model_class][fixture_name]
+ if (fixture.nil?)
+ raise "unable to find fixture #{model_class}:#{fixture_name}"
+ end
+
+ fixture.reload
+ return fixture
+ end
+ end
+end
18 tasks/fixture_extractor_tasks.rake
@@ -0,0 +1,18 @@
+namespace :db do
+
+ namespace :fixtures do
+ desc "Extract fixtures from the current environment into the fixtures directory"
+ task :extract => :environment do
+ require File.join(RAILS_ROOT, "test", "fixtures.rb")
+
+ extractor = FixtureExtractor::Extractor.new
+ FixtureHelper::FixtureMappings.instance.mappings.each do |model_class, mappings|
+ mappings.values.uniq.each do |model|
+ extractor.add_object(model)
+ end
+ end
+
+ extractor.dump
+ end
+ end
+end
8 test/fixture_extractor_test.rb
@@ -0,0 +1,8 @@
+require 'test_helper'
+
+class FixtureExtractorTest < ActiveSupport::TestCase
+ # Replace this with your real tests.
+ test "the truth" do
+ assert true
+ end
+end
3  test/test_helper.rb
@@ -0,0 +1,3 @@
+require 'rubygems'
+require 'active_support'
+require 'active_support/test_case'
1  uninstall.rb
@@ -0,0 +1 @@
+# Uninstall hook code here
Please sign in to comment.
Something went wrong with that request. Please try again.