iron_fixture_extractor 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source 'https://rubygems.org'
2
+ # TEMP CRAP FOR DEV, COMMENT OUT OR DELETE
3
+ # USED w ruby 1.9.2
4
+ # http://dirk.net/2010/04/17/ruby-debug-with-ruby-19x-and-rails-3-on-rvm/
5
+ gem 'ruby-debug19', :require => 'ruby-debug'
6
+ gem 'rake'
7
+ # Specify your gem's dependencies in iron_fixture_extractor.gemspec
8
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Joe Goggins
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,142 @@
1
+ # About
2
+
3
+ When object factories don't work because your data is too complex and creating manual fixtures is cumbersome and brittle: Iron Fixture Extractor.
4
+
5
+ Iron fixture extractor makes extracting complex ActiveRecord dependency graphs from live databases sane. Feed it an array of ActiveRecord objects that have preloaded associations via the .include method or just an adhoc array of ActiveRecord instances you want to capture as fixtures and it will write a bunch of fixture files for usage in your test cases.
6
+
7
+ `###
8
+ ,#
9
+ +#,
10
+ ;+############++++++++++++++++++++++++++++
11
+ ; + `:
12
+ ## +# ++,
13
+ .++` ;#; :+
14
+ '' ;+` `;;'
15
+ ;::' `;;. +;;+'
16
+ :;:;': +;;'' '+'+++:
17
+ `:';'++. '+''+`; .;;;;;''.
18
+ :,'''';; `````````
19
+
20
+ ~|~ _ _ _ |~. _|_ _ _ (~ _|_ _ _ __|_ _ _
21
+ _|_| (_)| | |~|><||_|| (/_ (_><| | (_|(_ | (_)|
22
+
23
+ Iron Fixture Extractor
24
+ is
25
+ handy when
26
+ you require complex data extracted from
27
+ crusty legacy
28
+ or
29
+ big ERP
30
+ databases
31
+ for
32
+ test cases.
33
+
34
+ ## Installation
35
+ Add this line to your application's Gemfile:
36
+
37
+ gem 'iron_fixture_extractor'
38
+
39
+ And then execute:
40
+
41
+ $ bundle
42
+
43
+ Or install it yourself as:
44
+
45
+ $ gem install iron_fixture_extractor
46
+
47
+ ## Usage
48
+ The Iron Fixture Extractor gem exposes everything under the Fe
49
+ namespace, we'll refer to it as "Fe" from here on out.
50
+
51
+ Fe is designed to be used in an interactive Ruby shell or Rails console.
52
+ The idea is to poke around your data via your ActiveRecord models, then
53
+ once you have a good dataset, use Fe.extract to load it into fixture
54
+ files you can write tests against.
55
+
56
+ This gem is dirt simple--consider reading the source code
57
+ and test cases directly to clarify any behavioral details this readme
58
+ doesn't cover.
59
+
60
+ ### Extract
61
+
62
+ Fe.extract 'Post.includes(:comments, :author).limit(1)', name => 'first_post_w_comments_and_authors'
63
+
64
+ ### Load Fixtures (BE CAREFUL, THIS DELETES EVERYTHING IN THE TARGET TABLES)
65
+
66
+ Fe.load_db(:first_post_w_comments_and_authors)
67
+
68
+ ### Rebuild Fixture Files
69
+ This uses the fe_manifest.yml's extract_code to re-extract fixtures
70
+ using the same code used to initially create them. Its handy when the live data changes and you want to refresh the fixture files to reflect it.
71
+
72
+ Fe.rebuild(:first_post_w_comments_and_authors)
73
+
74
+ ## How it works
75
+
76
+ ### Extract
77
+ The essense of the Fe.extract algorithm is:
78
+
79
+ for each record given to .extract
80
+ recursively resolve any association pre-loaded in the .association_cache [ActiveRecord] method
81
+ add it to a set of records keyed by model name
82
+ write each set of records as a <model_name>.yml fixture file to test/fe_fixtures/<the :name specified to .extract>/
83
+
84
+ The magic is all in the recursive usage of ActiveRecord::Base#association_cache. This means, that if you do something like:
85
+
86
+ p=Post.first
87
+ p.comments
88
+ Fe.extract(p)
89
+
90
+ you will get 2 fixture files: 1 post record fixture (not-surprising) and N comment fixtures because p.association_cache is populated for :comments on the post instance p.
91
+
92
+ ### Load Fixtures
93
+ This uses the same mechanism as Rails' `rake db:fixtures:load`, aka ActiveRecord::Fixtures.create_fixtures method
94
+
95
+ ### Rebuild Fixture Files
96
+ This is just like .extract, except the code used to do the query is
97
+ pulled from the fe_manifest.yml file.
98
+
99
+ ## Missing Features
100
+ * rake fe:fixtures:extract, fe:fixtures:load_db, and fe:fixtures:rebuild
101
+ ought exist and be available in Rails context via a Railtie. They would simply wrap the capabilities of Fe's extract, load_db, and rebuild method.
102
+ * If you give a non-string arg to .extract, the manifest should resolve
103
+ the .extract_code to be a bunch of look-ups by primary key ala [Post.find(1),Comment.find(2)].
104
+ * The output of each of the main commands should be meaningful, aka,
105
+ make extractor implement a sensible .to_s and .inspect
106
+ * load_db should error if Rails.env or RAILS_ENV is defined and set to
107
+ production
108
+
109
+ ## Contributing
110
+ To run test cases:
111
+
112
+ # clone or fork repo
113
+ cd iron_fixture_extractor
114
+ rake # runs test cases
115
+
116
+ Help on the missing features above would be much appreciated per the
117
+ usual github approach:
118
+
119
+ 1. Fork it
120
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
121
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
122
+ 4. Push to the branch (`git push origin my-new-feature`)
123
+ 5. Create new Pull Request
124
+
125
+ If you have other ideas for this tool, make a Github Issue.
126
+
127
+ ## Footnotes
128
+ I used various ideas from the following blog posts, gists, and existing
129
+ ruby gems, thanks to the authors of these pages:
130
+
131
+ * http://nhw.pl/wp/2009/09/24/extracting-fixtures
132
+ * http://nhw.pl/download/extract_fixtures.rake
133
+ * https://rubygems.org/gems/fixture_builder
134
+ * https://rubygems.org/gems/fixture_dependencies
135
+ * http://topfunky.net/svn/plugins/ar_fixtures/
136
+ * https://gist.github.com/997746
137
+ * https://gist.github.com/2686783
138
+ * http://snippets.dzone.com/posts/show/4729
139
+ * http://rubygems.org/search?utf8=%E2%9C%93&query=fixture
140
+ * http://www.dan-manges.com/blog/38
141
+ * http://www.martinfowler.com/bliki/ObjectMother.html
142
+ * http://asciicasts.com/episodes/158-factories-not-fixtures
data/Rakefile ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+ require 'rake/testtask'
4
+
5
+ Rake::TestTask.new(:test) do |t|
6
+ t.libs << 'lib'
7
+ t.libs << 'test'
8
+ t.pattern = 'test/**/*_test.rb'
9
+ t.verbose = true
10
+ end
11
+ task :default => 'test'
12
+
13
+ desc "Open an irb session preloaded with this library"
14
+ task :console do
15
+ sh "irb -rubygems -I lib -I test -r test_helper -r fe"
16
+ end
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/fe/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Joe Goggins"]
6
+ gem.email = ["goggins@umn.edu"]
7
+ gem.description = %q{When object factories don't work because your data is too complex and creating manual fixtures is cumbersome and brittle: Iron Fixture Extractor (for Rails/ActiveRecord) }
8
+ gem.summary = %q{Simplified dynamic fixture extraction for ActiveRecord}
9
+ gem.homepage = ""
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "iron_fixture_extractor"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = Fe::VERSION
17
+ gem.add_runtime_dependency "activerecord", "~> 3.2.1"
18
+ gem.add_runtime_dependency "activesupport", "~> 3.2.1"
19
+ gem.add_development_dependency "shoulda", "~> 3.0.1"
20
+ gem.add_development_dependency "sqlite3"
21
+ end
data/lib/fe.rb ADDED
@@ -0,0 +1,37 @@
1
+ # NOTE: require 'iron_fixture_extractor', NOT this file
2
+ module Fe
3
+ extend ActiveSupport::Autoload
4
+ autoload :Extractor
5
+
6
+ # global configuration
7
+
8
+ @@fixtures_root = 'test/fe_fixtures'
9
+ mattr_accessor :fixtures_root
10
+
11
+ # Top-level API methods
12
+ class << self
13
+ def extract(*args)
14
+ extractor = Fe::Extractor.new
15
+ extractor.load_from_args(*args)
16
+ extractor.extract
17
+ extractor
18
+ end
19
+
20
+ # NOTE: This is destructive, it will delete everything in the target table
21
+ #
22
+ def load_db(extract_name)
23
+ extractor = Fe::Extractor.new
24
+ extractor.name = extract_name
25
+ extractor.load_from_manifest
26
+ extractor.load_into_database
27
+ extractor
28
+ end
29
+ def rebuild(extract_name)
30
+ extractor = Fe::Extractor.new
31
+ extractor.name = extract_name
32
+ extractor.load_from_manifest
33
+ extractor.extract
34
+ extractor
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,132 @@
1
+ module Fe
2
+ class Extractor
3
+ attr_accessor :input_array, :extract_code, :name, :row_counts,:table_names
4
+
5
+ def extract
6
+ @row_counts = {}
7
+ @table_names = {}
8
+ self.output_hash.each_pair do |key,records|
9
+ @row_counts[key] = records.length
10
+ @table_names[key] = key.constantize.table_name
11
+ end
12
+
13
+ FileUtils.rmdir(self.target_path)
14
+ FileUtils.mkdir_p(self.target_path)
15
+ File.open(self.manifest_file_path,'w') do |file|
16
+ file.write( {:extract_code => self.extract_code,
17
+ :name => self.name,
18
+ :model_names => self.model_names,
19
+ :row_counts => self.row_counts,
20
+ :table_names => self.models.map {|m| m.table_name}
21
+ }.to_yaml)
22
+ end
23
+ self.write_model_fixtures
24
+ end
25
+
26
+ def load_from_args(active_relation_or_array,*args)
27
+ options = args.extract_options!
28
+ @name = (options[:name] || Time.now.strftime("%Y_%m_%d_%H_%M_%S")).to_sym
29
+ if active_relation_or_array.kind_of? String
30
+ @extract_code = active_relation_or_array
31
+ @input_array = Array(eval(active_relation_or_array)).to_a
32
+ else
33
+ @extract_code = "CANNOT_REBUILD_THIS_FIXTURE_SET_USE_STRING_ARG_TO_DOT_EXTRACT_METHOD"
34
+ @input_array = Array(active_relation_or_array).to_a
35
+ end
36
+ end
37
+
38
+ def load_from_manifest
39
+ raise "u gotta set .name to use this method" if self.name.blank?
40
+ h = YAML.load_file(self.manifest_file_path)
41
+ if h[:extract_code].match /CANNOT_REBUILD_THIS_FIXTURE_SET_USE_STRING_ARG_TO_DOT_EXTRACT_METHOD/
42
+ h[:extract_code] = [] # To make stuff not break cause it thinks its a string
43
+ end
44
+ self.load_from_args(h[:extract_code], :name => h[:name])
45
+ @models = h[:model_names].map {|x| x.constantize}
46
+ end
47
+
48
+ def load_into_database
49
+ # necessary to make multiple invocations possible in a single test
50
+ # case possible
51
+ ActiveRecord::Fixtures.reset_cache
52
+ self.models.each do |model|
53
+ ActiveRecord::Fixtures.create_fixtures(self.target_path, model.table_name)
54
+ end
55
+ end
56
+ # Returns a hash with model class names for keys and Set's of AR
57
+ # instances for values
58
+ # aka like this
59
+ # {'Post' => [<#Post id:1>,<#Post id:2>],
60
+ # 'Comment' => [<#Comment id:1>,<#Comment id:2>]}
61
+ #
62
+ def output_hash
63
+ if @output_hash.blank?
64
+ @output_hash = {}
65
+ self.input_array.each do |t|
66
+ recurse(t)
67
+ end
68
+ end
69
+ @output_hash
70
+ end
71
+
72
+ def model_names
73
+ self.output_hash.keys
74
+ end
75
+
76
+ # Note: this behavior is different if load_from_manifest vs
77
+ # load_from_args
78
+ def models
79
+ @models ||= self.model_names.map {|x| x.constantize}
80
+ end
81
+
82
+ def target_path
83
+ File.join(Fe.fixtures_root,self.name.to_s)
84
+ end
85
+
86
+ def manifest_file_path
87
+ File.join(self.target_path,'fe_manifest.yml')
88
+ end
89
+
90
+ def fixture_path_for_model(model_name)
91
+ File.join(self.target_path,"#{model_name.constantize.table_name}.yml")
92
+ end
93
+
94
+ protected
95
+
96
+ # Recursively goes over all association_cache's from the record and builds the output_hash
97
+ # This is the meat-and-potatoes of this tool (plus the the recurse
98
+ # method) is where something interesting is happening
99
+ def recurse(record)
100
+ raise "This gem only knows how to extract stuff w ActiveRecord" unless record.kind_of? ActiveRecord::Base
101
+ @output_hash[record.class.to_s] ||= Set.new # Set ensures no duplicates
102
+ @output_hash[record.class.to_s].add record
103
+ record.association_cache.each do |assoc_cache|
104
+ assoc_name = assoc_cache.first
105
+ assoc_value = assoc_cache.last.target
106
+ unless assoc_value.kind_of? Array
107
+ assoc_value = Array(assoc_value)
108
+ end
109
+ assoc_value.each do |a|
110
+ self.recurse(a)
111
+ end
112
+ end
113
+ end
114
+ def write_model_fixtures
115
+ FileUtils.mkdir_p(self.target_path)
116
+ self.output_hash.each_pair do |key,records|
117
+ # key is an ActiveRecord class
118
+ # records is an array of records to write
119
+ File.open(self.fixture_path_for_model(key),'w') do |file|
120
+ # props to Rails Receipts 3rd edition book for these 4 lines
121
+ # below
122
+ file.write records.inject({}) {|hash, record|
123
+ # Array() bit done to support composite primary keys
124
+ fixture_name = "r#{Array(record.id).join('_')}"
125
+ hash[fixture_name] = record.attributes
126
+ hash
127
+ }.to_yaml
128
+ end
129
+ end
130
+ end
131
+ end
132
+ end
data/lib/fe/version.rb ADDED
@@ -0,0 +1,3 @@
1
+ module Fe
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,7 @@
1
+ require "active_record"
2
+ require 'active_record/fixtures'
3
+ require "active_support/all"
4
+ require "set" # introduced in Ruby standard lib in 1.9
5
+ require "fileutils"
6
+ require "fe/version"
7
+ require 'fe'
@@ -0,0 +1,86 @@
1
+ require 'test_helper'
2
+ class BasicUsage < ActiveSupport::TestCase
3
+ context "Main API" do
4
+ setup do
5
+ @extract_code = 'Post.includes(:comments, :author).limit(1)'
6
+ @extract_name = :first_post_w_comments_and_authors
7
+ end
8
+ context ".extract" do
9
+ setup do
10
+ FeTestEnv.setup
11
+ end
12
+ teardown do
13
+ FeTestEnv.teardown
14
+ end
15
+ should "provide the right output, and put the file in the right place" do
16
+ extractor = Fe.extract(@extract_code, :name => @extract_name)
17
+ assert_kind_of Fe::Extractor, extractor
18
+ assert (%w(Post Comment Author) - extractor.model_names).empty?, "only these keys should exist"
19
+ assert_equal @extract_name, extractor.name
20
+ assert_equal Post.table_name, extractor.table_names['Post']
21
+ assert File.exists?(File.join(Fe.fixtures_root,'first_post_w_comments_and_authors','fe_manifest.yml')), "The file that allows the fixtures to get rebuilt"
22
+ assert_equal 1, extractor.row_counts['Post']
23
+ assert File.exists?(File.join(Fe.fixtures_root,'first_post_w_comments_and_authors',"#{Post.table_name}.yml")), "The file is created"
24
+ end
25
+ end
26
+ context ".load_db" do
27
+ setup do
28
+ FeTestEnv.setup # regular production db
29
+ extract_hash = Fe.extract(@extract_code, :name => @extract_name)
30
+ FeTestEnv.the_env = 'fake_test'
31
+ FeTestEnv.recreate_schema_without_data
32
+ end
33
+ teardown do
34
+ FeTestEnv.teardown
35
+ end
36
+ should "provide the ability to load fixtures" do
37
+ assert_equal 0, Post.count
38
+ assert_equal 0, Comment.count
39
+ assert_equal 0, Author.count
40
+ Fe.load_db(@extract_name)
41
+ assert_equal 1, Post.count
42
+ assert_equal 1, Comment.count
43
+ assert_equal 1, Author.count
44
+ end
45
+ end
46
+ context ".rebuild" do
47
+ setup do
48
+ FeTestEnv.setup
49
+ @extractor = Fe.extract(@extract_code, :name => @extract_name)
50
+ end
51
+ teardown do
52
+ # FeTestEnv.teardown
53
+ end
54
+ should "be able to rebuild the fixture files from the manifest" do
55
+ # TODO: continue here, should delete a comment, then rebuild,
56
+ # and assert
57
+ # all files mtimes have changed
58
+ # there is no comment file
59
+ results = eval(@extract_code)
60
+ first_post = results.first
61
+ assert_match /First post/i, first_post.name
62
+ first_post.name = "UPDATED_FIRST_POST"
63
+ first_post.save!
64
+ rebuild_hash = Fe.rebuild(@extract_name)
65
+ assert_match /UPDATED_FIRST_POST/, File.read(@extractor.fixture_path_for_model('Post'))
66
+ #assert_equal 0, Post.count
67
+ end
68
+ end
69
+ end
70
+ # NOT SURE IF THESE MATTER, probably do..commented out for now
71
+ #context "2nd tier API" do
72
+ #should "provide an extractor class" do
73
+ #extract_code = Post.first
74
+ #e=Fe::Extractor.new
75
+ #e.input_array = [extract_code]
76
+ #assert_kind_of Hash, e.output_hash
77
+ #assert_equal Post, e.output_hash.keys.first
78
+ #assert_equal extract_code, e.output_hash[Post].first
79
+ #end
80
+ #should "work with recursive loading" do
81
+ #e=Fe::Extractor.new
82
+ #e.input_array = Post.includes(:comments, :author)
83
+ #assert (e.output_hash.keys - [Post,Comment,Author]).empty?, "There are only keys for the eager loaded models"
84
+ #end
85
+ #end
86
+ end
@@ -0,0 +1,11 @@
1
+ fake_production:
2
+ adapter: sqlite3
3
+ database: test/tmp/fake_production.sqlite3
4
+ pool: 5
5
+ timeout: 5000
6
+
7
+ fake_test:
8
+ adapter: sqlite3
9
+ database: test/tmp/fake_test.sqlite3
10
+ pool: 5
11
+ timeout: 5000
@@ -0,0 +1,84 @@
1
+ class FeTestEnv
2
+ class << self
3
+ def models
4
+ [:post,:comment,:author,:group,:group_member]
5
+ end
6
+ def model_classes
7
+ self.models.map {|x| x.to_s.classify.constantize}
8
+ end
9
+ def fixtures_root
10
+ 'test/tmp/fe_fixtures'
11
+ end
12
+ def migrate_schema
13
+ ActiveRecord::Migrator.migrate(File.join(File.dirname(__FILE__),'migrations'),nil)
14
+ end
15
+ def migrate_fake_production_data
16
+ ActiveRecord::Migrator.migrate(File.join(File.dirname(__FILE__),'test_data_migrations'),nil)
17
+ end
18
+ def destroy_tmp_test_stuff #sqlite dbs and fixture files
19
+ FileUtils.rm_rf Dir.glob("#{self.tmp_directory}/*")
20
+ end
21
+ def tmp_directory
22
+ File.join(File.dirname(__FILE__), "tmp")
23
+ end
24
+ def establish_connection
25
+ ActiveRecord::Base.establish_connection(self.connections[self.the_env])
26
+ ActiveRecord::Base.connection
27
+ end
28
+ def connections
29
+ YAML::load_file(File.join(File.dirname(__FILE__), 'config', 'database.yml'))
30
+ end
31
+ def load_models
32
+ self.models.each do |x|
33
+ require "models/#{x}"
34
+ end
35
+ end
36
+
37
+ def unload_models
38
+ # DOESN"T WORK!!!!!!!!!
39
+ self.models.each do |x|
40
+ Object.send(:remove_const, "::#{x.to_s.capitalize}")
41
+ end
42
+ end
43
+ def make_fixtures_dir_and_set_fixtures_root
44
+ FileUtils.mkdir_p FeTestEnv.fixtures_root
45
+ Fe.fixtures_root = FeTestEnv.fixtures_root
46
+ end
47
+ attr_accessor :the_env
48
+
49
+ def setup_methods
50
+ @the_env ||= 'fake_production'
51
+ [
52
+ :make_fixtures_dir_and_set_fixtures_root,
53
+ :load_models,
54
+ :establish_connection,
55
+ :migrate_schema,
56
+ :migrate_fake_production_data]
57
+ end
58
+ def setup
59
+ self.setup_methods.each {|m| send m}
60
+ end
61
+ def teardown_methods
62
+ [
63
+ :destroy_tmp_test_stuff
64
+ ]
65
+ end
66
+ def teardown
67
+ self.teardown_methods.each {|m| send m}
68
+ end
69
+ def recreate_schema_without_data
70
+ f=File.join(self.tmp_directory,"#{self.the_env}.sqlite3")
71
+ begin
72
+ FileUtils.rm f
73
+ rescue
74
+ puts "#{f} does not exist"
75
+ end
76
+ [:load_models, :establish_connection,:migrate_schema].each {|m| send m}
77
+ end
78
+ def reload
79
+ teardown
80
+ setup
81
+ end
82
+ end
83
+ end
84
+
@@ -0,0 +1,12 @@
1
+ class CreatePosts < ActiveRecord::Migration
2
+ def change
3
+ create_table :posts do |t|
4
+ t.belongs_to :author
5
+ t.string :name
6
+ t.string :content
7
+
8
+ t.timestamps
9
+ end
10
+ add_index :posts, :author_id
11
+ end
12
+ end
@@ -0,0 +1,9 @@
1
+ class CreateAuthors < ActiveRecord::Migration
2
+ def change
3
+ create_table :authors do |t|
4
+ t.string :name
5
+
6
+ t.timestamps
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,13 @@
1
+ class CreateComments < ActiveRecord::Migration
2
+ def change
3
+ create_table :comments do |t|
4
+ t.belongs_to :author
5
+ t.belongs_to :post
6
+ t.string :content
7
+
8
+ t.timestamps
9
+ end
10
+ add_index :comments, :author_id
11
+ add_index :comments, :post_id
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ class CreateGroupMembers < ActiveRecord::Migration
2
+ def change
3
+ create_table :group_members do |t|
4
+ t.belongs_to :author
5
+ t.belongs_to :group
6
+ t.string :role
7
+
8
+ t.timestamps
9
+ end
10
+ add_index :group_members, :author_id
11
+ add_index :group_members, :group_id
12
+ end
13
+ end
@@ -0,0 +1,9 @@
1
+ class CreateGroups < ActiveRecord::Migration
2
+ def change
3
+ create_table :groups do |t|
4
+ t.string :name
5
+
6
+ t.timestamps
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,5 @@
1
+ class Author < ActiveRecord::Base
2
+ attr_accessible :name
3
+ has_many :posts
4
+ has_many :comments
5
+ end
@@ -0,0 +1,5 @@
1
+ class Comment < ActiveRecord::Base
2
+ belongs_to :author
3
+ belongs_to :post
4
+ attr_accessible :content
5
+ end
@@ -0,0 +1,5 @@
1
+ class Group < ActiveRecord::Base
2
+ attr_accessible :name
3
+ has_many :group_members
4
+ has_many :authors, through: :group_members
5
+ end
@@ -0,0 +1,5 @@
1
+ class GroupMember < ActiveRecord::Base
2
+ belongs_to :author
3
+ belongs_to :group
4
+ attr_accessible :role
5
+ end
@@ -0,0 +1,5 @@
1
+ class Post < ActiveRecord::Base
2
+ belongs_to :author
3
+ has_many :comments
4
+ attr_accessible :content, :name
5
+ end
@@ -0,0 +1,14 @@
1
+ class CreateSomeData < ActiveRecord::Migration
2
+ def up
3
+ a=Author.create name: "Joe"
4
+ p1=a.posts.create name: "First post"
5
+ p1.comments.create content: "This is crap"
6
+ p2=a.posts.create name: "Second post"
7
+ p2.comments.create content: "This is great"
8
+
9
+ a2=Author.create name: "Bill"
10
+ g=Group.create name: "Group 1"
11
+ g.authors << a2
12
+ g.save
13
+ end
14
+ end
@@ -0,0 +1,10 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ Bundler.setup
4
+ require 'shoulda'
5
+ require 'iron_fixture_extractor'
6
+ # TEMP, COMMENT OUT IF NEEDED
7
+ require 'sqlite3'
8
+ require 'ruby-debug'
9
+ require 'fe_test_env'
10
+ FeTestEnv.reload
metadata ADDED
@@ -0,0 +1,136 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: iron_fixture_extractor
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.1.0
6
+ platform: ruby
7
+ authors:
8
+ - Joe Goggins
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2012-06-16 00:00:00 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: activerecord
17
+ prerelease: false
18
+ requirement: &id001 !ruby/object:Gem::Requirement
19
+ none: false
20
+ requirements:
21
+ - - ~>
22
+ - !ruby/object:Gem::Version
23
+ version: 3.2.1
24
+ type: :runtime
25
+ version_requirements: *id001
26
+ - !ruby/object:Gem::Dependency
27
+ name: activesupport
28
+ prerelease: false
29
+ requirement: &id002 !ruby/object:Gem::Requirement
30
+ none: false
31
+ requirements:
32
+ - - ~>
33
+ - !ruby/object:Gem::Version
34
+ version: 3.2.1
35
+ type: :runtime
36
+ version_requirements: *id002
37
+ - !ruby/object:Gem::Dependency
38
+ name: shoulda
39
+ prerelease: false
40
+ requirement: &id003 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 3.0.1
46
+ type: :development
47
+ version_requirements: *id003
48
+ - !ruby/object:Gem::Dependency
49
+ name: sqlite3
50
+ prerelease: false
51
+ requirement: &id004 !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: "0"
57
+ type: :development
58
+ version_requirements: *id004
59
+ description: "When object factories don't work because your data is too complex and creating manual fixtures is cumbersome and brittle: Iron Fixture Extractor (for Rails/ActiveRecord) "
60
+ email:
61
+ - goggins@umn.edu
62
+ executables: []
63
+
64
+ extensions: []
65
+
66
+ extra_rdoc_files: []
67
+
68
+ files:
69
+ - .gitignore
70
+ - Gemfile
71
+ - LICENSE
72
+ - README.md
73
+ - Rakefile
74
+ - iron_fixture_extractor.gemspec
75
+ - lib/fe.rb
76
+ - lib/fe/extractor.rb
77
+ - lib/fe/version.rb
78
+ - lib/iron_fixture_extractor.rb
79
+ - test/basic_usage_test.rb
80
+ - test/config/database.yml
81
+ - test/fe_test_env.rb
82
+ - test/migrations/20120604043601_create_posts.rb
83
+ - test/migrations/20120604043602_create_authors.rb
84
+ - test/migrations/20120604043639_create_comments.rb
85
+ - test/migrations/20120604043808_create_group_members.rb
86
+ - test/migrations/20120604043818_create_groups.rb
87
+ - test/models/author.rb
88
+ - test/models/comment.rb
89
+ - test/models/group.rb
90
+ - test/models/group_member.rb
91
+ - test/models/post.rb
92
+ - test/test_data_migrations/001_create_some_data.rb
93
+ - test/test_helper.rb
94
+ homepage: ""
95
+ licenses: []
96
+
97
+ post_install_message:
98
+ rdoc_options: []
99
+
100
+ require_paths:
101
+ - lib
102
+ required_ruby_version: !ruby/object:Gem::Requirement
103
+ none: false
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ version: "0"
108
+ required_rubygems_version: !ruby/object:Gem::Requirement
109
+ none: false
110
+ requirements:
111
+ - - ">="
112
+ - !ruby/object:Gem::Version
113
+ version: "0"
114
+ requirements: []
115
+
116
+ rubyforge_project:
117
+ rubygems_version: 1.8.24
118
+ signing_key:
119
+ specification_version: 3
120
+ summary: Simplified dynamic fixture extraction for ActiveRecord
121
+ test_files:
122
+ - test/basic_usage_test.rb
123
+ - test/config/database.yml
124
+ - test/fe_test_env.rb
125
+ - test/migrations/20120604043601_create_posts.rb
126
+ - test/migrations/20120604043602_create_authors.rb
127
+ - test/migrations/20120604043639_create_comments.rb
128
+ - test/migrations/20120604043808_create_group_members.rb
129
+ - test/migrations/20120604043818_create_groups.rb
130
+ - test/models/author.rb
131
+ - test/models/comment.rb
132
+ - test/models/group.rb
133
+ - test/models/group_member.rb
134
+ - test/models/post.rb
135
+ - test/test_data_migrations/001_create_some_data.rb
136
+ - test/test_helper.rb