named_seeds 1.1.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2dd15c25329b3392795fb29d32abaac3a1066b4c
4
- data.tar.gz: f8ccffe2fe567906116a45ec4f7c1cf1235b7f62
3
+ metadata.gz: ecc617dea1b86fbaaea2fe3a16c381ba67d26e84
4
+ data.tar.gz: ba2a23916011c5572f70dd1c1b22a5dc1fe947ff
5
5
  SHA512:
6
- metadata.gz: 35a1cb0ee44477f9c052fc64c7808a08a1c2f2c349ec561e41a4c616b6c6175cb52015288d297daecb6b8538c83d937400059fcb84d4fc6587b1ce81f0020768
7
- data.tar.gz: 8c8e10690ce1ff0f79dec55754a19b6e1e3212de56854b207dac944a84ac786d0180cbcd155c7ef7cf2284dff90d19d8506028fe388df5094e22108f36a8e756
6
+ metadata.gz: dab6ede0737548ebb3e27246c9812e5117daa2e6166617f31050d8d1943e15bd6b5759e99ff0012909bdfc30937d1dd1b6b986f2d477c62493b3a0b466252817
7
+ data.tar.gz: 489d186ee125e43b2a8a56a0cc7125bd0bb1e7f0d9758e3fa7ed61b37873b2db8d41b6306edf9a2e330ab4e81954eec645af8411fde3ac6986e0133656116b54
data/.gitignore CHANGED
@@ -2,6 +2,7 @@
2
2
  *.rbc
3
3
  .bundle
4
4
  .config
5
+ .ruby-version
5
6
  .yardoc
6
7
  Gemfile.lock
7
8
  InstalledFiles
@@ -15,3 +16,4 @@ spec/reports
15
16
  test/tmp
16
17
  test/version_tmp
17
18
  tmp
