fabricators 0.0.1

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 (76) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.rdoc +134 -0
  4. data/Rakefile +32 -0
  5. data/lib/fabricators.rb +41 -0
  6. data/lib/fabricators/callbacks.rb +23 -0
  7. data/lib/fabricators/definitions.rb +58 -0
  8. data/lib/fabricators/fabricator.rb +102 -0
  9. data/lib/fabricators/generator.rb +19 -0
  10. data/lib/fabricators/methods.rb +11 -0
  11. data/lib/fabricators/proxy.rb +45 -0
  12. data/lib/fabricators/railtie.rb +14 -0
  13. data/lib/fabricators/reader.rb +18 -0
  14. data/lib/fabricators/version.rb +5 -0
  15. data/lib/generators/fabricators/model/model_generator.rb +15 -0
  16. data/lib/generators/fabricators/model/templates/fabricator.rb +4 -0
  17. data/test/aliases_test.rb +25 -0
  18. data/test/associations_test.rb +50 -0
  19. data/test/callbacks_test.rb +36 -0
  20. data/test/dependent_test.rb +26 -0
  21. data/test/dummy/README.rdoc +28 -0
  22. data/test/dummy/Rakefile +6 -0
  23. data/test/dummy/app/assets/javascripts/application.js +13 -0
  24. data/test/dummy/app/assets/stylesheets/application.css +15 -0
  25. data/test/dummy/app/controllers/application_controller.rb +5 -0
  26. data/test/dummy/app/helpers/application_helper.rb +2 -0
  27. data/test/dummy/app/models/group.rb +2 -0
  28. data/test/dummy/app/models/post.rb +3 -0
  29. data/test/dummy/app/models/user.rb +3 -0
  30. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  31. data/test/dummy/bin/bundle +3 -0
  32. data/test/dummy/bin/rails +4 -0
  33. data/test/dummy/bin/rake +4 -0
  34. data/test/dummy/config.ru +4 -0
  35. data/test/dummy/config/application.rb +22 -0
  36. data/test/dummy/config/boot.rb +5 -0
  37. data/test/dummy/config/database.yml +25 -0
  38. data/test/dummy/config/environment.rb +5 -0
  39. data/test/dummy/config/environments/development.rb +37 -0
  40. data/test/dummy/config/environments/production.rb +83 -0
  41. data/test/dummy/config/environments/test.rb +39 -0
  42. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  43. data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
  44. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  45. data/test/dummy/config/initializers/inflections.rb +16 -0
  46. data/test/dummy/config/initializers/mime_types.rb +4 -0
  47. data/test/dummy/config/initializers/session_store.rb +3 -0
  48. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  49. data/test/dummy/config/locales/en.yml +23 -0
  50. data/test/dummy/config/routes.rb +56 -0
  51. data/test/dummy/config/secrets.yml +22 -0
  52. data/test/dummy/db/migrate/20140613221835_create_users.rb +10 -0
  53. data/test/dummy/db/migrate/20140615152257_add_age_to_users.rb +5 -0
  54. data/test/dummy/db/migrate/20140615175509_add_phone_to_users.rb +5 -0
  55. data/test/dummy/db/migrate/20140615180938_create_groups.rb +9 -0
  56. data/test/dummy/db/migrate/20140615180954_create_posts.rb +9 -0
  57. data/test/dummy/db/migrate/20140615181030_add_group_id_to_users.rb +5 -0
  58. data/test/dummy/db/migrate/20140615181051_add_user_id_to_posts.rb +5 -0
  59. data/test/dummy/db/schema.rb +39 -0
  60. data/test/dummy/log/development.log +0 -0
  61. data/test/dummy/log/test.log +14513 -0
  62. data/test/dummy/public/404.html +67 -0
  63. data/test/dummy/public/422.html +67 -0
  64. data/test/dummy/public/500.html +66 -0
  65. data/test/dummy/public/favicon.ico +0 -0
  66. data/test/dummy/test/fabricators/people.rb +4 -0
  67. data/test/dummy/test/fabricators/users.rb +5 -0
  68. data/test/fabricators_test.rb +33 -0
  69. data/test/fixtures_test.rb +13 -0
  70. data/test/generators_test.rb +36 -0
  71. data/test/inheritance_test.rb +49 -0
  72. data/test/lists_test.rb +33 -0
  73. data/test/load_test.rb +13 -0
  74. data/test/merges_test.rb +31 -0
  75. data/test/test_helper.rb +27 -0
  76. metadata +211 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: bf4172edafa15e0c0a33f21c7b468a9dc0b174b7
