iron_fixture_extractor 0.1.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.md ADDED
@@ -0,0 +1,8 @@
1
+ ## 0.1.1 -> 1.0.0
2
+ * Fe.extract must be given a string or array of ActiveRecord queries
3
+ like this
4
+
5
+ * Fe.get_hash, truncate_tables_for, execute_extract_code,
6
+ to_factory_girl_string, make their debut...only get_hash is truly
7
+ awesome...the others...not so much
8
+
data/Gemfile CHANGED
@@ -1,8 +1,12 @@
1
1
  source 'https://rubygems.org'
2
+
2
3
  # TEMP CRAP FOR DEV, COMMENT OUT OR DELETE
4
+ #
5
+ gem 'debugger'
6
+
3
7
  # USED w ruby 1.9.2
4
8
  # http://dirk.net/2010/04/17/ruby-debug-with-ruby-19x-and-rails-3-on-rvm/
5
- gem 'ruby-debug19', :require => 'ruby-debug'
9
+ #gem 'ruby-debug19', :require => 'ruby-debug'
6
10
  gem 'rake'
7
11
  # Specify your gem's dependencies in iron_fixture_extractor.gemspec
8
12
  gemspec
data/README.md CHANGED
@@ -1,110 +1,77 @@
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:
1
+ # About Iron Fixture Extractor
36
2
 
37
- gem 'iron_fixture_extractor'
3
+ For extracting complex data from staging and production databases to be used for automated testing (works great with whatever testing framework your using).
38
4
 
39
- And then execute:
5
+ Its best when:
6
+ * your data is too complex for factories (like when integrating with legacy systems, ERP systems, etc)
7
+ * creating and maintaining manual fixtures is cumbersome and brittle (always, :))
40
8
 
41
- $ bundle
9
+ Its good for:
42
10
 
43
- Or install it yourself as:
11
+ Pulling data from a staging database containing vetted data that has
12
+ been built up by the development team, users, or business analysts to be used
13
+ as "archetypical" data structures in test cases, demonstration.
44
14
 
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.
15
+ Taking snapshots of production data that has triggered unexpected errors to be incorporated into test cases for closer inspection and correction.
50
16
 
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.
17
+ How it works:
55
18
 
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.
19
+ Feed it an array of ActiveRecord objects or ActiveRelation object and it will allow you to extract, load, and rebuild the records associated with your queries.
59
20
 
60
- ### Extract
21
+ ## Usage (typically in a console)
22
+ ### Extract (fixture files)
61
23
 
62
- Fe.extract 'Post.includes(:comments, :author).limit(1)', name => 'first_post_w_comments_and_authors'
24
+ Fe.extract 'Post.includes(:comments, :author).limit(1)', :name => 'first_post_w_comments_and_authors'
63
25
 
64
- ### Load Fixtures (BE CAREFUL, THIS DELETES EVERYTHING IN THE TARGET TABLES)
26
+ ### Load (dataset into database)
65
27
 
66
28
  Fe.load_db(:first_post_w_comments_and_authors)
67
29
 
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.
30
+ ### Rebuild (fixture files associated with the initial extraction)
71
31
 
72
32
  Fe.rebuild(:first_post_w_comments_and_authors)
73
33
 
74
- ## How it works
34
+ ### Pull up a hash from a particular fixture file (very handy in test cases)
35
+ Fe.get_hash(:first_post_w_comments_and_authors, Post, 'r1')
36
+ or
37
+ Fe.get_hash(:first_post_w_comments_and_authors, Post, :first)
38
+ or
39
+ Fe.get_hash(:first_post_w_comments_and_authors, Post, :last)
75
40
 
76
- ### Extract
77
- The essense of the Fe.extract algorithm is:
41
+ ## Installation
42
+ Add this line to your application's Gemfile:
78
43
 
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>/
44
+ gem 'iron_fixture_extractor'
83
45
 
84
- The magic is all in the recursive usage of ActiveRecord::Base#association_cache. This means, that if you do something like:
46
+ And then execute:
85
47
 
86
- p=Post.first
87
- p.comments
88
- Fe.extract(p)
48
+ $ bundle
89
49
 
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.
50
+ Or install it yourself as:
91
51
 
92
- ### Load Fixtures
93
- This uses the same mechanism as Rails' `rake db:fixtures:load`, aka ActiveRecord::Fixtures.create_fixtures method
52
+ $ gem install iron_fixture_extractor
53
+
54
+ ### Extract
55
+ The essense of the Fe.extract is dirt simple:
56
+
57
+ for each record given to Fe.extract
58
+ recursively resolve any association pre-loaded in the .association_cache [ActiveRecord] method
59
+ add it to a set of records keyed by model name
60
+ write each set of records as a <TheModel.table_name>.yml fixture
61
+ write a fe_manifest.yml that will allow you to later change the query, inspect row counts, and rebuild the fixtures by re-executing the originate queries
94
62
 
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
63
 
99
64
  ## 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
65
  * If you give a non-string arg to .extract, the manifest should resolve
103
66
  the .extract_code to be a bunch of look-ups by primary key ala [Post.find(1),Comment.find(2)].
104
67
  * The output of each of the main commands should be meaningful, aka,
105
68
  make extractor implement a sensible .to_s and .inspect
106
69
  * load_db should error if Rails.env or RAILS_ENV is defined and set to
107
70
  production
71
+ * An :extract_schema option passed to .extract that uses `rake db:structure:dump` functionality
72
+ or ActiveRecord::Base.connection.structure_dump to create .sql files containing a "create table" statement
73
+ for each distinct model class. This would allow you to completely de-couple your test cases + fixtures
74
+ from the external databases they were extracted from.
108
75
 
109
76
  ## Contributing
110
77
  To run test cases:
@@ -118,9 +85,11 @@ usual github approach:
118
85
 
119
86
  1. Fork it
120
87
  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
88
+ 3. Ensure the test cases run
89
+ 4. Copy one of the test cases (like basic_test.rb), rename, rip out the guts, and add some tests + code to the app
90
+ 5. Commit your changes (`git commit -am 'Added some feature'`)
91
+ 6. Push to the branch (`git push origin my-new-feature`)
92
+ 7. Create new Pull Request
124
93
 
125
94
  If you have other ideas for this tool, make a Github Issue.
126
95
 
@@ -18,4 +18,5 @@ Gem::Specification.new do |gem|
18
18
  gem.add_runtime_dependency "activesupport", "~> 3.2.1"
19
19
  gem.add_development_dependency "shoulda", "~> 3.0.1"
20
20
  gem.add_development_dependency "sqlite3"
21
+ gem.add_development_dependency "factory_girl"
21
22
  end
data/lib/fe.rb CHANGED
@@ -1,7 +1,10 @@
1
1
  # NOTE: require 'iron_fixture_extractor', NOT this file
2
2
  module Fe
3
+ class InvalidSourceModelToMapFrom < Exception; end
3
4
  extend ActiveSupport::Autoload
4
5
  autoload :Extractor
6
+ autoload :FactoryGirlDslMethods
7
+ require 'fe/railtie' if defined?(Rails)
5
8
 
6
9
  # global configuration
7
10
 
@@ -10,6 +13,12 @@ module Fe
10
13
 
11
14
  # Top-level API methods
12
15
  class << self
16
+ # Extract a set up Yml for one or more active relation alls
17
+ # You can call this in two ways
18
+ # Fe.extract('Post.all', :name => :bla)
19
+ # or
20
+ # Fe.extract('[Post.all,Comment.all]', :name => :bla2)
21
+ #
13
22
  def extract(*args)
14
23
  extractor = Fe::Extractor.new
15
24
  extractor.load_from_args(*args)
@@ -17,15 +26,27 @@ module Fe
17
26
  extractor
18
27
  end
19
28
 
29
+ # Insert fixtures into tables from the yml files in the
30
+ # "extract_name" fixture set
31
+ # If you specify a map_models hash here for the last arg like
32
+ # Post => DifferentPost
33
+ # It will load the fixtures into a different table than whats listed
34
+ # in the manifest
20
35
  # NOTE: This is destructive, it will delete everything in the target table
21
36
  #
22
- def load_db(extract_name)
37
+ def load_db(extract_name, map_models={})
23
38
  extractor = Fe::Extractor.new
24
39
  extractor.name = extract_name
25
40
  extractor.load_from_manifest
41
+ unless map_models.empty?
42
+ extractor.map_models_hash = map_models
43
+ end
26
44
  extractor.load_into_database
27
45
  extractor
28
46
  end
47
+
48
+ # Rebuilds an existing fixture set from a fe_manifest.yml
49
+ #
29
50
  def rebuild(extract_name)
30
51
  extractor = Fe::Extractor.new
31
52
  extractor.name = extract_name
@@ -33,5 +54,106 @@ module Fe
33
54
  extractor.extract
34
55
  extractor
35
56
  end
57
+
58
+
59
+ # Used if you want to get a hash representation of a particular
60
+ # fixture in a fixture set for a given model
61
+ #
62
+ # Used like
63
+ # h = Fe.get_hash(:first_post_w_comments_and_authors, Post, 'r1')
64
+ # => {:id => 1, :name => 'first post', ....}
65
+ # in the console
66
+ # or in a factory declaration like this
67
+ #
68
+ # FactoryGirl.define do
69
+ # factory :fe4,
70
+ # :class => Post,
71
+ # &Fe.get_hash(:first_post_w_comments_and_authors,Post,"r1").to_factory_girl_string.to_proc
72
+ # end
73
+ #
74
+ # Kinda meta, but somewhat useful
75
+ #
76
+ def get_hash(extract_name, model_name, fixture_name)
77
+ model_name = model_name.to_s
78
+ extractor = Fe::Extractor.new
79
+ extractor.name = extract_name
80
+
81
+ begin
82
+ h=extractor.fixture_hash_for_model(model_name)
83
+ rescue Exception => e
84
+ raise "Fe::Extractor#fixture_hash_for_model broke on #{model_name}, perhaps the yml file does exist?"
85
+ end
86
+ raise "#{h.inspect} Fe::Extractor#fixture_hash_for_model did not return a hash (broken fixture file)" unless h.kind_of? Hash
87
+
88
+ fixture_path_for_model = extractor.fixture_path_for_model(model_name)
89
+
90
+ if fixture_name.kind_of? Symbol
91
+ case fixture_name
92
+ when :first
93
+ a_hash = h.to_a.first.last
94
+ when :last
95
+ a_hash = h.to_a.last.last
96
+ else
97
+ raise "symbols can be :first or :last"
98
+ end
99
+ elsif fixture_name.kind_of? String
100
+ raise "Fixture of the name #{fixture_name} did not exist in in #{fixture_path_for_model}" unless h.has_key?(fixture_name)
101
+ a_hash = h[fixture_name]
102
+ else
103
+ raise "fixture name must be a string or a symbol like :first or :laset"
104
+ end
105
+ a_hash.define_singleton_method(:to_factory_girl_string) do
106
+ s=<<-EOS
107
+ x = #{model_name}.new(Fe.get_hash(:#{extract_name},#{model_name},"#{fixture_name}"))
108
+ EOS
109
+ model_name.constantize.column_names.each do |col|
110
+ s << "#{col} x.#{col}\n"
111
+ end
112
+ s.instance_eval do
113
+ def to_proc
114
+ Proc.new {
115
+ self
116
+ }
117
+ end
118
+ end
119
+ s
120
+ end
121
+ a_hash
122
+ end
123
+
124
+ # Execute the ActiveRecord query associated with the extract set
125
+ #
126
+ def execute_extract_code(extract_name)
127
+ extractor = Fe::Extractor.new
128
+ extractor.name = extract_name
129
+ extractor.load_from_manifest
130
+ extractor.load_input_array_by_executing_extract_code
131
+ extractor.input_array
132
+ end
133
+
134
+
135
+ # Truncate all tables referenced in an extract set
136
+ #
137
+ def truncate_tables_for(extract_name)
138
+ extractor = Fe::Extractor.new
139
+ extractor.name = extract_name
140
+ extractor.load_from_manifest
141
+ extractor.models.each do |model|
142
+ case ActiveRecord::Base.connection.adapter_name
143
+ when /mysql|oracle|postgresql/i
144
+ # Its dumb that this isn't in active record natively
145
+ # https://github.com/rails/rails/issues/5510
146
+ ActiveRecord::Base.connection.execute("truncate table #{model.table_name}")
147
+ else
148
+ model.delete_all
149
+ end
150
+ end
151
+ true
152
+ end
153
+
154
+ def augment_factory_girl!
155
+ FactoryGirl::Syntax::Default::DSL.send(:include, Fe::FactoryGirlDslMethods)
156
+ end
36
157
  end
