iron_fixture_extractor 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
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