4
+ data.tar.gz: 9e96fe2c40e58ace973698c3f59ac8cc3822a077
5
+ SHA512:
6
+ metadata.gz: 53c4e36450a96f6acda28bced824e382a8c45f706d1a83245c2773f0b67e1a59988f25a85392f9822b4074354102a4329b39522cfcb6c7ef1d89edc13634cacf
7
+ data.tar.gz: 239e928ca1e1a2b3f96be3045a27df12eabce2d385bb942a489f23e0c38c862f55516ac07f5de696cd5d175b843d17c639708992f0b291edb18458353995c69f
@@ -0,0 +1,20 @@
1
+ Copyright 2014 Museways
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,134 @@
1
+ {<img src="https://badge.fury.io/rb/fabricators.png" alt="Gem Version" />}[http://badge.fury.io/rb/fabricators] {<img src="https://codeclimate.com/github/museways/fabricators.png" />}[https://codeclimate.com/github/museways/fabricators] {<img src="https://travis-ci.org/museways/fabricators.png?branch=master" alt="Build Status" />}[https://travis-ci.org/museways/fabricators] {<img src="https://gemnasium.com/museways/fabricators.png" alt="Dependency Status" />}[https://gemnasium.com/museways/fabricators]
2
+
3
+ = Fabricators
4
+
5
+ Minimalistic factory alternative inspired in factory_girl.
6
+
7
+ = Install
8
+
9
+ Put this line in your Gemfile:
10
+ gem 'fabricators'
11
+
12
+ Then bundle:
13
+ $ bundle
14
+
15
+ = Configuration
16
+
17
+ There is no need to configure the rails application, the gem will do it automatically.
18
+
19
+ = Usage
20
+
21
+ == Methods
22
+
23
+ There are three methods available:
24
+ Fabricators.attributes_for
25
+ Fabricators.build
26
+ Fabricators.create
27
+
28
+ To not write "Fabricators" every time you can include the methods in your tests:
29
+ class ActiveSupport::TestCase
30
+ include Fabricators::Methods
31
+ end
32
+
33
+ Then you can you just:
34
+ attributes_for
35
+ build
36
+ create
37
+
38
+ Is possible to override the defaults passing a hash:
39
+ build :user, name: 'other'
40
+ create :category, title: 'other'
41
+
42
+ To create lists just pass the desired size as second parameter to build and create:
43
+ build :user, 2, name: 'other'
44
+ create :category, 5, title: 'other'
45
+
46
+ == Fabricators
47
+
48
+ The way you define your fabricators should be very familiar already.
49
+ Fabricators.define do
50
+ fabricator :user do
51
+ name 'example'
52
+ end
53
+ end
54
+
55
+ == Inehritance
56
+
57
+ Can be declare nested or separate:
58
+ Fabricators.define do
59
+ fabricator :user do
60
+ name 'example'
61
+ fabricator :user_with_email do
62
+ email 'example@mail.com'
63
+ end
64
+ end
65
+ fabricator :user_with_age, parent: :user do
66
+ age 9
67
+ end
68
+ end
69
+
70
+ == Generators
71
+
72
+ Define them outside your fabricators and use them as attributes:
73
+ Fabricators.define do
74
+ generator(:name) { 'example' }
75
+ generator(:email) { |n| "example#{n}@mail.com" }
76
+ generator(:age)
77
+ fabricator :user do
78
+ name
79
+ email
80
+ age
81
+ end
82
+ end
83
+
84
+ == Associations
85
+
86
+ Associations are declared just by the name of the association:
87
+ Fabricators.define do
88
+ fabricator :user do
89
+ posts
90
+ comments 4 # By default 1, but can be overwritten
91
+ end
92
+ fabricator :post do
93
+ user
94
+ end
95
+ fabricator :comment do
96
+ user
97
+ end
98
+ end
99
+
100
+ == Aliases
101
+
102
+ The aliases are essential when there is the need of context:
103
+ Fabricators.define do
104
+ generator(:title, aliases: [:first_name, :last_name]) { 'example' }
105
+ fabricators :user, aliases: :author do
106
+ first_name
107
+ last_name
108
+ comments
109
+ end
110
+ fabricators :post, aliases: :comment do
111
+ title
112
+ author
113
+ end
114
+ end
115
+
116
+ == Dependent attributes
117
+
118
+ If you need to use some logic that depends of another attribute you can go:
119
+ Fabricators.define do
120
+ fabricators :user do
121
+ name 'example'
122
+ email { "#{name}@mail.com" }
123
+ end
124
+ end
125
+
126
+ == Callbacks
127
+
128
+ The available callbacks are before(:build), before(:create), after(:build) and after(:create):
129
+ Fabricators.define do
130
+ before(:build) { |u| u.name = 'global' }
131
+ fabricator :user do
132
+ after(:build) { |u| u.name = 'local' }
133
+ end
134
+ end
@@ -0,0 +1,32 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'Fabricators'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.rdoc')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+
18
+
19
+
20
+ Bundler::GemHelper.install_tasks
21
+
22
+ require 'rake/testtask'
23
+
24
+ Rake::TestTask.new(:test) do |t|
25
+ t.libs << 'lib'
26
+ t.libs << 'test'
27
+ t.pattern = 'test/**/*_test.rb'
28
+ t.verbose = false
29
+ end
30
+
31
+
32
+ task default: :test
@@ -0,0 +1,41 @@
1
+ require 'fabricators/callbacks'
2
+ require 'fabricators/definitions'
3
+ require 'fabricators/fabricator'
4
+ require 'fabricators/generator'
5
+ require 'fabricators/reader'
6
+ require 'fabricators/proxy'
7
+ require 'fabricators/methods'
8
+ require 'fabricators/railtie'
9
+
10
+ module Fabricators
11
+ extend Methods
12
+ class << self
13
+
14
+ def define(&block)
15
+ definitions.instance_eval &block
16
+ end
17
+
18
+ def definitions
19
+ @definitions ||= Definitions.new
20
+ end
21
+
22
+ def generate(name)
23
+ definitions.find(name, :generator).generate
24
+ end
25
+
26
+ def paths
27
+ @paths ||= %w(test/fabricators spec/fabricators).map { |path| Rails.root.join(path) }
28
+ end
29
+
30
+ def path
31
+ @path ||= paths.find { |path| Dir.exists? path }
32
+ end
33
+
34
+ def populate
35
+ Dir[path.join('**', '*.rb')].each do |file|
36
+ load file
37
+ end
38
+ end
39
+
40
+ end
41
+ end
@@ -0,0 +1,23 @@
1
+ module Fabricators
2
+ module Callbacks
3
+
4
+ def callbacks
5
+ @callbacks ||= {}
6
+ end
7
+
8
+ %w(after before).each do |moment|
9
+ define_method moment do |actions, &block|
10
+ actions = [actions] unless actions.is_a? Array
11
+ actions.each do |action|
12
+ name = :"#{moment}_#{action}"
13
+ if callbacks[name]
14
+ callbacks[name] << block
15
+ else
16
+ callbacks[name] = [block]
17
+ end
18
+ end
19
+ end
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,58 @@
1
+ module Fabricators
2
+ class Definitions
3
+ include Callbacks
4
+
5
+ def initialize
6
+ reset!
7
+ end
8
+
9
+ def reset!
10
+ @fabricators = {}
11
+ @generators = {}
12
+ @callbacks = {}
13
+ end
14
+
15
+ def fabricator(name, options={}, &block)
16
+ fabricator = Fabricator.new(name, options, &block)
17
+ iterate_names name, options do |name|
18
+ @fabricators[name] = fabricator
19
+ end
20
+ end
21
+
22
+ def generator(name, first=0, options={}, &block)
23
+ generator = Generator.new(first, &block)
24
+ iterate_names name, options do |name|
25
+ @generators[name] = generator
26
+ end
27
+ end
28
+
29
+ def find(name, type)
30
+ case type
31
+ when :fabricator
32
+ @fabricators[name]
33
+ when :generator
34
+ @generators[name]
35
+ end.tap do |definition|
36
+ raise "Definition #{name} of type #{type} not found" unless definition
37
+ end
38
+ end
39
+
40
+ protected
41
+
42
+ def iterate_names(name, options)
43
+ names = [name]
44
+ if aliases = options[:aliases]
45
+ case aliases
46
+ when Array
47
+ names |= aliases
48
+ else
49
+ names << aliases
50
+ end
51
+ end
52
+ names.each do |name|
53
+ yield name
54
+ end
55
+ end
56
+
57
+ end
58
+ end
@@ -0,0 +1,102 @@
1
+ module Fabricators
2
+ class Fabricator
3
+
4
+ attr_reader :options, :proxy
5
+
6
+ def initialize(name, options={}, &block)
7
+ @name = name
8
+ @options = options
9
+ @block = block
10
+ @loaded = false
11
+ Reader.new(name, options, &block)
12
+ end
13
+
14
+ def parent
15
+ @parent ||= begin
16
+ if @options[:parent]
17
+ Fabricators.definitions.find(@options[:parent], :fabricator)
18
+ end
19
+ end
20
+ end
21
+
22
+ def attributes_for(options={})
23
+ {}.tap do |hash|
24
+ iterate_attributes(options, proxy) do |name, value|
25
+ hash[name] = value
26
+ end
27
+ end
28
+ end
29
+
30
+ %w(build create).each do |name|
31
+ define_method name do |*args|
32
+ options = args.extract_options!
33
+ single_name = :"#{name}_one"
34
+ if args.any?
35
+ [].tap do |list|
36
+ args.first.times do
37
+ list << send(single_name, options)
38
+ end
39
+ end
40
+ else
41
+ send(single_name, options)
42
+ end
43
+ end
44
+ end
45
+
46
+ %w(options attributes_for build create).each do |name|
47
+ define_method :"#{name}_with_load" do |*args|
48
+ load
49
+ send :"#{name}_without_load", *args
50
+ end
51
+ alias_method_chain name, :load
52
+ end
53
+
54
+ protected
55
+
56
+ def load
57
+ unless @loaded
58
+ if parent
59
+ @options = parent.options.merge(@options)
60
+ end
61
+ unless @options[:class] ||= @name.to_s.classify.constantize
62
+ raise "Class not found for fabricator #{@name}"
63
+ end
64
+ @proxy = Proxy.new(self, &@block)
65
+ @loaded = true
66
+ end
67
+ end
68
+
69
+ def build_one(options={})
70
+ @options[:class].new.tap do |instance|
71
+ trigger :before_build, instance
72
+ iterate_attributes(options, instance) do |name, value|
73
+ instance.send :"#{name}=", value
74
+ end
75
+ trigger :after_build, instance
76
+ end
77
+ end
78
+
79
+ def create_one(options={})
80
+ build_one(options).tap do |instance|
81
+ trigger :before_create, instance
82
+ instance.save
83
+ trigger :after_create, instance
84
+ end
85
+ end
86
+
87
+ def trigger(name, instance)
88
+ globals = (Fabricators.definitions.callbacks[name] || [])
89
+ locals = (proxy.callbacks[name] || [])
90
+ (globals + locals).each do |callback|
91
+ callback.call instance
92
+ end
93
+ end
94
+
95
+ def iterate_attributes(options={}, context)
96
+ proxy.attributes.merge(options).each do |name, value|
97
+ yield name, (value.is_a?(Proc) ? context.instance_eval(&value) : value)
98
+ end
99
+ end
100
+
101
+ end
102
+ end
@@ -0,0 +1,19 @@
1
+ module Fabricators
2
+ class Generator
3
+
4
+ def initialize(starts_at, &block)
5
+ @index = starts_at
6
+ @block = block
7
+ end
8
+
9
+ def generate
10
+ @index += 1
11
+ if @block
12
+ @block.call(@index)
13
+ else
14
+ @index
15
+ end
16
+ end
17
+
18
+ end
19
+ end