37
158
  end
159
+
data/lib/fe/extractor.rb CHANGED
@@ -1,8 +1,9 @@
1
1
  module Fe
2
2
  class Extractor
3
- attr_accessor :input_array, :extract_code, :name, :row_counts,:table_names
3
+ attr_accessor :input_array, :extract_code, :name, :row_counts,:table_names, :manifest_hash
4
4
 
5
5
  def extract
6
+ load_input_array_by_executing_extract_code
6
7
  @row_counts = {}
7
8
  @table_names = {}
8
9
  self.output_hash.each_pair do |key,records|
@@ -10,47 +11,102 @@ module Fe
10
11
  @table_names[key] = key.constantize.table_name
11
12
  end
12
13
 
13
- FileUtils.rmdir(self.target_path)
14
+ if File.directory?(self.target_path)
15
+ FileUtils.remove_dir(self.target_path,:force => true)
16
+ end
14
17
  FileUtils.mkdir_p(self.target_path)
18
+ @manifest_hash = {:extract_code => self.extract_code,
19
+ :name => self.name,
20
+ :model_names => self.model_names,
21
+ :row_counts => self.row_counts,
22
+ :table_names => self.models.map {|m| m.table_name}
23
+ }
15
24
  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)
25
+ file.write(@manifest_hash.to_yaml)
22
26
  end
23
27
  self.write_model_fixtures
24
28
  end
25
29
 
30
+ # This is called from 2 types of invocations
31
+ # Fe.extract('Post.all', :name => :bla)
32
+ # or
33
+ # Fe.extract('[Post.all,Comment.all]', :name => :bla2)
34
+ #
26
35
  def load_from_args(active_relation_or_array,*args)
27
36
  options = args.extract_options!
28
37
  @name = (options[:name] || Time.now.strftime("%Y_%m_%d_%H_%M_%S")).to_sym
29
38
  if active_relation_or_array.kind_of? String
30
39
  @extract_code = active_relation_or_array
31
- @input_array = Array(eval(active_relation_or_array)).to_a
32
40
  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
41
+ raise "Extract code must be a string, so .rebuild can be called"
35
42
  end
36
43
  end
37
44
 
45
+ def load_input_array_by_executing_extract_code
46
+ @input_array = Array(eval(@extract_code)).to_a
47
+ end
48
+
38
49
  def load_from_manifest
39
50
  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
51
+ @manifest_hash = YAML.load_file(self.manifest_file_path)
52
+ @extract_code = @manifest_hash[:extract_code]
53
+ @name = @manifest_hash[:name]
54
+ @models = @manifest_hash[:model_names].map {|x| x.constantize}
55
+ end
56
+
57
+ def map_models_hash=(map_models_hash)
58
+ unless (map_models_hash.keys - self.models).empty?
59
+ raise InvalidSourceModelToMapFrom.new "your map models hash must contain keys representing class names that exist in the fe_manifest.yml"
43
60
  end
44
- self.load_from_args(h[:extract_code], :name => h[:name])
45
- @models = h[:model_names].map {|x| x.constantize}
61
+ @map_models_hash = map_models_hash
46
62
  end
47
63
 
64
+ def map_models_hash
65
+ if @map_models_hash.nil?
66
+ {}
67
+ else
68
+ @map_models_hash
69
+ end
70
+ end
71
+
72
+
73
+ # Loads data from each fixture file in the extract set using
74
+ # ActiveRecord::Fixtures
75
+ #
48
76
  def load_into_database
49
77
  # necessary to make multiple invocations possible in a single test
50
78
  # case possible
51
79
  ActiveRecord::Fixtures.reset_cache
52
80
  self.models.each do |model|
