iron_fixture_extractor 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. data/CHANGELOG.md +6 -0
  2. data/Gemfile +7 -9
  3. data/README.md +129 -47
  4. data/Rakefile +5 -6
  5. data/iron_fixture_extractor.gemspec +0 -3
  6. data/lib/fe.rb +18 -43
  7. data/lib/fe/extractor.rb +91 -63
  8. data/lib/fe/version.rb +1 -1
  9. data/spec/README_FOR_DEVELOPERS.md +26 -0
  10. data/spec/dummy_environments/sqlite/dummy1/config/database.yml +11 -0
  11. data/spec/dummy_environments/sqlite/dummy1/data_migrations/001_create_some_data.rb +17 -0
  12. data/spec/dummy_environments/sqlite/dummy1/migrations/20120604043601_create_posts.rb +13 -0
  13. data/spec/dummy_environments/sqlite/dummy1/migrations/20120604043602_create_authors.rb +9 -0
  14. data/spec/dummy_environments/sqlite/dummy1/migrations/20120604043603_create_different_posts.rb +14 -0
  15. data/spec/dummy_environments/sqlite/dummy1/migrations/20120604043639_create_comments.rb +13 -0
  16. data/spec/dummy_environments/sqlite/dummy1/migrations/20120604043808_create_group_members.rb +13 -0
  17. data/spec/dummy_environments/sqlite/dummy1/migrations/20120604043818_create_groups.rb +9 -0
  18. data/spec/dummy_environments/sqlite/dummy1/migrations/20120604043819_create_users.rb +10 -0
  19. data/spec/dummy_environments/sqlite/dummy1/models/author.rb +5 -0
  20. data/spec/dummy_environments/sqlite/dummy1/models/comment.rb +5 -0
  21. data/spec/dummy_environments/sqlite/dummy1/models/complex_thing.rb +4 -0
  22. data/spec/dummy_environments/sqlite/dummy1/models/different_post.rb +9 -0
  23. data/spec/dummy_environments/sqlite/dummy1/models/group.rb +5 -0
  24. data/spec/dummy_environments/sqlite/dummy1/models/group_member.rb +5 -0
  25. data/spec/dummy_environments/sqlite/dummy1/models/post.rb +7 -0
  26. data/spec/dummy_environments/sqlite/dummy1/models/serialized_attribute_encoder.rb +12 -0
  27. data/spec/dummy_environments/sqlite/dummy1/models/user.rb +2 -0
  28. data/spec/dummy_environments/sqlite/dummy1/models/user/admin.rb +3 -0
  29. data/spec/dummy_environments/sqlite/dummy1/models/user/jerk.rb +3 -0
  30. data/spec/execute_extract_code_spec.rb +29 -0
  31. data/spec/extract_spec.rb +37 -0
  32. data/spec/extract_works_with_multiple_extract_queries_in_one_command_spec.rb +12 -0
  33. data/spec/fe_test_env_spec.rb +65 -0
  34. data/spec/get_hash_spec.rb +27 -0
  35. data/spec/load_db_map_option_spec.rb +39 -0
  36. data/spec/load_db_spec.rb +48 -0
  37. data/spec/load_db_works_with_serialized_attributes_spec.rb +18 -0
  38. data/spec/rebuild_spec.rb +18 -0
  39. data/spec/spec_helper.rb +15 -0
  40. data/spec/support/fe_test_env.rb +181 -0
  41. data/spec/support/first_post_w_comments_and_authors.rb +12 -0
  42. data/spec/truncate_tables_for_spec.rb +39 -0
  43. data/spec/works_with_single_table_inheritance_spec.rb +16 -0
  44. data/test/basic_usage_test.ported.rb +114 -0
  45. data/test/{different_target_table_test.rb → different_target_table_test.not_porting.rb} +0 -0
  46. data/test/factory_girl_test.not_porting_now.rb +79 -0
  47. data/test/{fe_test_env.rb → fe_test_env.ported.rb} +0 -0
  48. data/test/{get_hash_test.rb → get_hash_test.ported.rb} +17 -1
  49. data/test/{multi_tree_usage_test.rb → multi_tree_usage_test.ported.rb} +0 -0
  50. data/test/{serialized_attribute_test.rb → serialized_attribute_test.ported.rb} +0 -0
  51. data/test/{sti_test.rb → sti_test.ported.rb} +0 -0
  52. data/test/test_helper.rb +0 -1
  53. metadata +135 -88
  54. data/lib/fe/factory_girl_dsl_methods.rb +0 -28
  55. data/test/basic_usage_test.rb +0 -106
  56. data/test/factory_girl_test.rb +0 -77
