machinist_redux 3.0.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.
- checksums.yaml +7 -0
- data/.codeclimate.yml +17 -0
- data/.gitignore +24 -0
- data/.rspec +2 -0
- data/.rubocop.yml +60 -0
- data/.rubocop_todo.yml +92 -0
- data/.travis.yml +23 -0
- data/Appraisals +11 -0
- data/Gemfile +32 -0
- data/LICENSE.txt +21 -0
- data/README.md +307 -0
- data/Rakefile +20 -0
- data/gemfiles/rails_4.2.gemfile +38 -0
- data/gemfiles/rails_4.2.gemfile.lock +232 -0
- data/gemfiles/rails_5.0.gemfile +38 -0
- data/gemfiles/rails_5.0.gemfile.lock +232 -0
- data/gemfiles/rails_5.1.gemfile +34 -0
- data/gemfiles/rails_5.1.gemfile.lock +231 -0
- data/lib/generators/machinist/install/USAGE +2 -0
- data/lib/generators/machinist/install/install_generator.rb +46 -0
- data/lib/generators/machinist/install/templates/blueprints.rb +9 -0
- data/lib/generators/machinist/install/templates/machinist.rb.erb +7 -0
- data/lib/generators/machinist/model/model_generator.rb +11 -0
- data/lib/machinist.rb +5 -0
- data/lib/machinist/active_record.rb +14 -0
- data/lib/machinist/active_record/blueprint.rb +14 -0
- data/lib/machinist/active_record/lathe.rb +21 -0
- data/lib/machinist/blueprint.rb +84 -0
- data/lib/machinist/exceptions.rb +30 -0
- data/lib/machinist/lathe.rb +65 -0
- data/lib/machinist/machinable.rb +100 -0
- data/lib/machinist/version.rb +3 -0
- data/machinist.gemspec +23 -0
- data/spec/machinist/active_record_spec.rb +106 -0
- data/spec/machinist/blueprint_inheritance_spec.rb +101 -0
- data/spec/machinist/blueprint_spec.rb +76 -0
- data/spec/machinist/exceptions_spec.rb +16 -0
- data/spec/machinist/machinable_spec.rb +91 -0
- data/spec/spec_helper.rb +110 -0
- data/spec/support/active_record_environment.rb +62 -0
- metadata +94 -0
@@ -0,0 +1,30 @@
|
|
1
|
+
module Machinist
|
2
|
+
# Raised when make! is called on a class whose blueprints don't support
|
3
|
+
# saving.
|
4
|
+
class BlueprintCantSaveError < RuntimeError
|
5
|
+
attr_reader :blueprint
|
6
|
+
|
7
|
+
def initialize(blueprint)
|
8
|
+
@blueprint = blueprint
|
9
|
+
end
|
10
|
+
|
11
|
+
def message
|
12
|
+
"make! is not supported by blueprints for class #{@blueprint.klass.name}"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# Raised when calling make on a class with no corresponding blueprint
|
17
|
+
# defined.
|
18
|
+
class NoBlueprintError < RuntimeError
|
19
|
+
attr_reader :klass, :name
|
20
|
+
|
21
|
+
def initialize(klass, name)
|
22
|
+
@klass = klass
|
23
|
+
@name = name
|
24
|
+
end
|
25
|
+
|
26
|
+
def message
|
27
|
+
"No #{@name} blueprint defined for class #{@klass.name}"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module Machinist
|
2
|
+
# When you make an object, the blueprint for that object is instance-evaled
|
3
|
+
# against a Lathe.
|
4
|
+
#
|
5
|
+
# The Lathe implements all the methods that are available to the blueprint,
|
6
|
+
# including method_missing to let the blueprint define attributes.
|
7
|
+
class Lathe
|
8
|
+
def initialize(klass, serial_number, attributes = {})
|
9
|
+
@klass = klass
|
10
|
+
@serial_number = serial_number
|
11
|
+
@assigned_attributes = {}
|
12
|
+
|
13
|
+
@object = @klass.new
|
14
|
+
attributes.each { |key, value| assign_attribute(key, value) }
|
15
|
+
end
|
16
|
+
|
17
|
+
# Returns a unique serial number for the object under construction.
|
18
|
+
def sn
|
19
|
+
@serial_number
|
20
|
+
end
|
21
|
+
|
22
|
+
# Returns the object under construction.
|
23
|
+
attr_reader :object
|
24
|
+
|
25
|
+
def method_missing(attribute, *args, &block) #:nodoc:
|
26
|
+
unless attribute_assigned?(attribute)
|
27
|
+
assign_attribute(attribute, make_attribute(attribute, args, &block))
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Undef a couple of methods that are common ActiveRecord attributes.
|
32
|
+
# (Both of these are deprecated in Ruby 1.8 anyway.)
|
33
|
+
undef_method :id if respond_to?(:id)
|
34
|
+
undef_method :type if respond_to?(:type)
|
35
|
+
|
36
|
+
protected
|
37
|
+
|
38
|
+
def make_attribute(attribute, args, &block) #:nodoc:
|
39
|
+
count = args.shift if args.first.is_a?(0.class)
|
40
|
+
if count
|
41
|
+
Array.new(count) { make_one_value(attribute, args, &block) }
|
42
|
+
else
|
43
|
+
make_one_value(attribute, args, &block)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def make_one_value(attribute, args) #:nodoc:
|
48
|
+
raise_argument_error(attribute) unless args.empty?
|
49
|
+
yield
|
50
|
+
end
|
51
|
+
|
52
|
+
def assign_attribute(key, value) #:nodoc:
|
53
|
+
@assigned_attributes[key.to_sym] = value
|
54
|
+
@object.send("#{key}=", value)
|
55
|
+
end
|
56
|
+
|
57
|
+
def attribute_assigned?(key) #:nodoc:
|
58
|
+
@assigned_attributes.key?(key.to_sym)
|
59
|
+
end
|
60
|
+
|
61
|
+
def raise_argument_error(attribute) #:nodoc:
|
62
|
+
raise ArgumentError, "Invalid arguments to attribute #{attribute} in blueprint"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
module Machinist
|
2
|
+
# Extend classes with this module to define the blueprint and make methods.
|
3
|
+
module Machinable
|
4
|
+
# Define a blueprint with the given name for this class.
|
5
|
+
#
|
6
|
+
# e.g.
|
7
|
+
# Post.blueprint do
|
8
|
+
# title { "A Post" }
|
9
|
+
# body { "Lorem ipsum..." }
|
10
|
+
# end
|
11
|
+
#
|
12
|
+
# If you provide the +name+ argument, a named blueprint will be created.
|
13
|
+
# See the +blueprint_name+ argument to the make method.
|
14
|
+
def blueprint(name = :master, &block)
|
15
|
+
@blueprints ||= {}
|
16
|
+
if block_given?
|
17
|
+
parent = (name == :master ? superclass : self) # Where should we look for the parent blueprint?
|
18
|
+
@blueprints[name] = blueprint_class.new(self, parent: parent, &block)
|
19
|
+
end
|
20
|
+
@blueprints[name]
|
21
|
+
end
|
22
|
+
|
23
|
+
# Construct an object from a blueprint.
|
24
|
+
#
|
25
|
+
# :call-seq:
|
26
|
+
# make([count], [blueprint_name], [attributes = {}])
|
27
|
+
#
|
28
|
+
# [+count+]
|
29
|
+
# The number of objects to construct. If +count+ is provided, make
|
30
|
+
# returns an array of objects rather than a single object.
|
31
|
+
# [+blueprint_name+]
|
32
|
+
# Construct the object from the named blueprint, rather than the master
|
33
|
+
# blueprint.
|
34
|
+
# [+attributes+]
|
35
|
+
# Override the attributes from the blueprint with values from this hash.
|
36
|
+
def make(*args)
|
37
|
+
decode_args_to_make(*args) do |blueprint, attributes|
|
38
|
+
blueprint.make(attributes)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# Construct and save an object from a blueprint, if the class allows saving.
|
43
|
+
#
|
44
|
+
# :call-seq:
|
45
|
+
# make!([count], [blueprint_name], [attributes = {}])
|
46
|
+
#
|
47
|
+
# Arguments are the same as for make.
|
48
|
+
def make!(*args)
|
49
|
+
decode_args_to_make(*args) do |blueprint, attributes|
|
50
|
+
raise BlueprintCantSaveError, blueprint unless blueprint.respond_to?(:make!)
|
51
|
+
blueprint.make!(attributes)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# Remove all blueprints defined on this class.
|
56
|
+
def clear_blueprints!
|
57
|
+
@blueprints = {}
|
58
|
+
end
|
59
|
+
|
60
|
+
# Classes that include Machinable can override this method if they want to
|
61
|
+
# use a custom blueprint class when constructing blueprints.
|
62
|
+
#
|
63
|
+
# The default is Machinist::Blueprint.
|
64
|
+
def blueprint_class
|
65
|
+
Machinist::Blueprint
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
# Parses the arguments to make.
|
71
|
+
#
|
72
|
+
# Yields a blueprint and an attributes hash to the block, which should
|
73
|
+
# construct an object from them. The block may be called multiple times to
|
74
|
+
# construct multiple objects.
|
75
|
+
def decode_args_to_make(*args) #:nodoc:
|
76
|
+
count, name, attributes = *decode_args(args)
|
77
|
+
blueprint = ensure_blueprint(name)
|
78
|
+
|
79
|
+
if count.nil?
|
80
|
+
yield(blueprint, attributes)
|
81
|
+
else
|
82
|
+
Array.new(count) { yield(blueprint, attributes) }
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def decode_args(args)
|
87
|
+
shift_arg = ->(klass) { args.shift if args.first.is_a?(klass) }
|
88
|
+
count = shift_arg[0.class]
|
89
|
+
name = shift_arg[Symbol] || :master
|
90
|
+
attributes = shift_arg[Hash] || {}
|
91
|
+
raise ArgumentError, "Couldn't understand arguments" unless args.empty?
|
92
|
+
[count, name, attributes]
|
93
|
+
end
|
94
|
+
|
95
|
+
def ensure_blueprint(name)
|
96
|
+
@blueprints ||= {}
|
97
|
+
@blueprints[name] || raise(NoBlueprintError.new(self, name))
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
data/machinist.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
lib = File.expand_path('../lib', __FILE__)
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
+
require 'machinist/version'
|
6
|
+
|
7
|
+
Gem::Specification.new do |gem|
|
8
|
+
gem.name = 'machinist_redux'
|
9
|
+
gem.version = Machinist::VERSION
|
10
|
+
gem.authors = ['Pete Yandell', 'Attila Györffy', 'Dominic Sayers']
|
11
|
+
gem.email = ['dominic@sayers.cc']
|
12
|
+
gem.description = 'Machinist makes it easy to create objects for use in tests. It generates data for the ' \
|
13
|
+
"attributes you don't care about, and constructs any necessary associated objects, leaving you "\
|
14
|
+
'to specify only the fields you care about in your test.'
|
15
|
+
gem.summary = "Fixtures aren't fun. Machinist was."
|
16
|
+
gem.homepage = 'http://github.com/dominicsayers/machinist'
|
17
|
+
gem.license = 'MIT'
|
18
|
+
|
19
|
+
gem.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
|
20
|
+
gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
|
21
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
22
|
+
gem.require_paths = ['lib']
|
23
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
require 'support/active_record_environment'
|
2
|
+
|
3
|
+
RSpec.describe Machinist::ActiveRecord do
|
4
|
+
include ActiveRecordEnvironment
|
5
|
+
|
6
|
+
before do
|
7
|
+
empty_database!
|
8
|
+
end
|
9
|
+
|
10
|
+
context 'make' do
|
11
|
+
it 'returns an unsaved object' do
|
12
|
+
Post.blueprint {}
|
13
|
+
post = Post.make
|
14
|
+
expect(post).to be_a(Post)
|
15
|
+
expect(post).to be_new_record
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
context 'make!' do
|
20
|
+
it 'makes and saves objects' do
|
21
|
+
Post.blueprint {}
|
22
|
+
post = Post.make!
|
23
|
+
expect(post).to be_a(Post)
|
24
|
+
expect(post).not_to be_new_record
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'raises an exception for an invalid object' do
|
28
|
+
User.blueprint {}
|
29
|
+
expect do
|
30
|
+
User.make!(username: '')
|
31
|
+
end.to raise_error(ActiveRecord::RecordInvalid)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context 'associations support' do
|
36
|
+
it 'handles belongs_to associations' do
|
37
|
+
User.blueprint do
|
38
|
+
username { "user_#{sn}" }
|
39
|
+
end
|
40
|
+
Post.blueprint do
|
41
|
+
author
|
42
|
+
end
|
43
|
+
post = Post.make!
|
44
|
+
expect(post).to be_a(Post)
|
45
|
+
expect(post).not_to be_new_record
|
46
|
+
expect(post.author).to be_a(User)
|
47
|
+
expect(post.author).not_to be_new_record
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'handles has_many associations' do
|
51
|
+
Post.blueprint do
|
52
|
+
comments(3)
|
53
|
+
end
|
54
|
+
Comment.blueprint {}
|
55
|
+
post = Post.make!
|
56
|
+
expect(post).to be_a(Post)
|
57
|
+
expect(post).not_to be_new_record
|
58
|
+
expect(post.comments.size).to eq(3)
|
59
|
+
post.comments.each do |comment|
|
60
|
+
expect(comment).to be_a(Comment)
|
61
|
+
expect(comment).not_to be_new_record
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'handles habtm associations' do
|
66
|
+
Post.blueprint do
|
67
|
+
tags(3)
|
68
|
+
end
|
69
|
+
Tag.blueprint do
|
70
|
+
name { "tag_#{sn}" }
|
71
|
+
end
|
72
|
+
post = Post.make!
|
73
|
+
expect(post).to be_a(Post)
|
74
|
+
expect(post).not_to be_new_record
|
75
|
+
expect(post.tags.size).to eq(3)
|
76
|
+
post.tags.each do |tag|
|
77
|
+
expect(tag).to be_a(Tag)
|
78
|
+
expect(tag).not_to be_new_record
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'handles overriding associations' do
|
83
|
+
User.blueprint do
|
84
|
+
username { "user_#{sn}" }
|
85
|
+
end
|
86
|
+
Post.blueprint do
|
87
|
+
author { User.make(username: "post_author_#{sn}") }
|
88
|
+
end
|
89
|
+
post = Post.make!
|
90
|
+
expect(post).to be_a(Post)
|
91
|
+
expect(post).not_to be_new_record
|
92
|
+
expect(post.author).to be_a(User)
|
93
|
+
expect(post.author).not_to be_new_record
|
94
|
+
expect(post.author.username).to match(/^post_author_\d+$/)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
context 'error handling' do
|
99
|
+
it 'raises an exception for an attribute with no value' do
|
100
|
+
User.blueprint { username }
|
101
|
+
expect do
|
102
|
+
User.make
|
103
|
+
end.to raise_error(ArgumentError)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
|
3
|
+
module InheritanceSpecs
|
4
|
+
class Grandpa
|
5
|
+
extend Machinist::Machinable
|
6
|
+
attr_accessor :name, :age
|
7
|
+
end
|
8
|
+
|
9
|
+
class Dad < Grandpa
|
10
|
+
extend Machinist::Machinable
|
11
|
+
attr_accessor :name, :age
|
12
|
+
end
|
13
|
+
|
14
|
+
class Son < Dad
|
15
|
+
extend Machinist::Machinable
|
16
|
+
attr_accessor :name, :age
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
RSpec.describe Machinist::Blueprint do
|
21
|
+
describe 'explicit inheritance' do
|
22
|
+
it 'inherits attributes from the parent blueprint' do
|
23
|
+
parent_blueprint = described_class.new(OpenStruct) do
|
24
|
+
name { 'Fred' }
|
25
|
+
age { 97 }
|
26
|
+
end
|
27
|
+
|
28
|
+
child_blueprint = described_class.new(OpenStruct, parent: parent_blueprint) do
|
29
|
+
name { 'Bill' }
|
30
|
+
end
|
31
|
+
|
32
|
+
child = child_blueprint.make
|
33
|
+
expect(child.name).to eq('Bill')
|
34
|
+
expect(child.age).to eq(97)
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'takes the serial number from the parent' do
|
38
|
+
parent_blueprint = described_class.new(OpenStruct) do
|
39
|
+
parent_serial { sn }
|
40
|
+
end
|
41
|
+
|
42
|
+
child_blueprint = described_class.new(OpenStruct, parent: parent_blueprint) do
|
43
|
+
child_serial { sn }
|
44
|
+
end
|
45
|
+
|
46
|
+
expect(parent_blueprint.make.parent_serial).to eq('0001')
|
47
|
+
expect(child_blueprint.make.child_serial).to eq('0002')
|
48
|
+
expect(parent_blueprint.make.parent_serial).to eq('0003')
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe 'class inheritance' do
|
53
|
+
before do
|
54
|
+
[InheritanceSpecs::Grandpa, InheritanceSpecs::Dad, InheritanceSpecs::Son].each(&:clear_blueprints!)
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'inherits blueprinted attributes from the parent class' do
|
58
|
+
InheritanceSpecs::Dad.blueprint do
|
59
|
+
name { 'Fred' }
|
60
|
+
end
|
61
|
+
InheritanceSpecs::Son.blueprint {}
|
62
|
+
expect(InheritanceSpecs::Son.make.name).to eq('Fred')
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'overrides blueprinted attributes in the child class' do
|
66
|
+
InheritanceSpecs::Dad.blueprint do
|
67
|
+
name { 'Fred' }
|
68
|
+
end
|
69
|
+
InheritanceSpecs::Son.blueprint do
|
70
|
+
name { 'George' }
|
71
|
+
end
|
72
|
+
expect(InheritanceSpecs::Dad.make.name).to eq('Fred')
|
73
|
+
expect(InheritanceSpecs::Son.make.name).to eq('George')
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'inherits from blueprinted attributes in ancestor class' do
|
77
|
+
InheritanceSpecs::Grandpa.blueprint do
|
78
|
+
name { 'Fred' }
|
79
|
+
end
|
80
|
+
InheritanceSpecs::Son.blueprint {}
|
81
|
+
expect(InheritanceSpecs::Grandpa.make.name).to eq('Fred')
|
82
|
+
expect { InheritanceSpecs::Dad.make }.to raise_error(RuntimeError)
|
83
|
+
expect(InheritanceSpecs::Son.make.name).to eq('Fred')
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'follows inheritance for named blueprints correctly' do
|
87
|
+
InheritanceSpecs::Dad.blueprint do
|
88
|
+
name { 'John' }
|
89
|
+
age { 56 }
|
90
|
+
end
|
91
|
+
InheritanceSpecs::Dad.blueprint(:special) do
|
92
|
+
name { 'Paul' }
|
93
|
+
end
|
94
|
+
InheritanceSpecs::Son.blueprint(:special) do
|
95
|
+
age { 37 }
|
96
|
+
end
|
97
|
+
expect(InheritanceSpecs::Son.make(:special).name).to eq('John')
|
98
|
+
expect(InheritanceSpecs::Son.make(:special).age).to eq(37)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
|
3
|
+
RSpec.describe Machinist::Blueprint do
|
4
|
+
it 'makes an object of the given class' do
|
5
|
+
blueprint = described_class.new(OpenStruct) {}
|
6
|
+
expect(blueprint.make).to be_an(OpenStruct)
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'constructs an attribute from the blueprint' do
|
10
|
+
blueprint = described_class.new(OpenStruct) do
|
11
|
+
name { 'Fred' }
|
12
|
+
end
|
13
|
+
expect(blueprint.make.name).to eq('Fred')
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'constructs an array for an attribute in the blueprint' do
|
17
|
+
blueprint = described_class.new(OpenStruct) do
|
18
|
+
things(3) { Object.new }
|
19
|
+
end
|
20
|
+
things = blueprint.make.things
|
21
|
+
expect(things).to be_an(Array)
|
22
|
+
expect(things.size).to eq(3)
|
23
|
+
things.each { |thing| expect(thing).to be_an(Object) }
|
24
|
+
expect(things.uniq).to eq(things)
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'allows passing in attributes to override the blueprint' do
|
28
|
+
block_called = false
|
29
|
+
blueprint = described_class.new(OpenStruct) do
|
30
|
+
name do
|
31
|
+
block_called = true
|
32
|
+
'Fred'
|
33
|
+
end
|
34
|
+
end
|
35
|
+
expect(blueprint.make(name: 'Bill').name).to eq('Bill')
|
36
|
+
expect(block_called).to be_falsey
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'provides a serial number within the blueprint' do
|
40
|
+
blueprint = described_class.new(OpenStruct) do
|
41
|
+
name { "Fred #{sn}" }
|
42
|
+
end
|
43
|
+
expect(blueprint.make.name).to eq('Fred 0001')
|
44
|
+
expect(blueprint.make.name).to eq('Fred 0002')
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'provides access to the object being constructed within the blueprint' do
|
48
|
+
blueprint = described_class.new(OpenStruct) do
|
49
|
+
title { 'Test' }
|
50
|
+
body { object.title }
|
51
|
+
end
|
52
|
+
expect(blueprint.make.body).to eq('Test')
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'allows attribute names to be strings' do
|
56
|
+
blueprint = described_class.new(OpenStruct) do
|
57
|
+
name { 'Fred' }
|
58
|
+
end
|
59
|
+
expect(blueprint.make('name' => 'Bill').name).to eq('Bill')
|
60
|
+
end
|
61
|
+
|
62
|
+
# These are normally a problem because of name clashes with the standard (but
|
63
|
+
# deprecated) Ruby methods. This test makes sure we work around this.
|
64
|
+
it 'works with type and id attributes' do
|
65
|
+
klass = Class.new do
|
66
|
+
attr_accessor :id, :type
|
67
|
+
end
|
68
|
+
blueprint = described_class.new(klass) do
|
69
|
+
id { 'custom id' }
|
70
|
+
type { 'custom type' }
|
71
|
+
end
|
72
|
+
object = blueprint.make
|
73
|
+
expect(object.id).to eq('custom id')
|
74
|
+
expect(object.type).to eq('custom type')
|
75
|
+
end
|
76
|
+
end
|