53
- ActiveRecord::Fixtures.create_fixtures(self.target_path, model.table_name)
81
+ if self.map_models_hash.has_key?(model)
82
+ raise "Unfortunately, this is not implemented...from the implementation of .create_fixtures it seems impossible...keeping this code in case its not"
83
+ h = {model.table_name => self.map_models_hash[model]}
84
+ ActiveRecord::Fixtures.create_fixtures(self.target_path, model.table_name, h)
85
+ else
86
+ ActiveRecord::Fixtures.create_fixtures(self.target_path, model.table_name)
87
+ end
88
+ case ActiveRecord::Base.connection.adapter_name
89
+ when /oracle/i
90
+ if model.column_names.include? "id"
91
+ count = model.count
92
+ sequence_name = model.sequence_name.to_s
93
+ max_id = model.maximum(:id)
94
+ next_id = max_id.nil? ? 1 : max_id.to_i + 1
95
+ begin
96
+ ActiveRecord::Base.connection.execute("drop sequence #{sequence_name}")
97
+ rescue
98
+ puts "[Iron Fixture Extractor] WARNING: couldnt drop the sequence #{sequence_name}, (but who cares!)"
99
+ end
100
+ begin
101
+ q="create sequence #{sequence_name} increment by 1 start with #{next_id}"
102
+ ActiveRecord::Base.connection.execute(q)
103
+ rescue
104
+ puts "[Iron Fixture Extractor] WARNING: couldnt create the sequence #{sequence_name}"
105
+ end
106
+ end
107
+ else
108
+ # Do nothing, only oracle adapters need this
109
+ end
54
110
  end
55
111
  end
56
112
  # Returns a hash with model class names for keys and Set's of AR
@@ -63,7 +119,13 @@ module Fe
63
119
  if @output_hash.blank?
64
120
  @output_hash = {}
65
121
  self.input_array.each do |t|
66
- recurse(t)
122
+ if t.kind_of?(Array) || t.kind_of?(ActiveRecord::Relation)
123
+ t.each do |ar_object|
124
+ recurse(ar_object)
125
+ end
126
+ else
127
+ recurse(t)
128
+ end
67
129
  end
68
130
  end
69
131
  @output_hash
@@ -91,15 +153,38 @@ module Fe
91
153
  File.join(self.target_path,"#{model_name.constantize.table_name}.yml")
92
154
  end
93
155
 
156
+ def fixture_hash_for_model(model_name)
157
+ model_name = model_name.to_s
158
+ if @fixture_hashes.nil?
159
+ @fixture_hashes = {}
160
+ end
161
+ if @fixture_hashes.has_key?(model_name)
162
+ @fixture_hashes[model_name]
163
+ else
164
+ @fixture_hashes[model_name] = YAML.load_file(self.fixture_path_for_model(model_name))
165
+ end
166
+ @fixture_hashes[model_name]
167
+ end
94
168
  protected
95
169
 
96
170
  # Recursively goes over all association_cache's from the record and builds the output_hash
97
171
  # This is the meat-and-potatoes of this tool (plus the the recurse
98
172
  # method) is where something interesting is happening
173
+ #
174
+ # TODO: To work with ActiveRecord 2.3.x, we'll need to recurse using this logic: (from activerecord-2.3.14/lib/active_record/associations.rb)
175
+ # # Clears out the association cache
176
+ # def clear_association_cache #:nodoc:
177
+ # self.class.reflect_on_all_associations.to_a.each do |assoc|
178
+ # instance_variable_set "@#{assoc.name}", nil
179
+ # end unless self.new_record?
180
+ # end
181
+ #
182
+ #
99
183
  def recurse(record)
100
184
  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
185
+ key = record.class.base_class.to_s # the base_class is key for correctly handling STI
186
+ @output_hash[key] ||= Set.new # Set ensures no duplicates
187
+ @output_hash[key].add record
103
188
  record.association_cache.each do |assoc_cache|
104
189
  assoc_name = assoc_cache.first
105
190
  assoc_value = assoc_cache.last.target
@@ -123,6 +208,10 @@ module Fe
123
208
  # Array() bit done to support composite primary keys
124
209
  fixture_name = "r#{Array(record.id).join('_')}"
125
210
  hash[fixture_name] = record.attributes
211
+ # dump serialized attributes
212
+ record.serialized_attributes.each do |attr, serializer|
213
+ hash[fixture_name][attr] = serializer.dump(hash[fixture_name][attr])
214
+ end
126
215
  hash
127
216
  }.to_yaml
128
217
  end
@@ -0,0 +1,28 @@
1
+ module Fe
2
+ module FactoryGirlDslMethods
3
+ def fe_factory(name, options = {})
4
+ unless extract_name = options.delete(:extract_name)
5
+ raise "Must specify extract_name (the fixture set name)"
6
+ end
7
+ unless fixture_name = options.delete(:fixture_name)
8
+ raise "Must specify fixture_name" # TODO:Later, make this default to :first once impelmented in Fe
9
+ end
10
+ unless options.has_key?(:class)
11
+ raise "Must specify the class when using with iron fixture extractor"
12
+ end
13
+
14
+ # CONTINUE HERE. We need to figure out how to build a
15
+ # block for Factory girl from the hash that lives in the yaml.
16
+ #
17
+ fe_hash = Fe.get_hash(extract_name, options[:class],fixture_name)
18
+
19
+ the_block = Proc.new {
20
+ }
21
+
22
+ factory(name,options,&the_block)
23
+
24
+ factory_inst = ::FactoryGirl.factory_by_name(name)
25
+ # require 'debugger'; debugger; puts 'DSLExt'
26
+ end
27
+ end
28
+ end
data/lib/fe/railtie.rb ADDED
@@ -0,0 +1,7 @@
1
+ module Fe
2
+ class Railtie < Rails::Railtie
3
+ rake_tasks do
4
+ load File.join(File.dirname(__FILE__),'tasks','iron_fixture_extractor.rake')
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,12 @@
1
+ namespace :iron_fixture_extractor do
2
+ desc "Executes Fe.rebuild(extract_name) to re-create an existing fixture file set"
3
+ task :rebuild, [:extract_name] => :environment do |t,args|
4
+ Fe.rebuild(args[:extract_name].to_sym)
5
+ end
6
+
7
+ desc "Executes Fe.load_db(extract_name) to insert rows associated with file set"
8
+ task :load_db, [:extract_name] => :environment do |t,args|
9
+ Fe.load_db(args[:extract_name].to_sym)
10
+ end
11
+
12
+ end
data/lib/fe/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Fe
2
- VERSION = "0.1.1"
2
+ VERSION = "1.0.0"
3
3
  end