@@ -0,0 +1,48 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Fe.load_db" do
4
+ include FirstPostWCommentsAndAuthors
5
+ it "ensures the test env is all good..there are no rows" do
6
+ FeTestEnv.instance.connect_to_target
7
+ FeTestEnv.instance.create_tables_in('target')
8
+ @model_names.each do |mn|
9
+ expect(mn.constantize.count).to eql(0)
10
+ end
11
+ end
12
+ it "has a loaded target database with the same number of rows than is in the source" do
13
+ FeTestEnv.instance.connect_to_target
14
+ FeTestEnv.instance.create_tables_in('target')
15
+ Fe.load_db(@extract_name)
16
+ @extractor.row_counts.each_pair do |m,c|
17
+ expect(m.constantize.count).to eql(c), "number of rows in the target should be the same as the counts from the source given the extract_code"
18
+ end
19
+ end
20
+ context ":only and :except options" do
21
+ before(:each) do
22
+ FeTestEnv.instance.connect_to_target
23
+ FeTestEnv.instance.create_tables_in('target')
24
+ end
25
+ it "supports :only => Array of yml file names to only load particular tables" do
26
+ expect {
27
+ Fe.load_db(@extract_name, :only => 'posts' )
28
+ }.to change {
29
+ Post.count
30
+ }.from(0).to(1)
31
+ expect(Author.count).to eql(0)
32
+ expect(Comment.count).to eql(0)
33
+ end
34
+
35
+ it "supports :except => Array of yml file names to load all tables except those specified" do
36
+ extractor = Fe.load_db(@extract_name, :except => ['authors', 'comments'] )
37
+ expect(Author.count).to eql(0)
38
+ expect(Comment.count).to eql(0)
39
+ expect(Post.count).to eql(extractor.row_counts['Post'])
40
+ end
41
+
42
+ it "raises an exception no models result after the :only or :except filters" do
43
+ expect {
44
+ Fe.load_db(@extract_name, :except => ['authors', 'comments','posts'] )
45
+ }.to raise_exception
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+
3
+ describe "A model with a serialized attribute" do
4
+ it "can .extract and .load_db correctly" do
5
+ FeTestEnv.instance.bomb_and_rebuild
6
+ @extract_code = 'Post.limit(1)'
7
+ @extract_name = :posts_with_serialized_thing
8
+ Fe.extract(@extract_code, :name => @extract_name)
9
+ FeTestEnv.instance.connect_to_target
10
+ FeTestEnv.instance.create_tables_in('target')
11
+ Fe.load_db(@extract_name)
12
+ if Post.count == 0
13
+ raise "The test setup didn't work, Post.count should have some rows in the target"
14
+ end
15
+ expect(Post.first.serialized_thing).to be_a_kind_of(ComplexThing)
16
+ end
17
+ end
18
+
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Fe.rebuild" do
4
+ include FirstPostWCommentsAndAuthors
5
+
6
+ # The following illustrates that the .yml file first does not have
7
+ # BOOM_BOOM_TEST, then does after .rebuild
8
+ it "rebuilds the fixture files from the manifest" do
9
+ the_posts_fixture_file_contents = File.read(@extractor.fixture_path_for_model('Post'))
10
+ first_post = Post.first
11
+ expect(the_posts_fixture_file_contents).to include first_post.name
12
+ expect(the_posts_fixture_file_contents).to_not include 'BOOM_BOOM_TEST'
13
+ first_post.name = "BOOM_BOOM_TEST"
14
+ first_post.save!
15
+ Fe.rebuild(@extract_name)
16
+ expect(File.read(@extractor.fixture_path_for_model('Post'))).to include 'BOOM_BOOM_TEST'
17
+ end
18
+ end
@@ -0,0 +1,15 @@
1
+ require 'rspec'
2
+ require 'iron_fixture_extractor'
3
+ # Require test helpers like FeTestEnv
4
+ Dir[File.join(File.dirname(__FILE__),"support/**/*.rb")].each {|f| require f}
5
+ # Don't show me the migration up + down crap
6
+ ActiveRecord::Migration.verbose = false
7
+ # Show be colors!
8
+ RSpec.configure do |config|
9
+ config.failure_color = :magenta
10
+ config.tty = true
11
+ config.color = true
12
+ end
13
+
14
+ require 'sqlite3'
15
+ FeTestEnv.instance = FeTestEnv.new(File.join(File.dirname(__FILE__),'dummy_environments','sqlite','dummy1'))
@@ -0,0 +1,181 @@
1
+ # An object for setting up dummy source and target environments
2
+ # used through the test suite
3
+ #
4
+ class FeTestEnv
5
+ attr_reader :root_path
6
+ # caller should specify full path
7
+ # by default it isn't lazy with initialization of tmp dir + loading models
8
+ def initialize(root_path, options = {:lazy => false})
9
+ @root_path = root_path
10
+ if !options[:lazy]
11
+ bomb_and_rebuild
12
+ end
13
+ end
14
+
15
+ # INITIALIZATION HELPERS
16
+ def bomb_and_rebuild
17
+ Fe.fixtures_root = self.fe_fixtures_dir
18
+ initialize_tmp
19
+ load_models
20
+ connect_to_source
21
+ create_tables_in('source')
22
+ create_rows_in('source')
23
+ end
24
+
25
+ def initialize_tmp
26
+ FileUtils.rm_rf(tmp_dir)
27
+ FileUtils.mkdir_p(tmp_dir)
28
+ FileUtils.mkdir_p(fe_fixtures_dir)
29
+ self
30
+ end
31
+ def load_models
32
+ model_files.each do |m|
33
+ load m
34
+ end
35
+ self
36
+ end
37
+
38
+ # PUBLIC API
39
+ def create_tables_in(string)
40
+ send("connect_to_#{string}")
41
+ run_migrations
42
+ end
43
+ def create_rows_in(string)
44
+ send("connect_to_#{string}")
45
+ run_data_migrations
46
+ end
47
+ def connect_to_source
48
+ ActiveRecord::Base.establish_connection(database_dot_yml_hash['source'])
49
+ end
50
+ def connect_to_target
51
+ ActiveRecord::Base.establish_connection(database_dot_yml_hash['target'])
52
+ end
53
+
54
+ # WORKER HELPERS
55
+ def run_migrations
56
+ ActiveRecord::Migrator.migrate("#{root_path}/migrations/",nil)
57
+ end
58
+ def run_data_migrations
59
+ ActiveRecord::Migrator.migrate("#{root_path}/data_migrations/",nil)
60
+ end
61
+
62
+ # File & directory location accessors (provides full path)
63
+ # --------------------------------------------------------
64
+ #
65
+ def database_dot_yml_file
66
+ File.join(root_path,'config','database.yml')
67
+ end
68
+ def database_dot_yml_hash
69
+ YAML::load_file(database_dot_yml_file)
70
+ end
71
+ def migration_files
72
+ Dir["#{root_path}/migrations/**/*.rb"]
73
+ end
74
+ def model_files
75
+ Dir["#{root_path}/models/**/*.rb"]
76
+ end
77
+ def tmp_dir
78
+ File.expand_path(File.join(File.dirname(__FILE__),'..','tmp'))
79
+ end
80
+ def fe_fixtures_dir
81
+ File.join(tmp_dir,'fe_fixtures')
82
+ end
83
+ def sqlite_db_dir
84
+ tmp_dir
85
+ end
86
+
87
+ # Singleton-style
88
+ class << self
89
+ def instance
90
+ raise "spec_helper.rb is supposed to set @instance...bug there yo" if @instance.nil?
91
+ @instance
92
+ end
93
+ def instance=(i)
94
+ @instance = i
95
+ end
96
+ end
97
+ end
98
+ #class FeTestEnv
99
+ #class << self
100
+ #def models
101
+ #[:serialized_attribute_encoder,:complex_thing,:post,:comment,:author,:group,:group_member,:different_post, :user, :'user/admin',:'user/jerk']
102
+ #end
103
+ #def model_classes
104
+ #self.models.map {|x| x.to_s.classify.constantize}
105
+ #end
106
+ #def fixtures_root
107
+ #'test/tmp/fe_fixtures'
108
+ #end
109
+ #def migrate_schema
110
+ #ActiveRecord::Migrator.migrate(File.join(File.dirname(__FILE__),'migrations'),nil)
111
+ #end
112
+ #def migrate_fake_production_data
113
+ #ActiveRecord::Migrator.migrate(File.join(File.dirname(__FILE__),'test_data_migrations'),nil)
114
+ #end
115
+ #def destroy_tmp_test_stuff #sqlite dbs and fixture files
116
+ #FileUtils.rm_rf Dir.glob("#{self.tmp_directory}/*")
117
+ #end
118
+ #def tmp_directory
119
+ #File.join(File.dirname(__FILE__), "tmp")
120
+ #end
121
+ #def establish_connection
122
+ #ActiveRecord::Base.establish_connection(self.connections[self.the_env])
123
+ #ActiveRecord::Base.connection
124
+ #end
125
+ #def connections
126
+ #YAML::load_file(File.join(File.dirname(__FILE__), 'config', 'database.yml'))
127
+ #end
128
+ #def load_models
129
+ #self.models.each do |x|
130
+ #require "models/#{x}"
131
+ #end
132
+ #end
133
+
134
+ #def unload_models
135
+ ## DOESN"T WORK!!!!!!!!!
136
+ #self.models.each do |x|
137
+ #Object.send(:remove_const, "::#{x.to_s.capitalize}")
138
+ #end
139
+ #end
140
+ #def make_fixtures_dir_and_set_fixtures_root
141
+ #FileUtils.mkdir_p FeTestEnv.fixtures_root
142
+ #Fe.fixtures_root = FeTestEnv.fixtures_root
143
+ #end
144
+ #attr_accessor :the_env
145
+
146
+ #def setup_methods
147
+ #@the_env ||= 'fake_production'
148
+ #[
149
+ #:make_fixtures_dir_and_set_fixtures_root,
150
+ #:load_models,
151
+ #:establish_connection,
152
+ #:migrate_schema,
153
+ #:migrate_fake_production_data]
154
+ #end
155
+ #def setup
156
+ #self.setup_methods.each {|m| send m}
157
+ #end
158
+ #def teardown_methods
159
+ #[
160
+ #:destroy_tmp_test_stuff
161
+ #]
162
+ #end
163
+ #def teardown
164
+ #self.teardown_methods.each {|m| send m}
165
+ #end
166
+ #def recreate_schema_without_data
167
+ #f=File.join(self.tmp_directory,"#{self.the_env}.sqlite3")
168
+ #begin
169
+ #FileUtils.rm f
170
+ #rescue
171
+ #puts "#{f} does not exist"
172
+ #end
173
+ #[:load_models, :establish_connection,:migrate_schema].each {|m| send m}
174
+ #end
175
+ #def reload
176
+ #teardown
177
+ #setup
178
+ #end
179
+ #end
180
+ #end
181
+
@@ -0,0 +1,12 @@
1
+ module FirstPostWCommentsAndAuthors
2
+ extend ActiveSupport::Concern
3
+ included do
4
+ before(:each) do
5
+ FeTestEnv.instance.bomb_and_rebuild
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
+ @model_names = %w(Post Comment Author)
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,39 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Fe.truncate_tables_for(<extract_name>)" do
4
+ include FirstPostWCommentsAndAuthors
5
+
6
+ #should "truncate only the tables in the fixture set" do
7
+ #Group.create
8
+ #assert_equal 1, Group.count
9
+
10
+ #Fe.load_db(@extract_name)
11
+ #assert_equal 1, Post.count
12
+ #assert_equal 1, Comment.count
13
+ #assert_equal 1, Author.count
14
+
15
+ #Fe.truncate_tables_for(@extract_name)
16
+ #assert_equal 1, Group.count
17
+ #assert_equal 0, Post.count
18
+ #assert_equal 0, Comment.count
19
+ #assert_equal 0, Author.count
20
+
21
+ #end
22
+ it "truncates only the tables in the fixture set" do
23
+ FeTestEnv.instance.connect_to_target
24
+ FeTestEnv.instance.create_tables_in('target')
25
+ expect(Group.count).to eql(0)
26
+ Group.create!
27
+ expect(Group.count).to eql(1)
28
+ Fe.load_db(@extract_name)
29
+ expect(Group.count).to eql(1), "didn't load any groups in fixture set"
30
+ @model_names.each do |mn|
31
+ expect(mn.constantize.count).to be > 0
32
+ end
33
+ Fe.truncate_tables_for(@extract_name)
34
+ @model_names.each do |mn|
35
+ expect(mn.constantize.count).to eql(0)
36
+ end
37
+ expect(Group.count).to eql(1)
38
+ end
39
+ end
@@ -0,0 +1,16 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Single Table Inheritance extract and load behavior" do
4
+ it "works as expected" do
5
+ FeTestEnv.instance.bomb_and_rebuild
6
+ @extract_code = 'User.where("1=1")'
7
+ @extract_name = :all_users
8
+ extractor = Fe.extract(@extract_code, :name => @extract_name)
9
+ expect(extractor.models).to eql([User]), "This will correspond to one fixture file"
10
+ FeTestEnv.instance.connect_to_target
11
+ FeTestEnv.instance.create_tables_in('target')
12
+ Fe.load_db(@extract_name)
13
+ expect(User.all.map(&:type).sort).to eql(["User::Admin","User::Jerk"])
14
+ end
15
+ end
16
+
@@ -0,0 +1,114 @@
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
+ # PORTED
16
+ #should "provide the right output, and put the file in the right place" do
17
+
18
+ ## CONTINUE PORTING FROM HERE in extract_spec!!!!!!!!!!
19
+ #extractor = Fe.extract(@extract_code, :name => @extract_name)
20
+ #assert_kind_of Fe::Extractor, extractor
21
+ #assert (%w(Post Comment Author) - extractor.model_names).empty?, "only these keys should exist"
22
+ #assert_equal @extract_name, extractor.name
23
+ #assert_equal Post.table_name, extractor.table_names['Post']
24
+ #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"
25
+ #assert_equal 1, extractor.row_counts['Post']
26
+ #assert_equal 1, extractor.row_counts['Author']
27
+ #assert_kind_of Hash, extractor.manifest_hash
28
+ #assert File.exists?(File.join(Fe.fixtures_root,'first_post_w_comments_and_authors',"#{Post.table_name}.yml")), "The file is created"
29
+ #end
30
+ end
31
+ context ".load_db, .execute_extract_code" do
32
+ setup do
33
+ FeTestEnv.setup # regular production db
34
+ extract_hash = Fe.extract(@extract_code, :name => @extract_name)
35
+ FeTestEnv.the_env = 'fake_test'
36
+ FeTestEnv.recreate_schema_without_data
37
+ end
38
+ teardown do
39
+ FeTestEnv.teardown
40
+ end
41
+ # PORTED
42
+ #should "provide the ability to load fixtures" do
43
+ #assert_equal 0, Post.count
44
+ #assert_equal 0, Comment.count
45
+ #assert_equal 0, Author.count
46
+ #Fe.load_db(@extract_name)
47
+ #assert_equal 1, Post.count
48
+ #assert_equal 1, Comment.count
49
+ #assert_equal 1, Author.count
50
+ #end
51
+ # PORTED
52
+ #should "provide the ability to execute the same query that built the fixtures" do
53
+ #Fe.load_db(@extract_name)
54
+ #rows = Fe.execute_extract_code(:first_post_w_comments_and_authors)
55
+ #assert_equal 1, rows.length
56
+ #assert (rows.first.association_cache.keys - [:comments,:author]).empty?, "Comments and authors should be eager loaded"
57
+ #end
58
+ end
59
+ context ".rebuild" do
60
+ setup do
61
+ FeTestEnv.setup
62
+ @extractor = Fe.extract(@extract_code, :name => @extract_name)
63
+ end
64
+ teardown do
65
+ FeTestEnv.teardown
66
+ end
67
+ # PORTED
68
+ #should "be able to rebuild the fixture files from the manifest" do
69
+ ## TODO: CONTINUE HERE JOE
70
+ ## TODO: continue here, should delete a comment, then rebuild,
71
+ ## and assert
72
+ ## all files mtimes have changed
73
+ ## there is no comment file
74
+ #results = eval(@extract_code)
75
+ #first_post = results.first
76
+ #assert_match /First post/i, first_post.name
77
+ #first_post.name = "UPDATED_FIRST_POST"
78
+ #first_post.save!
79
+ #rebuild_hash = Fe.rebuild(@extract_name)
80
+ #assert_match /UPDATED_FIRST_POST/, File.read(@extractor.fixture_path_for_model('Post'))
81
+ ##assert_equal 0, Post.count
82
+ #end
83
+ end
84
+
85
+ context ".truncate_tables_for" do
86
+ setup do
87
+ FeTestEnv.setup # regular production db
88
+ extract_hash = Fe.extract(@extract_code, :name => @extract_name)
89
+ FeTestEnv.the_env = 'fake_test'
90
+ FeTestEnv.recreate_schema_without_data
91
+ end
92
+ teardown do
93
+ FeTestEnv.teardown
94
+ end
95
+ # PORTED
96
+ #should "truncate only the tables in the fixture set" do
97
+ #Group.create
98
+ #assert_equal 1, Group.count
99
+
100
+ #Fe.load_db(@extract_name)
101
+ #assert_equal 1, Post.count
102
+ #assert_equal 1, Comment.count
103
+ #assert_equal 1, Author.count
104
+
105
+ #Fe.truncate_tables_for(@extract_name)
106
+ #assert_equal 1, Group.count
107
+ #assert_equal 0, Post.count
108
+ #assert_equal 0, Comment.count
109
+ #assert_equal 0, Author.count
110
+
111
+ #end
112
+ end
113
+ end
114
+ end