19
+ gemfiles/*
@@ -0,0 +1,14 @@
1
+ sudo: false
2
+ cache: bundler
3
+ rvm:
4
+ - 2.0.0
5
+ - 2.1.5
6
+ - 2.2.1
7
+ install:
8
+ - gem install bundler
9
+ - bundle --version
10
+ - bundle install
11
+ before_script:
12
+ - bundle exec appraisal install
13
+ script:
14
+ - bundle exec appraisal rake test
@@ -0,0 +1,12 @@
1
+
2
+ appraise 'rails40' do
3
+ gem 'rails', '~> 4.0.0'
4
+ end
5
+
6
+ appraise 'rails41' do
7
+ gem 'rails', '~> 4.1.0'
8
+ end
9
+
10
+ appraise 'rails42' do
11
+ gem 'rails', '~> 4.2.0'
12
+ end
data/Gemfile CHANGED
@@ -1,2 +1,5 @@
1
1
  source 'https://rubygems.org'
2
2
  gemspec
3
+
4
+ gem 'terminal-notifier-guard' if RbConfig::CONFIG["host_os"] =~ /darwin/
5
+
@@ -0,0 +1,18 @@
1
+ clearing :on
2
+ notification :terminal_notifier if defined?(TerminalNotifier)
3
+
4
+ guard :minitest, {
5
+ all_on_start: true,
6
+ autorun: false,
7
+ include: ['lib', 'test'],
8
+ test_folders: ['test'],
9
+ test_file_patterns: ["*_test.rb"]
10
+ } do
11
+ if ENV['TEST_FILES']
12
+ ENV['TEST_FILES'].split(',').map(&:strip).each do |file|
13
+ watch(%r{.*}) { file }
14
+ end
15
+ else
16
+ watch(%r{.*}) { 'test' }
17
+ end
18
+ end
data/README.md CHANGED
@@ -1,28 +1,24 @@
1
- # NamedSeeds
2
1
 
3
- **Almost Ready for Rails 4.2.0.beta2**
2
+ <img width="502" height="298" alt="NamedSeeds - When it comes to fast tests... you reap what you sow!" src="https://cloud.githubusercontent.com/assets/2381/6770492/c7093fa6-d097-11e4-9e1f-6f90a857f8d3.png" />
4
3
 
5
- * [Various Issues With 4.2.0.beta2 DB Setup/Testing](https://github.com/rails/rails/issues/17170)
6
- * [The `test:prepare` Task Might Be Useless Now?](https://github.com/rails/rails/issues/17171)
4
+ <hr>
7
5
 
8
- **Make your tests fast by augmenting them with transactional fixtures powered by your favorite factory library!**
6
+ **Make your tests fast by augmenting them with transactional fixtures
7
+ powered by your favorite factory library!**
9
8
 
10
- We all know that ActiveRecord::Fixtures are hard to maintain and are disconnected from the models that save your data. But Rails did get something right with transactional tests and easy helper methods to access fixtures by name. NamedSeeds aims to be a drop-in replacement for Rails fixtures or an enhancement to RSpec and Cucumber while using any object generator of your choice!
9
+ We all know that ActiveRecord's fixtures are hard to maintain, and more importantly, disconnected from the models that create your data. This disconnect can lead to invalid or incomplete representations of your objects as your application grows. But Rails did get something right. Fixtures combined with transactional tests are a huge performance win while providing [canned references among your team](http://martinfowler.com/bliki/ObjectMother.html) via helper methods that find fixtures using a unique name. The NamedSeeds gem aims to replace YAML fixtures by providing a slim identification layer to be used in conjunction with your factory library of choice. For example, [FactoryGirl](https://github.com/thoughtbot/factory_girl).
11
10
 
12
- The idea is to leverage your tests' existing factories to generate fixtures that will be populated before testing starts and to use a database transaction strategy around each test. In this way you have a populated story that can be accessed via convienient helper methods like `users(:admin)` which in turn yields much faster test runs. Database fixtures, even those seeded by factories, are not a panacea and we highly suggested that you continue to use factories in your tests when it makes sense to do so. For those that think this is mad or have FUD to share, please see my blog articles:
11
+ The idea is to leverage your tests' existing factories to generate fixtures that will be populated before testing starts and to use a database transaction strategy around each test. In this way you have a curated set of personas that can be accessed via convenient helper methods like `users(:admin)` which in turn yields much faster test runs. **NamedSeeds fixtures also become your seed data for Rails' development environment.** This consistency between development and testing is a huge win for on-boarding new team members. Lastly, database fixtures, even those seeded by factories, are not a panacea and we recommend that you continue to use factories in your tests for edge cases when it makes sense to do so.
13
12
 
14
- * Inprogress...
15
- * Inprogress...
13
+ NamedSeeds is best when your factories follow two key principals:
16
14
 
17
-
18
- ## Versions
19
-
20
- The current master branch is for Rails v4.2.0 and up and follows v1.1 major version. Please use our `1-0-stable` branch for Rails v3.1 to v4.1.
15
+ * Leveraging your models for most business logic.
16
+ * Creation of "valid garbage" with no/minimal args while allowing idempotency via explicit args.
21
17
 
22
18
 
23
19
  ## Installation
24
20
 
25
- Add the named_seeds gem to your Rails' Gemfile in both the development and test group as shown below. This is needed as the NamedSeeds gem exposes rake tasks needed in both environments.
21
+ Add the gem to your Rails' Gemfile in both the development and test group as shown below. This is needed since the NamedSeeds gem has integrations in both environments.
26
22
 
27
23
  ```ruby
28
24
  group :development, :test do
@@ -30,109 +26,188 @@ group :development, :test do
30
26
  end
31
27
  ```
32
28
 
33
- That's it! The NamedSeeds gem will hook into the Rails test cycle to make sure your factoried fixtures (and any engine seeds) are populated after your test schema is created and before your test suite runs.
34
29
 
35
- ## Usage
30
+ ## Quick Start
36
31
 
37
- NamedSeeds requires that you create a `db/test/seeds.rb` file. The contents of this file can be anything you want. We recommend using a factory library like [FactoryGirl](https://github.com/thoughtbot/factory_girl) or [Machinist](https://github.com/notahat/machinist).
32
+ NamedSeeds only requires that you customize the Rails `db/seeds.rb` file. The contents of this file can be anything you want! We recommend using a factory library like [FactoryGirl](https://github.com/thoughtbot/factory_girl) or [Machinist](https://github.com/notahat/machinist).
38
33
 
39
34
  ```ruby
40
35
  require 'factory_girl'
36
+ include FactoryGirl::Syntax::Methods
41
37
  FactoryGirl.find_definitions rescue false
38
+ FactoryGirl.lint
39
+
40
+ @bob = create :user, id: NamedSeeds.identify(:bob), email: 'bob@test.com'
41
+ ```
42
+
43
+ In this example we have given our Bob user an explicit primary key using the identify method of NamedSeeds. This ensures we have a handle on Bob in our tests. For this happen, make the following changes to your Rails `test_helper.rb` file.
44
+
45
+ ```ruby
46
+ ENV["RAILS_ENV"] = "test"
47
+ require File.expand_path('../../config/environment', __FILE__)
48
+ require 'rails/test_help'
49
+ NamedSeeds.load_seed
42
50
 
43
- @bob = FactoryGirl.create :user, id: NamedSeeds.identify(:bob), email: 'bob@test.com'
51
+ class ActiveSupport::TestCase
52
+
53
+ named_seeds :users
54
+
55
+ end
44
56
  ```
45
57
 
46
- Use the `NamedSeeds.identify` method to give a name to the identity used for this record. You will be able to find this record using that name later on.
58
+ Here we have added `NamedSeeds.load_seed` after our requires. This ensures our test database is properly seeded. We have also added a `named_seeds :users` declaration that creates a test helper method that can find any persona with a matching identity. The method name follows ActiveRecord model/table name conventions. So in this case we expect to find a `User` model. An example of what our unit test for Bob might look like with the new `users` fixture helper would be:
47
59
 
60
+ ```ruby
61
+ require 'test_helper'
48
62
 
49
- #### Integration Notes
63
+ class UserTest < ActiveSupport::TestCase
50
64
 
51
- The NamedSeeds gem will hook into ActiveRecord's `db:setup` task. This means that new developers can checkout your code and run the normal Rails setup process and see a fully populated development database that has the same seed/fixtures story used by your tests. For example:
65
+ tests "should work" do
66
+ user = users(:bob)
67
+ assert_equal 'bob@test.com', user.email
68
+ end
52
69
 
70
+ end
53
71
  ```
72
+
73
+ This test is very contrived and is only meant to illustrate the `users(:bob)` test helper which closely mimics ActiveRecord's fixture helpers.
74
+
75
+
76
+ ## Detailed Usage
77
+
78
+ #### Development Benefits
79
+
80
+ NamedSeeds hooks into the `db:setup` process. In this way, the same fixture story seeded in your test environment is the same in development. For example, if you are on-boarding a new developer and bootstrapping their environment.
81
+
82
+ ```shell
54
83
  $ bundle
55
- $ rake db:create:all
56
- $ rake db:setup
84
+ $ rake db:create:all db:setup
57
85
  ```
58
86
 
59
- If you need to force a reload of your development environment's data, just use Rails conventions. For example, the `db:reset` task calls setup, so NamedSeeds will hook in at the right place.
87
+ Your local development database will now contain all fixtures created in db/seeds. As you fixtures grow, re-create your development environment with confidence.
60
88
 
89
+
90
+ ```shell
91
+ $ bundle
92
+ $ rake db:drop:all db:create:all db:setup
61
93
  ```
62
- $ rake db:reset
94
+
95
+ #### The NamedSeeds::DSL
96
+
97
+ If you do not like typing `NamedSeeds.identify(:persona)` over and over again in your seeds file, you can include the `NamedSeeds::DSL` at the top. This will give you direct scope to the `identify` method which is also succinctly aliased to just `id` if you want.
98
+
99
+ ```ruby
100
+ include NamedSeeds::DSL
101
+
102
+ id(:ruby) # => 207281424
103
+ id(:sapphire_2) # => 1066363776
63
104
  ```
64
105
 
65
- Likewise, if you wanted to reset your test database and pre-populate it with named seeds/fixtures you can run the following:
106
+ #### UUID Identifiers
107
+
108
+ By default identities boil down to a consistent integer whose values are less than 2^30. These are great for typical primary or foreign keys. Now that Rails supports UUID keys in both models and ActiveRecord fixtures, so does the NamedSeeds gem. The identity method can use an optional second parameter to denote the SQL type when seeding your database.
66
109
 
110
+ ```ruby
111
+ id(:ken, :uuid) # => '4f156606-8cb3-509e-a177-956ca0a22015'
67
112
  ```
68
- $ spring stop && rake db:test:prepare
113
+
114
+ So if our `User` model did use a UUID column type, our seed file might look like this.
115
+
116
+ ```ruby
117
+ @bob = create :user, id: NamedSeeds.identify(:bob), email: 'bob@test.com'
69
118
  ```
70
119
 
71
- #### Rails
120
+ #### String Identifier
72
121
 
73
- By default, Rails' ActiveSupport::TestCase has set the `use_transactional_fixtures` to true. So all you need to do is declare which tables have NamedSeeds keys.
122
+ If your model uses strings for primary keys or what is known as "natural" keys, then NamedSeeds can still work for you. First, create your seed data without the identity helper. For example, below we are seeding US states in a contrived lookup table.
74
123
 
75
124
  ```ruby
76
- class ActiveSupport::TestCase
77
- named_seeds :users, :posts
78
- end
125
+ # In db/seeds.rb file.
126
+ create :state, id: 'VA', name: 'Virginia'
127
+ create :state, id: 'WA', name: 'Washington'
79
128
  ```
80
129
 
81
- Now you can use both the `users` and `posts` helper methods to find any named identity from your seed file.
130
+ Here the primary key of the `State` model is a string column. You have two options to generate test helpers for these objects. Note that none are technically needed since the identities are known and not random integers.
82
131
 
83
132
  ```ruby
84
- require 'test_helper'
85
- class UserTest < ActiveSupport::TestCase
86
- setup { @user = users(:bob) }
87
- tests "should work" do
88
- assert_equal 'bob@test.com', @user.posts
89
- end
90
- end
133
+ named_seeds :states, identities: {virginia: 'VA', washington: 'WA'}
134
+ states(:virginia) # => #<State id: 'VA'... >
135
+
136
+ named_seeds :states, identities: :natural
137
+ states('VA') # => #<State id: 'VA'... >
138
+
91
139
  ```
92
140
 
93
- #### RSpec
141
+ By passing an identities hash to `named_seeds` you can customize the name of the key used in finders. The first line would generate a method that allows you to find states using the longer identities key values. This is great if your natural keys do not necessarily speak to the persona/object under test. If you wanted to use the natural key string values, you can just pass `:natural` to the identities option.
142
+
143
+ #### Setting Fixture Classes
94
144
 
95
- Coming soon...
145
+ If your test helper name can not infer the class name, just use the `:class` option when declaring seeds in your test helper.
96
146
 
97
- #### Cucumber
147
+ ```ruby
148
+ named_seeds :users, class: Legacy::User
149
+ ```
98
150
 
99
- Coming soon...
151
+ #### Moving From ActiveRecord Fixtures
100
152
 
153
+ Unlike ActiveRecord fixtures, NamedSeeds does not support loading fixtures per test case. Since the entire fixture story is loaded before the test suite runs. NamedSeeds is much more akin to `fixtures(:all)` and the `named_seeds` method is more about creating test helper methods to access named fixtures. Lastly, NamedSeeds has no notion of instantiated fixtures.
154
+
155
+ #### Using DatabaseCleaner
156
+
157
+ Rails 4 (maybe starting in 4.1) now has a new test database synchronization strategy. No longer is your entire development schema cloned when you run your tests. This saves time when running tests but it also adds a potential gotcha when using db/seeds.rb with the NamedSeeds gem. We recommend using the DatabaseCleaner gem and cleaning your DB at the top of your seed file.
158
+
159
+ ```ruby
160
+ # In your Gemfile.
161
+ group :development, :test do
162
+ gem 'named_seeds'
163
+ gem 'database_cleaner'
164
+ end
165
+
166
+ # Top of db/seeds.rb file.
167
+ require 'database_cleaner'
168
+ DatabaseCleaner.clean_with :truncation
169
+ DatabaseCleaner.clean
170
+ ```
101
171
 
102
172
 
103
173
  ## Configurations
104
174
 
105
- NamedSeeds is a `Rails::Railtie` that exposes a few `config` options. So open up the `config/environments/development.rb` **(yes in development.rb)** and use the `config.named_seeds` options below. NOTE: I have found that sometimes I need to add some configurations to `config/environments/test.rb` too.
175
+ #### Other Rails::Engine And Seed Loaders
106
176
 
107
- * *app_load_seed* - Load your Rails application's db/seeds.rb file into the test database. This is done before db/test/seeds.rb is loaded. Default is `true` but may people use this file incorrectly vs standard lookup tables.
108
- * *engines_with_load_seed* - Some Rails engines provide a load seed hook. If you want NamedSeed to call the engine's seed method into your tests database, push the engine constant to this array. Any object responding to `load_seed` sould work here too. Default is an empty array.
177
+ Rails::Engines are a great way to distribute shared functionality. Rails exposes a hook called `load_seed` that an engine can implement. These are great for seeding tables that an engine's models may need. You can tell NamedSeeds to use any object that responds to `load_seed` and each will be called after `db/seeds.rb` is loaded. For example:
109
178
 
110
179
  ```ruby
111
- My::Application.configure do
112
- config.named_seeds.app_load_seed = false
113
- config.named_seeds.engines_with_load_seed += [GeoData::Engine, OurLookupTables]
180
+ # In config/initializers/named_seeds.rb
181
+
182
+ if defined?(NamedSeeds)
183
+ Rails.application.config.named_seeds.engines_with_load_seed = [
184
+ GeoData::Engine,
185
+ OurLookupTables
186
+ ]
187
+ end
114
188
  end
115
189
  ```
116
190
 
117
- NamedSeeds relies on ActiveRecord's `ActiveRecord::Migration.maintain_test_schema!` setting. We do not want to get into the business of coupling too much with the internals of Rails and hance assume this is true.
118
191
 
192
+ ## Versions
119
193
 
120
- ## Todo
194
+ The current master branch is for Rails v4.0.0 and up and. Please use our `1-0-stable` branch for Rails v3.x.
121
195
 
122
- Show Rails implementation using ActiveSupport::TestCase or RSpec.
123
196
 
124
- Show examples with these 3 factory libraries.
197
+ ## Contributing
125
198
 
126
- * https://github.com/thoughtbot/factory_girl
127
- * https://github.com/paulelliott/fabrication
128
- * https://github.com/notahat/machinist
199
+ We use the [Appraisal](https://github.com/thoughtbot/appraisal) gem from Thoughtbot to help us test different versions of Rails. The `rake appraisal test` command actually runs our test suite against all Rails versions in our `Appraisal` file. So after cloning the repo, running the following commands.
129
200
 
130
- Set up a dummy_application in test.
201
+ ```shell
202
+ $ bundle install
203
+ $ bundle exec appraisal install
204
+ $ bundle exec appraisal rake test
205
+ ```
206
+
207
+ If you want to run the tests for a specific Rails version, use one of the appraisal names found in our `Appraisals` file. For example, the following will run our tests suite for Rails 4.1.x.
131
208
 
132
- How are we different from:
209
+ ```shell
210
+ $ bundle exec appraisal rails41 rake test
211
+ ```
133
212
 
134
- * https://github.com/mbleigh/seed-fu
135
- * https://github.com/sevenwire/bootstrapper/
136
- * https://github.com/franciscotufro/environmental_seeder
137
213
 
138
- Talk about http://railscasts.com/episodes/179-seed-data
data/TODO.md ADDED
@@ -0,0 +1,23 @@
1
+ ## Alternative Solutions
2
+
3
+ There are no absolutes, especially when it comes to software. That said, we think NamedSeeds is the best way to use fixtures. It encourages... (good factoies)
4
+
5
+ Everyone loves their own brand :poop:
6
+
7
+
8
+ * Seedbank gives your Rails seed data a little structure.
9
+ https://github.com/james2m/seedbank
10
+
11
+
12
+ * Relational seeding for Rails apps
13
+ https://github.com/vigetlabs/sprig
14
+ * Rails 4 task to dump (parts) of your database to db/seeds.rb
15
+ https://github.com/rroblak/seed_dump
16
+ * Allows composing fixture sets
17
+ https://github.com/optoro/composable_fixtures
18
+ * Advanced seed data handling for Rails, combining the best practices of several methods together.
19
+ https://github.com/mbleigh/seed-fu
20
+ * Auto generate factories from data
21
+ https://github.com/markburns/to_factory
22
+
23
+
@@ -1,7 +1,22 @@
1
1
  require 'rails'
2
2
  require 'active_record'
3
3
  require 'named_seeds/version'
4
- require 'named_seeds/identity'
5
- require 'named_seeds/read'
6
4
  require 'named_seeds/railtie'
7
- require 'named_seeds/active_support'
5
+ require 'named_seeds/uuid'
6
+ require 'named_seeds/dsl'
7
+ require 'named_seeds/identity'
8
+ require 'named_seeds/rails'
9
+
10
+ module NamedSeeds
11
+
12
+ extend DSL
13
+
14
+ def self.load_seed
15
+ Railtie.load_seed
16
+ end
17
+
18
+ def self.reset_cache
19
+ Identity.reset_cache
20
+ end
21
+
22
+ end
@@ -0,0 +1,24 @@
1
+ require 'zlib'
2
+
3
+ module NamedSeeds
4
+ module DSL
5
+
6
+ MAX_ID = 2 ** 30 - 1
7
+
8
+ # Copy of ActiveRecord::Fixtures.identify method.
9
+ # Returns a consistent, platform-independent identifier for +label+.
10
+ # Integer identifiers are values less than 2^30.
11
+ # UUIDs are RFC 4122 version 5 SHA-1 hashes.
12
+ #
13
+ def identify(label, column_type = :integer)
14
+ if column_type == :uuid
15
+ NamedSeeds.uuid_v5(label)
16
+ else
17
+ Zlib.crc32(label.to_s) % MAX_ID
18
+ end
19
+ end
20
+ alias_method :id, :identify
21
+
22
+ end
23
+ end
24
+
@@ -1,11 +1,70 @@
1
- require 'zlib'
1
+ require 'active_record/fixtures'
2
2
 
3
3
  module NamedSeeds
4
-
5
- # A direct copy of ActiveRecord::Fixtures.identify.
6
- # Returns a consistent, platform-independent identifier for +label+ that are positive integers less than 2^32.
7
- def self.identify(label)
8
- Zlib.crc32(label.to_s) % (2 ** 30 - 1)
4
+
5
+ class FixtureClassNotFound < ActiveRecord::FixtureClassNotFound
6
+ end
7
+
8
+ class Identity
9
+
10
+ @@all_cached = Hash.new
11
+
12
+ class << self
13
+
14
+ def reset_cache
15
+ @@all_cached.clear
16
+ end
17
+
18
+ def named(name, options)
19
+ @@all_cached[name] ||= new(name, options)
20
+ end
21
+
22
+ end
23
+
24
+ def initialize(name, options={})
25
+ @name = name
26
+ @options = options
27
+ @fixtures = {}
28
+ end
29
+
30
+ def find(*identities)
31
+ fixtures = identities.map { |identity| model_find(identity) }
32
+ fixtures.many? ? fixtures : fixtures.first
33
+ end
34
+
35
+ def identities
36
+ @options[:identities] || @options[:ids]
37
+ end
38
+
39
+
40
+ private
41
+
42
+ def model_find(identity)
43
+ @fixtures[identity.to_s] ||= model_class.unscoped { model_class.find model_id(identity) }
44
+ end
45
+
46
+ def model_class
47
+ return @model_class if defined?(@model_class)
48
+ @model_class = (@options[:class] || @options[:klass]) || @name.to_s.classify.safe_constantize
49
+ raise FixtureClassNotFound, "No class found for named_seed #{@name.inspect}. Use :class option." unless @model_class
50
+ @model_class
51
+ end
52
+
53
+ def model_id(identity)
54
+ case identities
55
+ when NilClass then NamedSeeds.identify(identity, model_primary_key_type)
56
+ when Hash then identities[identity]
57
+ when :natural then identity
58
+ end
59
+ end
60
+
61
+ def model_primary_key_type
62
+ type = model_class.column_types[model_class.primary_key].type
63
+ sql_type = model_class.columns_hash[model_class.primary_key].sql_type
64
+ return :uuid if ['uuid', 'guid', 'uniqueidentifier'].include?(sql_type)
65
+ type ? type.to_sym : :id
66
+ end
67
+
9
68
  end
10
69
 
11
- end
70
+ end
@@ -0,0 +1,27 @@
1
+ require 'active_support/concern'
2
+ require 'active_support/test_case'
3
+
4
+ module NamedSeeds
5
+ module TestHelper
6
+
7
+ extend ActiveSupport::Concern
8
+
9
+ def after_teardown
10
+ super
11
+ NamedSeeds.reset_cache
12
+ end
13
+
14
+ module ClassMethods
15
+
16
+ def named_seeds(name, options={})
17
+ define_method(name) do |*identities|
18
+ Identity.named(name, options).find(*identities)
19
+ end
20
+ end
21
+
22
+ end
23
+
24
+ end
25
+ end
26
+
27
+ ActiveSupport::TestCase.send :include, NamedSeeds::TestHelper
@@ -1,44 +1,26 @@
1
+ require 'active_record/tasks/database_tasks'
2
+
1
3
  module NamedSeeds
2
4
  class Railtie < Rails::Railtie
3
5
 
4
6
  config.named_seeds = ActiveSupport::OrderedOptions.new
5
- config.named_seeds.app_load_seed = true
6
7
  config.named_seeds.engines_with_load_seed = []
7
8
 
8
9
  config.before_initialize do |app|
9
- Rails.application.paths.add 'db/test/seeds', with: 'db/test/seeds.rb'
10
- end
11
-
12
- rake_tasks do
13
- load "named_seeds/railties/databases.rake"
14
- end
15
-
16
- def setup
17
- load test_seed_file if test_seed_file
10
+ ActiveRecord::Tasks::DatabaseTasks.seed_loader = NamedSeeds::Railtie
18
11
  end
19
12
 
20
- def prepare
21
- return unless test_seed_file
22
- load_all_seeds
23
- setup
13
+ def load_seed
14
+ Rails.application.load_seed
15
+ engines_load_seed
24
16
  end
25
17
 
26
18
 
27
19
  protected
28
20
 
29
- def load_all_seeds
30
- ActiveRecord::Tasks::DatabaseTasks.load_seed if config.named_seeds.app_load_seed
21
+ def engines_load_seed
31
22
  config.named_seeds.engines_with_load_seed.each { |engine| engine.load_seed }
32
23
  end
33
24
 
34
- def test_seed_file
35
- Rails.application.paths["db/test/seeds"].existent.first
36
- end
37
-
38
25
  end
39
-
40
- def self.prepare
41
- NamedSeeds::Railtie.prepare
42
- end
43
-
44
26
  end
@@ -0,0 +1,18 @@
1
+ require 'securerandom'
2
+
3
+ module NamedSeeds
4
+
5
+ # Copy of ActiveSupport's Digest::UUID extension for v5 UUIDs.
6
+ # Needed to maintain backward compatibility with Rails 4.0 and 4.1.
7
+ #
8
+ def self.uuid_v5(name)
9
+ hash = Digest::SHA1.new
10
+ hash.update("k\xA7\xB8\x12\x9D\xAD\x11\xD1\x80\xB4\x00\xC0O\xD40\xC8")
11
+ hash.update(name.to_s)
12
+ ary = hash.digest.unpack('NnnnnN')
13
+ ary[2] = (ary[2] & 0x0FFF) | (5 << 12)
14
+ ary[3] = (ary[3] & 0x3FFF) | 0x8000
15
+ "%08x-%04x-%04x-%04x-%04x%08x" % ary
16
+ end
17
+
18
+ end
@@ -1,3 +1,19 @@
1
1
  module NamedSeeds
2
- VERSION = "1.1.0"
2
+
3
+ module VERSION
4
+ MAJOR = 2
5
+ MINOR = 0
6
+ TINY = 0
7
+ PRE = nil
8
+ STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
9
+ end
10
+
11
+ def self.version
12
+ Gem::Version.new VERSION::STRING
13
+ end
14
+
15
+ def self.version_string
16
+ VERSION::STRING
17
+ end
18
+
3
19
  end
@@ -2,20 +2,23 @@
2
2
  $:.push File.expand_path("../lib", __FILE__)
3
3
  require "named_seeds/version"
4
4
 
5
- Gem::Specification.new do |gem|
6
- gem.name = "named_seeds"
7
- gem.version = NamedSeeds::VERSION
8
- gem.authors = ["Ken Collins"]
9
- gem.email = ["ken@metaskills.net"]
10
- gem.summary = %q|Replace ActiveRecord::Fixtures With #{your_factory_lib}.|
11
- gem.description = %q|Make you tests fast by augmenting them with transactional fixtures powered by your favorite factory library!|
12
- gem.homepage = "http://github.com/metaskills/named_seeds"
13
- gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
14
- gem.files = `git ls-files`.split("\n")
15
- gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
16
- gem.require_paths = ["lib"]
17
- gem.add_runtime_dependency 'rails', '~> 4.2.0.beta2'
18
- gem.add_development_dependency 'sqlite3'
19
- gem.add_development_dependency 'rake'
20
- gem.add_development_dependency 'minitest'
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "named_seeds"
7
+ spec.version = NamedSeeds.version_string
8
+ spec.authors = ["Ken Collins"]
9
+ spec.email = ["ken@metaskills.net"]
10
+ spec.summary = %q|Replace ActiveRecord::Fixtures With #{your_factory_lib}.|
11
+ spec.description = %q|Make you tests fast by augmenting them with transactional fixtures powered by your favorite factory library!|
12
+ spec.homepage = "http://github.com/metaskills/named_seeds"
13
+ spec.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
14
+ spec.files = `git ls-files`.split("\n")
15
+ spec.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
16
+ spec.require_paths = ["lib"]
17
+ spec.add_runtime_dependency 'rails', '>= 4.0'
18
+ spec.add_development_dependency 'appraisal'
19
+ spec.add_development_dependency 'guard'
20
+ spec.add_development_dependency 'guard-minitest'
21
+ spec.add_development_dependency 'pry'
22
+ spec.add_development_dependency 'rake'
23
+ spec.add_development_dependency 'sqlite3'
21
24
  end
@@ -0,0 +1,13 @@
1
+ require 'test_helper'
2
+
3
+ class DslTest < NamedSeeds::TestCase
4
+
5
+ module T ; extend NamedSeeds::DSL ; end
6
+
7
+ def test_includes_all_methods
8
+ assert_equal 207281424, T.identify(:ruby)
9
+ assert_equal 207281424, T.id(:ruby)
10
+ end
11
+
12
+
13
+ end
@@ -0,0 +1,23 @@
1
+ require 'test_helper'
2
+
3
+ class IdentifyTest < NamedSeeds::TestCase
4
+
5
+ def test_works_on_strings
6
+ assert_equal id('foo'), id('foo')
7
+ assert_not_equal id('FOO'), id('foo')
8
+ end
9
+
10
+ def test_works_on_symbols
11
+ assert_equal id('foo'), id(:foo)
12
+ end
13
+
14
+ def test_identifies_consistently
15
+ assert_equal 207281424, id(:ruby)
16
+ assert_equal 1066363776, id(:sapphire_2)
17
+ end
18
+
19
+ def test_can_generate_uuid_identities
20
+ assert_match '4f156606-8cb3-509e-a177-956ca0a22015', id(:ken, :uuid)
21
+ end
22
+
23
+ end
@@ -0,0 +1,73 @@
1
+ require 'test_helper'
2
+
3
+ class NamedSeedsTest < NamedSeeds::TestCase
4
+
5
+ named_seeds :users
6
+ named_seeds :posts
7
+ named_seeds :states, identities: {virginia: 'VA', washington: 'WA'}
8
+ named_seeds :enterprise_objects
9
+
10
+ named_seeds :natural_id_states, identities: :natural, class: State
11
+ named_seeds :classy_users, class: User
12
+ named_seeds :no_model_class
13
+
14
+
15
+ def test_generated_method_that_can_find_a_record
16
+ assert_equal @@ken, users(:ken)
17
+ end
18
+
19
+ def test_not_found_is_just_plain_active_record_exceptions
20
+ assert_raise(ActiveRecord::RecordNotFound) { users(:not_found) }
21
+ end
22
+
23
+ def test_can_pass_multiple_names_to_fixture_accessor
24
+ assert_equal [@@ken, @@john], users(:ken, :john)
25
+ assert_equal [@@virginia, @@washington], states(:virginia, :washington)
26
+ assert_equal [@@virginia, @@washington], natural_id_states('VA', 'WA')
27
+ end
28
+
29
+ def test_can_find_string_primary_keys_using_identities_hash_option
30
+ assert_equal @@virginia, states(:virginia)
31
+ end
32
+
33
+ def test_can_find_string_primary_keys_using_identities_natural_option
34
+ assert_equal @@virginia, natural_id_states('VA')
35
+ end
36
+
37
+ def test_caches_fixture_lookups
38
+ assert_equal users(:ken).object_id, users(:ken).object_id
39
+ end
40
+
41
+ def test_can_reset_the_fixture_lookup_cache
42
+ ken1 = users(:ken)
43
+ NamedSeeds.reset_cache
44
+ ken2 = users(:ken)
45
+ assert_not_equal ken1.object_id, ken2.object_id
46
+ end
47
+
48
+ def test_can_define_a_bad_named_seed_with_no_model_and_lazily_see_an_exception
49
+ assert_raise(NamedSeeds::FixtureClassNotFound) { no_model_class(:name) }
50
+ end
51
+
52
+ def test_named_seeds_fixtur_class_not_found_subclasses_activerecords
53
+ assert NamedSeeds::FixtureClassNotFound < ActiveRecord::FixtureClassNotFound
54
+ end
55
+
56
+ def test_can_find_named_seed_with_uuid_primary_key
57
+ assert_equal @@enterprising_ken, enterprise_objects(:ken)
58
+ end unless TESTING_RAILS_40
59
+
60
+ end
61
+
62
+ module SomeNamespace
63
+ class User ; def self.find(id) ; self.new ; end ; end
64
+ class NamespacedActiveSupportTest < NamedSeeds::TestCase
65
+
66
+ named_seeds :users
67
+
68
+ def test_generated_method_finds_proper_constant
69
+ assert_equal @@ken, users(:ken)
70
+ end
71
+
72
+ end
73
+ end
@@ -1,14 +1,48 @@
1
1
  require 'active_record/base'
2
2
 
3
+ TESTING_RAILS_40 = Gem::Dependency.new('rails', '~> 4.0.0') =~ Gem::Dependency.new('rails', Rails::VERSION::STRING)
4
+ TESTING_RAILS_41 = Gem::Dependency.new('rails', '~> 4.1.0') =~ Gem::Dependency.new('rails', Rails::VERSION::STRING)
5
+ TESTING_RAILS_42 = Gem::Dependency.new('rails', '~> 4.2.0') =~ Gem::Dependency.new('rails', Rails::VERSION::STRING)
6
+
3
7
  ActiveRecord::Base.logger = nil
4
8
  ActiveRecord::Base.establish_connection adapter: 'sqlite3', database: ':memory:'
5
9
 
6
10
  ActiveRecord::Base.class_eval do
7
- silence(:stdout) do
11
+ connection.instance_eval do
8
12
 
9
- connection.create_table :users, force: true do |t|
13
+ create_table :users, force: true do |t|
10
14
  t.string :name, :email
11
15
  end
12
16
 
17
+ create_table :posts, id: false, force: true do |t|
18
+ t.primary_key :id, :uuid, default: nil
19
+ t.string :title, :body
20
+ t.references :user
21
+ end
22
+
23
+ create_table :states, id: false, force: true do |t|
24
+ t.primary_key :abbr, :string, default: nil
25
+ t.string :name
26
+ end
27
+
28
+ create_table :enterprise_objects, id: :uuid, primary_key: :id, force: true do |t|
29
+ t.string :name
30
+ end unless TESTING_RAILS_40
31
+
13
32
  end
14
33
  end
34
+
35
+ class User < ActiveRecord::Base
36
+ has_many :posts
37
+ end
38
+
39
+ class Post < ActiveRecord::Base
40
+ end
41
+
42
+ class State < ActiveRecord::Base
43
+ self.primary_key = :abbr
44
+ end
45
+
46
+ class EnterpriseObject < ActiveRecord::Base
47
+ self.primary_key = :id
48
+ end
@@ -1,15 +1,47 @@
1
1
  require 'rubygems'
2
- require "bundler/setup"
3
- Bundler.require
2
+ require 'bundler' ; Bundler.require :development, :test
4
3
  require 'named_seeds'
5
- require 'minitest/autorun'
6
4
  require 'support/active_record'
5
+ require 'active_support/test_case'
6
+ require 'active_support/testing/autorun'
7
7
 
8
- ActiveSupport.test_order = :random
8
+ ActiveSupport.test_order = :random if ActiveSupport.respond_to?(:test_order)
9
9
 
10
10
  module NamedSeeds
11
- class Spec < MiniTest::Spec
11
+ class TestCase < ActiveSupport::TestCase
12
12
 
13
+ class << self
14
+
15
+ def id(*args)
16
+ NamedSeeds.identify(*args)
17
+ end
18
+
19
+ def create_user(id, attributes={})
20
+ ::User.create!(attributes) { |x| x.id = id }
21
+ end
22
+
23
+ def create_state(id, attributes={})
24
+ ::State.create!(attributes) { |x| x.abbr = id }
25
+ end
26
+
27
+ def create_enterprise_object(id, attributes={})
28
+ ::EnterpriseObject.create!(attributes) { |x| x.id = id }
29
+ end
30
+
31
+ end
32
+
33
+ @@ken = create_user 155397742, name: 'Ken Collins', email: 'ken@metaskills.net'
34
+ @@john = create_user 830138774, name: 'John Hall', email: 'john.hall@example.com'
35
+
36
+ @@virginia = create_state 'VA', name: 'Virginia'
37
+ @@washington = create_state 'WA', name: 'Washington'
38
+
39
+ @@enterprising_ken = create_enterprise_object '4f156606-8cb3-509e-a177-956ca0a22015', name: 'Ken Collins' unless TESTING_RAILS_40
40
+
41
+
42
+ private
43
+
44
+ def id(*args) ; self.class.id(*args) ; end
13
45
 
14
46
  end
15
47
  end
metadata CHANGED
@@ -1,31 +1,73 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: named_seeds
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ken Collins
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-11-27 00:00:00.000000000 Z
11
+ date: 2015-03-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 4.2.0.beta2
19
+ version: '4.0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: 4.2.0.beta2
26
+ version: '4.0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: sqlite3
28
+ name: appraisal
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: guard
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: guard-minitest
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: pry
29
71
  requirement: !ruby/object:Gem::Requirement
30
72
  requirements:
31
73
  - - ">="
@@ -53,7 +95,7 @@ dependencies:
53
95
  - !ruby/object:Gem::Version
54
96
  version: '0'
55
97
  - !ruby/object:Gem::Dependency
56
- name: minitest
98
+ name: sqlite3
57
99
  requirement: !ruby/object:Gem::Requirement
58
100
  requirements:
59
101
  - - ">="
@@ -75,22 +117,27 @@ extensions: []
75
117
  extra_rdoc_files: []
76
118
  files:
77
119
  - ".gitignore"
120
+ - ".travis.yml"
121
+ - Appraisals
78
122
  - CHANGELOG.md
79
123
  - Gemfile
124
+ - Guardfile
80
125
  - LICENSE
81
126
  - README.md
82
127
  - Rakefile
128
+ - TODO.md
83
129
  - lib/named_seeds.rb
84
- - lib/named_seeds/active_support.rb
130
+ - lib/named_seeds/dsl.rb
85
131
  - lib/named_seeds/identity.rb
132
+ - lib/named_seeds/rails.rb
86
133
  - lib/named_seeds/railtie.rb
87
- - lib/named_seeds/railties/databases.rake
88
- - lib/named_seeds/read.rb
134
+ - lib/named_seeds/uuid.rb
89
135
  - lib/named_seeds/version.rb
90
136
  - named_seeds.gemspec
91
- - test/cases/base_test.rb
137
+ - test/cases/dsl_test.rb
138
+ - test/cases/identify_test.rb
139
+ - test/cases/named_seeds_test.rb
92
140
  - test/support/active_record.rb
93
- - test/support/models.rb
94
141
  - test/test_helper.rb
95
142
  homepage: http://github.com/metaskills/named_seeds
96
143
  licenses: []
@@ -116,7 +163,8 @@ signing_key:
116
163
  specification_version: 4
117
164
  summary: 'Replace ActiveRecord::Fixtures With #{your_factory_lib}.'
118
165
  test_files:
119
- - test/cases/base_test.rb
166
+ - test/cases/dsl_test.rb
167
+ - test/cases/identify_test.rb
168
+ - test/cases/named_seeds_test.rb
120
169
  - test/support/active_record.rb
121
- - test/support/models.rb
122
170
  - test/test_helper.rb
@@ -1,4 +0,0 @@
1
- require 'active_support/test_case'
2
-
3
- ActiveSupport::TestCase.send :include, NamedSeeds::Read
4
-
@@ -1,14 +0,0 @@
1
- namespace :named_seeds do
2
-
3
- task :setup => :environment do
4
- NamedSeeds::Railtie.setup
5
- end
6
-
7
- task :prepare do
8
- NamedSeeds::Railtie.prepare
9
- end
10
-
11
- end
12
-
13
- Rake::Task['db:setup'].enhance { Rake::Task['named_seeds:setup'].invoke }
14
- Rake::Task['db:test:prepare'].enhance { Rake::Task['named_seeds:prepare'].invoke }
@@ -1,50 +0,0 @@
1
- require 'active_support/concern'
2
-
3
- module NamedSeeds
4
- module Read
5
-
6
- extend ActiveSupport::Concern
7
-
8
- module ClassMethods
9
-
10
- def named_seeds(name, options = {})
11
- klass = options[:klass] || name.to_s.classify.constantize
12
- identities = options[:identities]
13
- case identities
14
- when Hash
15
- define_method(name) do |*fixnames|
16
- objs = fixnames.map do |fixname|
17
- id = identities[fixname.to_sym]
18
- find_named_seed name, klass, id, fixname
19
- end
20
- fixnames.one? ? objs.first : objs
21
- end
22
- else
23
- define_method(name) do |*fixnames|
24
- objs = fixnames.map do |fixname|
25
- id = NamedSeeds.identify(fixname)
26
- find_named_seed name, klass, id, fixname
27
- end
28
- fixnames.one? ? objs.first : objs
29
- end
30
- end
31
- end
32
-
33
- end
34
-
35
- protected
36
-
37
- def find_named_seed(name, klass, id, fixname)
38
- begin
39
- klass.find(id)
40
- rescue ActiveRecord::RecordNotFound => e
41
- nsfinder = :"#{name}_#{fixname}"
42
- raise e unless respond_to?(nsfinder)
43
- send(nsfinder)
44
- end
45
- end
46
-
47
-
48
- end
49
- end
50
-
@@ -1,23 +0,0 @@
1
- require 'test_helper'
2
-
3
- class BaseTest < NamedSeeds::Spec
4
-
5
- describe 'identifiy' do
6
-
7
- it 'works on strings' do
8
- NamedSeeds.identify('foo').must_equal NamedSeeds.identify('foo')
9
- NamedSeeds.identify('foo').wont_equal NamedSeeds.identify('FOO')
10
- end
11
-
12
- it 'works on symbols' do
13
- NamedSeeds.identify(:foo).must_equal NamedSeeds.identify(:foo)
14
- end
15
-
16
- it 'identifies consistently' do
17
- NamedSeeds.identify(:ruby).must_equal 207281424
18
- NamedSeeds.identify(:sapphire_2).must_equal 1066363776
19
- end
20
-
21
- end
22
-
23
- end
@@ -1,4 +0,0 @@
1
-
2
- class User < ActiveRecord::Base
3
-
4
- end