@@ -20,10 +20,12 @@ class BasicUsage < ActiveSupport::TestCase
20
20
  assert_equal Post.table_name, extractor.table_names['Post']
21
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
22
  assert_equal 1, extractor.row_counts['Post']
23
+ assert_equal 1, extractor.row_counts['Author']
24
+ assert_kind_of Hash, extractor.manifest_hash
23
25
  assert File.exists?(File.join(Fe.fixtures_root,'first_post_w_comments_and_authors',"#{Post.table_name}.yml")), "The file is created"
24
26
  end
25
27
  end
26
- context ".load_db" do
28
+ context ".load_db, .execute_extract_code" do
27
29
  setup do
28
30
  FeTestEnv.setup # regular production db
29
31
  extract_hash = Fe.extract(@extract_code, :name => @extract_name)
@@ -42,6 +44,12 @@ class BasicUsage < ActiveSupport::TestCase
42
44
  assert_equal 1, Comment.count
43
45
  assert_equal 1, Author.count
44
46
  end
47
+ should "provide the ability to execute the same query that built the fixtures" do
48
+ Fe.load_db(@extract_name)
49
+ rows = Fe.execute_extract_code(:first_post_w_comments_and_authors)
50
+ assert_equal 1, rows.length
51
+ assert (rows.first.association_cache.keys - [:comments,:author]).empty?, "Comments and authors should be eager loaded"
52
+ end
45
53
  end
46
54
  context ".rebuild" do
47
55
  setup do
@@ -49,7 +57,7 @@ class BasicUsage < ActiveSupport::TestCase
49
57
  @extractor = Fe.extract(@extract_code, :name => @extract_name)
50
58
  end
51
59
  teardown do
52
- # FeTestEnv.teardown
60
+ FeTestEnv.teardown
53
61
  end
54
62
  should "be able to rebuild the fixture files from the manifest" do
55
63
  # TODO: continue here, should delete a comment, then rebuild,
@@ -66,21 +74,33 @@ class BasicUsage < ActiveSupport::TestCase
66
74
  #assert_equal 0, Post.count
67
75
  end
68
76
  end
77
+
78
+ context ".truncate_tables_for" do
79
+ setup do
80
+ FeTestEnv.setup # regular production db
81
+ extract_hash = Fe.extract(@extract_code, :name => @extract_name)
82
+ FeTestEnv.the_env = 'fake_test'
83
+ FeTestEnv.recreate_schema_without_data
84
+ end
85
+ teardown do
86
+ FeTestEnv.teardown
87
+ end
88
+ should "truncate only the tables in the fixture set" do
89
+ Group.create
90
+ assert_equal 1, Group.count
91
+
92
+ Fe.load_db(@extract_name)
93
+ assert_equal 1, Post.count
94
+ assert_equal 1, Comment.count
95
+ assert_equal 1, Author.count
96
+
97
+ Fe.truncate_tables_for(@extract_name)
98
+ assert_equal 1, Group.count
99
+ assert_equal 0, Post.count
100
+ assert_equal 0, Comment.count
101
+ assert_equal 0, Author.count
102
+
103
+ end
104
+ end
69
105
  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
106
  end
@@ -0,0 +1,35 @@
1
+ # This test ensures that you can load_db into a different table/model
2
+ # than the one you extracted from
3
+ #
4
+ # THIS IS NOT COMPLETE, it seems like its impossible if you want to use
5
+ # ActiveRecord's .create_fixtures method...talk to Joe if you really
6
+ # need this feature
7
+ #
8
+ require 'test_helper'
9
+ class DfferentTargetTableTest < ActiveSupport::TestCase
10
+ #setup do
11
+ #@extract_code = 'Post.includes(:comments, :author).limit(1)'
12
+ #@extract_name = :first_post_w_comments_and_authors
13
+ #FeTestEnv.setup # regular production db
14
+ #extract_hash = Fe.extract(@extract_code, :name => @extract_name)
15
+ #FeTestEnv.the_env = 'fake_test'
16
+ #FeTestEnv.recreate_schema_without_data
17
+ #end
18
+ #teardown do
19
+ #FeTestEnv.teardown
20
+ #end
21
+ #should "provide the ability to load fixtures" do
22
+ #assert_equal 0, Post.count
23
+ #assert_equal 0, ::DifferentPost.count
24
+ #assert_raise Fe::InvalidSourceModelToMapFrom do
25
+ ## should fail cause User is not in the fixture set
26
+ #extractor = Fe.load_db(@extract_name, User => Post)
27
+ #end
28
+ ## extractor = Fe.load_db(@extract_name, Post => ::DifferentPost)
29
+ #require 'debugger'; debugger; puts 's'
30
+ #puts "TODO: CONTINUE HERE WITH BUILDING THE CODE TO MAKE THE FOLLOWING 2 ASSERT STATEMENTS PASS"
31
+ ##assert_equal 0, Post.count
32
+ ##assert_equal 1, DifferentPost.count
33
+ ##assert_equal 1, Author.count
34
+ #end
35
+ end
@@ -0,0 +1,77 @@
1
+ # WARNING: THIS IS AN EXPERIMENTAL FEATURE THAT ISN'T QUITE COMPLETE AND MIGHT BE DEPRECATED
2
+ # WARNING: THIS IS AN EXPERIMENTAL FEATURE THAT ISN'T QUITE COMPLETE AND MIGHT BE DEPRECATED
3
+ # WARNING: THIS IS AN EXPERIMENTAL FEATURE THAT ISN'T QUITE COMPLETE AND MIGHT BE DEPRECATED
4
+ # WARNING: THIS IS AN EXPERIMENTAL FEATURE THAT ISN'T QUITE COMPLETE AND MIGHT BE DEPRECATED
5
+ require 'test_helper'
6
+ require 'factory_girl'
7
+ class FactoryGirlTest < ActiveSupport::TestCase
8
+ setup do
9
+
10
+ @extract_code = 'Post.includes(:comments, :author).limit(1)'
11
+ @extract_name = :first_post_w_comments_and_authors
12
+ FeTestEnv.setup # regular production db
13
+ Fe.extract(@extract_code, :name => @extract_name) # build fixture yml
14
+ FeTestEnv.the_env = 'fake_test'
15
+ FeTestEnv.recreate_schema_without_data
16
+
17
+ @post_hash = Fe.get_hash(:first_post_w_comments_and_authors, Post,"r1")
18
+
19
+
20
+ end
21
+ should "expose a .to_factory_girl_string method" do
22
+ assert_kind_of Hash, @post_hash
23
+ assert_respond_to @post_hash, :to_factory_girl_string
24
+ assert !Hash.instance_methods.include?(:to_factory_girl_string)
25
+
26
+ @fg_string = @post_hash.to_factory_girl_string
27
+ assert_match /Post/, @fg_string, "The string should have the model name on the first line"
28
+ end
29
+
30
+ should ".to_factory_girl_string should return a monkey patched string implementing .to_proc" do
31
+ @fg_string = @post_hash.to_factory_girl_string
32
+ assert_respond_to @fg_string, :to_proc
33
+ end
34
+
35
+ should "be just like a factory produced in a non-meta way" do
36
+ FactoryGirl.define do
37
+ # This is the essense of the code that .to_factory_girl_string spits out
38
+ factory :fe2, :class => Post do
39
+ x = Post.new(Fe.get_hash(:first_post_w_comments_and_authors,Post,"r1"))
40
+ id x.id
41
+ author_id x.author_id
42
+ name x.name
43
+ content x.content
44
+ serialized_thing x.serialized_thing
45
+ created_at x.created_at
46
+ updated_at x.updated_at
47
+ end
48
+
49
+ # We are evaluating the to_factory_girl_string in the block context factory girl
50
+ # if you wanted to override settings you could do so afterwords
51
+ factory :fe3, :class => Post, &Proc.new {
52
+ self.instance_eval(Fe.get_hash(:first_post_w_comments_and_authors,Post,"r1").to_factory_girl_string)
53
+ # I think You could override attributes set in the fixture here, like:
54
+ # name "poo poo"
55
+ }
56
+
57
+ # This is two levels meta-ness away
58
+ factory :fe4,
59
+ :class => Post,
60
+ &Fe.get_hash(:first_post_w_comments_and_authors,Post,"r1").to_factory_girl_string.to_proc
61
+ end
62
+
63
+ @fe2 = FactoryGirl.create(:fe2)
64
+ assert_kind_of Post, @fe2
65
+
66
+ @fe3 = FactoryGirl.create(:fe3)
67
+ assert_kind_of Post, @fe3
68
+ assert_kind_of Time, @fe3.updated_at, "Objects get the right type"
69
+
70
+ @fe4 = FactoryGirl.create(:fe4)
71
+ assert_kind_of Post, @fe4
72
+ assert_kind_of Time, @fe4.updated_at, "Objects get the right type"
73
+ end
74
+ teardown do
75
+ FeTestEnv.teardown
76
+ end
77
+ end
data/test/fe_test_env.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  class FeTestEnv
2
2
  class << self
3
3
  def models
4
- [:post,:comment,:author,:group,:group_member]
4
+ [:serialized_attribute_encoder,:complex_thing,:post,:comment,:author,:group,:group_member,:different_post, :user, :'user/admin',:'user/jerk']
5
5
  end
6
6
  def model_classes
7
7
  self.models.map {|x| x.to_s.classify.constantize}
@@ -0,0 +1,35 @@
1
+ require 'test_helper'
2
+ class GetHashTest < ActiveSupport::TestCase
3
+ context "Fe" do
4
+ setup do
5
+ FeTestEnv.setup
6
+ @extract_code = 'Post.includes(:comments, :author).limit(1)'
7
+ @extract_name = :first_post_w_comments_and_authors
8
+ extractor = Fe.extract(@extract_code, :name => @extract_name)
9
+ end
10
+ context ".extract" do
11
+ should "have a .get_hash method" do
12
+ assert_respond_to Fe, :get_hash
13
+ end
14
+ context ".get_hash behavior" do
15
+ should "return a hash with the right columns" do
16
+ h = Fe.get_hash(:first_post_w_comments_and_authors, Post, 'r1')
17
+ assert_kind_of Hash, h
18
+ assert_equal 1, h["id"]
19
+ assert_equal "First post", h["name"]
20
+ assert_equal "ComplexThing", h["serialized_thing"]
21
+
22
+ # allow :first to grab the first fixture, so you don't have to know the name
23
+ h2 = Fe.get_hash(:first_post_w_comments_and_authors, Post, :first)
24
+ assert_equal h, h2
25
+
26
+ h3 = Fe.get_hash(:first_post_w_comments_and_authors, Post, :last)
27
+ assert_equal h, h3, "there is only one fixture in this set to last is the same as first"
28
+ end
29
+ end
30
+ end
31
+ teardown do
32
+ FeTestEnv.teardown
33
+ end
34
+ end
35
+ end
@@ -4,6 +4,7 @@ class CreatePosts < ActiveRecord::Migration
4
4
  t.belongs_to :author
5
5
  t.string :name
6
6
  t.string :content
7
+ t.string :serialized_thing
7
8
 
8
9
  t.timestamps
9
10
  end
@@ -0,0 +1,14 @@
1
+ class CreateDifferentPosts < ActiveRecord::Migration
2
+ # DUPLICATED FROM Posts
3
+ def change
4
+ create_table :different_posts do |t|
5
+ t.belongs_to :author
6
+ t.string :name
7
+ t.string :content
8
+ t.string :serialized_thing
9
+
10
+ t.timestamps
11
+ end
12
+ add_index :different_posts, :author_id
13
+ end
14
+ end
@@ -0,0 +1,10 @@
1
+ class CreateUsers < ActiveRecord::Migration
2
+ def change
3
+ create_table :users do |t|
4
+ t.string :name
5
+ t.string :type
6
+
7
+ t.timestamps
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,4 @@
1
+ # This is serialized in the Post.serialized_thing attribute.
2
+ #
3
+ class ComplexThing
4
+ end
@@ -0,0 +1,6 @@
1
+ class DifferentPost < ActiveRecord::Base
2
+ # This is supposed to be identical to post
3
+ # and used to test fixture loading to a model
4
+ # different from the one it was extracted from
5
+ # so behavior doesn't matter
6
+ end
data/test/models/group.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  class Group < ActiveRecord::Base
2
2
  attr_accessible :name
3
3
  has_many :group_members
4
- has_many :authors, through: :group_members
4
+ has_many :authors, :through => :group_members
5
5
  end
data/test/models/post.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  class Post < ActiveRecord::Base
2
2
  belongs_to :author
3
3
  has_many :comments
4
- attr_accessible :content, :name
4
+ attr_accessible :content, :name, :serialized_thing
5
+ serialize :serialized_thing, SerializedAttributeEncoder.new
5
6
  end
@@ -0,0 +1,12 @@
1
+ # This encoder just serializes complex attributes with the string
2
+ # representation of their class. A +ComplexThing+ instance is stored in
3
+ # the database as 'ComplexThing', not a marshalled Ruby object.
4
+ #
5
+ class SerializedAttributeEncoder
6
+ def load(value)
7
+ value.constantize.new
8
+ end
9
+ def dump(object)
10
+ object.class.to_s
11
+ end
12
+ end
@@ -0,0 +1,2 @@
1
+ class User < ActiveRecord::Base
2
+ end
@@ -0,0 +1,2 @@
1
+ class User::Admin < User
2
+ end
@@ -0,0 +1,2 @@
1
+ class User::Jerk < User
2
+ end
@@ -0,0 +1,25 @@
1
+ require 'test_helper'
2
+ class MultiTreeUsageTest < ActiveSupport::TestCase
3
+ context "Multi Tree Usage" do
4
+ setup do
5
+ @extract_code = '[Post.includes(:comments).limit(1),Author.all]'
6
+ @extract_name = :two_tree
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 (%w(Post Comment Author) - extractor.model_names).empty?, "only these keys should exist"
18
+ assert File.exists?(File.join(Fe.fixtures_root,'two_tree','fe_manifest.yml')), "The file that allows the fixtures to get rebuilt"
19
+ assert_equal 1, extractor.row_counts['Post']
20
+ assert_equal 2, extractor.row_counts['Author']
21
+ #assert File.exists?(File.join(Fe.fixtures_root,'first_post_w_comments_and_authors',"#{Post.table_name}.yml")), "The file is created"
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,27 @@
1
+ require 'test_helper'
2
+ class SerializedAttributeTest < ActiveSupport::TestCase
3
+ context "A model with a serialized attribute" do
4
+ setup do
5
+ @extract_code = 'Post.limit(1)'
6
+ @extract_name = :posts_with_serialized_thing
7
+ end
8
+ context ".extract and .load_db with serialized attributes" do
9
+ setup do
10
+ FeTestEnv.setup
11
+ Fe.extract(@extract_code, :name => @extract_name)
12
+ FeTestEnv.the_env = 'fake_test'
13
+ FeTestEnv.recreate_schema_without_data
14
+ end
15
+ teardown do
16
+ FeTestEnv.teardown
17
+ end
18
+ should "extract the .dump() value of the serialized attribute" do
19
+ Fe.load_db(@extract_name)
20
+ if Post.count == 0
21
+ raise "The test setup didn't work, Post.count should have some rows"
22
+ end
23
+ assert_kind_of ComplexThing, Post.first.serialized_thing
24
+ end
25
+ end
26
+ end
27
+ end
data/test/sti_test.rb ADDED
@@ -0,0 +1,20 @@
1
+ require 'test_helper'
2
+ class StiTest < ActiveSupport::TestCase
3
+ setup do
4
+ FeTestEnv.setup
5
+ @extract_code = 'User.where("1=1")'
6
+ @extract_name = :all_users
7
+ end
8
+ teardown do
9
+ FeTestEnv.teardown
10
+ end
11
+ should "yo" do
12
+ extractor = Fe.extract(@extract_code, :name => @extract_name)
13
+ assert_equal [User], extractor.models
14
+ assert_equal({'User' => 2}, extractor.row_counts)
15
+ FeTestEnv.the_env = 'fake_test'
16
+ FeTestEnv.recreate_schema_without_data
17
+ Fe.load_db(@extract_name)
18
+ assert_equal ["User::Admin", "User::Jerk"], User.all.map(&:type).sort
19
+ end
20
+ end
@@ -1,14 +1,17 @@
1
1
  class CreateSomeData < ActiveRecord::Migration
2
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"
3
+ a=Author.create :name => "Joe"
4
+ p1=a.posts.create :name => "First post", :serialized_thing => ComplexThing.new
5
+ p1.comments.create :content => "This is crap"
6
+ p2=a.posts.create :name => "Second post", :serialized_thing => ComplexThing.new
7
+ p2.comments.create :content => "This is great"
8
8
 
9
- a2=Author.create name: "Bill"
10
- g=Group.create name: "Group 1"
9
+ a2=Author.create :name => "Bill"
10
+ g=Group.create :name => "Group 1"
11
11
  g.authors << a2
12
12
  g.save
13
+
14
+ User::Jerk.create(:name => "Jimmy the jerk")
15
+ User::Admin.create(:name => "Ron the admin")
13
16
  end
14
17
  end
data/test/test_helper.rb CHANGED
@@ -5,6 +5,7 @@ require 'shoulda'
5
5
  require 'iron_fixture_extractor'
6
6
  # TEMP, COMMENT OUT IF NEEDED
7
7
  require 'sqlite3'
8
- require 'ruby-debug'
8
+ #require 'ruby-debug'
9
9
  require 'fe_test_env'
10
+ ActiveRecord::Migration.verbose = false
10
11
  FeTestEnv.reload
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: iron_fixture_extractor
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.1.1
5
+ version: 1.0.0
6
6
  platform: ruby
7
7
  authors:
8
8
  - Joe Goggins
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2012-06-16 00:00:00 Z
13
+ date: 2012-11-30 00:00:00 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activerecord
@@ -56,6 +56,17 @@ dependencies:
56
56
  version: "0"
57
57
  type: :development
58
58
  version_requirements: *id004
59
+ - !ruby/object:Gem::Dependency
60
+ name: factory_girl
61
+ prerelease: false
62
+ requirement: &id005 !ruby/object:Gem::Requirement
63
+ none: false
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: "0"
68
+ type: :development
69
+ version_requirements: *id005
59
70
  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
71
  email:
61
72
  - goggins@umn.edu
@@ -67,6 +78,7 @@ extra_rdoc_files: []
67
78
 
68
79
  files:
69
80
  - .gitignore
81
+ - CHANGELOG.md
70
82
  - Gemfile
71
83
  - LICENSE
72
84
  - README.md
@@ -74,21 +86,38 @@ files:
74
86
  - iron_fixture_extractor.gemspec
75
87
  - lib/fe.rb
76
88
  - lib/fe/extractor.rb
89
+ - lib/fe/factory_girl_dsl_methods.rb
90
+ - lib/fe/railtie.rb
91
+ - lib/fe/tasks/iron_fixture_extractor.rake
77
92
  - lib/fe/version.rb
78
93
  - lib/iron_fixture_extractor.rb
79
94
  - test/basic_usage_test.rb
80
95
  - test/config/database.yml
96
+ - test/different_target_table_test.rb
97
+ - test/factory_girl_test.rb
81
98
  - test/fe_test_env.rb
99
+ - test/get_hash_test.rb
82
100
  - test/migrations/20120604043601_create_posts.rb
83
101
  - test/migrations/20120604043602_create_authors.rb
102
+ - test/migrations/20120604043603_create_different_posts.rb
84
103
  - test/migrations/20120604043639_create_comments.rb
85
104
  - test/migrations/20120604043808_create_group_members.rb
86
105
  - test/migrations/20120604043818_create_groups.rb
106
+ - test/migrations/20120604043819_create_users.rb
87
107
  - test/models/author.rb
88
108
  - test/models/comment.rb
109
+ - test/models/complex_thing.rb
110
+ - test/models/different_post.rb
89
111
  - test/models/group.rb
90
112
  - test/models/group_member.rb
91
113
  - test/models/post.rb
114
+ - test/models/serialized_attribute_encoder.rb
115
+ - test/models/user.rb
116
+ - test/models/user/admin.rb
117
+ - test/models/user/jerk.rb
118
+ - test/multi_tree_usage_test.rb
119
+ - test/serialized_attribute_test.rb
120
+ - test/sti_test.rb
92
121
  - test/test_data_migrations/001_create_some_data.rb
93
122
  - test/test_helper.rb
94
123
  homepage: https://github.com/joegoggins/iron_fixture_extractor
@@ -114,23 +143,37 @@ required_rubygems_version: !ruby/object:Gem::Requirement
114
143
  requirements: []
115
144
 
116
145
  rubyforge_project:
117
- rubygems_version: 1.8.24
146
+ rubygems_version: 1.8.15
118
147
  signing_key:
119
148
  specification_version: 3
120
149
  summary: Simplified dynamic fixture extraction for ActiveRecord
121
150
  test_files:
122
151
  - test/basic_usage_test.rb
123
152
  - test/config/database.yml
153
+ - test/different_target_table_test.rb
154
+ - test/factory_girl_test.rb
124
155
  - test/fe_test_env.rb
156
+ - test/get_hash_test.rb
125
157
  - test/migrations/20120604043601_create_posts.rb
126
158
  - test/migrations/20120604043602_create_authors.rb
159
+ - test/migrations/20120604043603_create_different_posts.rb
127
160
  - test/migrations/20120604043639_create_comments.rb
128
161
  - test/migrations/20120604043808_create_group_members.rb
129
162
  - test/migrations/20120604043818_create_groups.rb
163
+ - test/migrations/20120604043819_create_users.rb
130
164
  - test/models/author.rb
131
165
  - test/models/comment.rb
166
+ - test/models/complex_thing.rb
167
+ - test/models/different_post.rb
132
168
  - test/models/group.rb
133
169
  - test/models/group_member.rb
134
170
  - test/models/post.rb
171
+ - test/models/serialized_attribute_encoder.rb
172
+ - test/models/user.rb
173
+ - test/models/user/admin.rb
174
+ - test/models/user/jerk.rb
175
+ - test/multi_tree_usage_test.rb
176
+ - test/serialized_attribute_test.rb
177
+ - test/sti_test.rb
135
178
  - test/test_data_migrations/001_create_some_data.rb
136
179
  - test/test_helper.rb