fabrication 2.21.0 → 3.0.0.beta.1.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.
- checksums.yaml +4 -4
- data/README.markdown +1 -4
- data/Rakefile +8 -10
- data/lib/fabricate.rb +10 -13
- data/lib/fabrication.rb +4 -9
- data/lib/fabrication/config.rb +23 -22
- data/lib/fabrication/cucumber/step_fabricator.rb +20 -13
- data/lib/fabrication/errors/duplicate_fabricator_error.rb +5 -3
- data/lib/fabrication/errors/infinite_recursion_error.rb +5 -3
- data/lib/fabrication/errors/misplaced_fabricate_error.rb +7 -3
- data/lib/fabrication/errors/unfabricatable_error.rb +5 -4
- data/lib/fabrication/errors/unknown_fabricator_error.rb +5 -5
- data/lib/fabrication/generator/active_record.rb +18 -15
- data/lib/fabrication/generator/base.rb +93 -81
- data/lib/fabrication/generator/sequel.rb +29 -27
- data/lib/fabrication/railtie.rb +1 -3
- data/lib/fabrication/schematic/attribute.rb +69 -62
- data/lib/fabrication/schematic/definition.rb +139 -134
- data/lib/fabrication/schematic/evaluator.rb +61 -54
- data/lib/fabrication/schematic/manager.rb +67 -59
- data/lib/fabrication/schematic/runner.rb +12 -9
- data/lib/fabrication/sequencer.rb +23 -22
- data/lib/fabrication/support.rb +57 -54
- data/lib/fabrication/syntax/make.rb +0 -1
- data/lib/fabrication/transform.rb +34 -36
- data/lib/fabrication/version.rb +1 -1
- data/lib/rails/generators/fabrication/cucumber_steps/cucumber_steps_generator.rb +2 -3
- data/lib/rails/generators/fabrication/cucumber_steps/templates/fabrication_steps.rb +10 -10
- data/lib/rails/generators/fabrication/model/model_generator.rb +9 -9
- data/lib/tasks/defined_fabricators.rake +11 -11
- metadata +10 -12
- data/lib/fabrication/generator/data_mapper.rb +0 -17
- data/lib/fabrication/generator/mongoid.rb +0 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3153c373659350c2969d98f3d21cbc60c92f9aff1f00c51f32c7238357c49195
|
4
|
+
data.tar.gz: d69204cacb17bfab516ecbe93d2e05edb60c596052130a1b41340e699dc25412
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 99e08637411f94b9df1ff63572c85b9b5fc8016677d043f53b1fb2acf27495b8f1cd1162b63cc6ed6be7579facf5e6dcc9c0929d2374fb6e7b30570308e33184
|
7
|
+
data.tar.gz: abffe3aeb00cb0b29589ad12daa9710801bdaecf5898d46b40e7cefa5150a0d00464df300c9edc54e22092097cdd0c712af0af5ae6b9f11f0ccd9965ce9b7582
|
data/README.markdown
CHANGED
@@ -6,10 +6,7 @@ Fabrication is an object generation framework for Ruby.
|
|
6
6
|
|
7
7
|
## Compatibility
|
8
8
|
|
9
|
-
Fabrication is tested against
|
10
|
-
|
11
|
-
[](http://travis-ci.org/paulelliott/fabrication)
|
12
|
-
[](https://codeclimate.com/github/paulelliott/fabrication)
|
9
|
+
Fabrication is tested against all officially supported versions of Ruby.
|
13
10
|
|
14
11
|
## Documentation
|
15
12
|
|
data/Rakefile
CHANGED
@@ -1,20 +1,18 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler/setup'
|
3
3
|
|
4
4
|
Bundler.require
|
5
5
|
|
6
|
-
require
|
6
|
+
require 'rspec/core/rake_task'
|
7
7
|
RSpec::Core::RakeTask.new(:spec) do |spec|
|
8
|
-
spec.pattern =
|
8
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
9
9
|
end
|
10
10
|
|
11
11
|
desc 'All cucumber features with kitchen sink appraisal'
|
12
12
|
task :cucumber do
|
13
|
-
system('appraisal kitchen-sink cucumber -f progress')
|
13
|
+
system('appraisal kitchen-sink cucumber -f progress --publish-quiet')
|
14
14
|
end
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
task default: :spec
|
20
|
-
end
|
16
|
+
default_task = ENV['APPRAISAL_INITIALIZED'] ? :spec : %i[cucumber appraisal]
|
17
|
+
|
18
|
+
task default: default_task
|
data/lib/fabricate.rb
CHANGED
@@ -1,51 +1,48 @@
|
|
1
1
|
class Fabricate
|
2
|
-
def self.times(count, name, overrides={}, &block)
|
2
|
+
def self.times(count, name, overrides = {}, &block)
|
3
3
|
count.times.map { Fabricate(name, overrides, &block) }
|
4
4
|
end
|
5
5
|
|
6
|
-
def self.build_times(count, name, overrides={}, &block)
|
6
|
+
def self.build_times(count, name, overrides = {}, &block)
|
7
7
|
count.times.map { Fabricate.build(name, overrides, &block) }
|
8
8
|
end
|
9
9
|
|
10
|
-
def self.attributes_for_times(count, name, overrides={}, &block)
|
10
|
+
def self.attributes_for_times(count, name, overrides = {}, &block)
|
11
11
|
count.times.map { Fabricate.attributes_for(name, overrides, &block) }
|
12
12
|
end
|
13
13
|
|
14
|
-
def self.attributes_for(name, overrides={}, &block)
|
14
|
+
def self.attributes_for(name, overrides = {}, &block)
|
15
15
|
fail_if_initializing(name)
|
16
16
|
schematic(name).to_attributes(overrides, &block)
|
17
17
|
end
|
18
18
|
|
19
|
-
def self.to_params(name, overrides={}, &block)
|
19
|
+
def self.to_params(name, overrides = {}, &block)
|
20
20
|
fail_if_initializing(name)
|
21
21
|
schematic(name).to_params(overrides, &block)
|
22
22
|
end
|
23
23
|
|
24
|
-
def self.build(name, overrides={}, &block)
|
24
|
+
def self.build(name, overrides = {}, &block)
|
25
25
|
fail_if_initializing(name)
|
26
26
|
schematic(name).build(overrides, &block).tap do |object|
|
27
27
|
Fabrication::Cucumber::Fabrications[name] = object if Fabrication::Config.register_with_steps?
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
|
-
def self.create(name, overrides={}, &block)
|
31
|
+
def self.create(name, overrides = {}, &block)
|
32
32
|
fail_if_initializing(name)
|
33
33
|
schematic(name).fabricate(overrides, &block)
|
34
34
|
end
|
35
35
|
|
36
|
-
def self.sequence(name=Fabrication::Sequencer::DEFAULT, start=nil, &block)
|
36
|
+
def self.sequence(name = Fabrication::Sequencer::DEFAULT, start = nil, &block)
|
37
37
|
Fabrication::Sequencer.sequence(name, start, &block)
|
38
38
|
end
|
39
39
|
|
40
40
|
def self.schematic(name)
|
41
41
|
Fabrication.manager.load_definitions if Fabrication.manager.empty?
|
42
|
-
Fabrication.manager[name] || raise(Fabrication::UnknownFabricatorError
|
42
|
+
Fabrication.manager[name] || raise(Fabrication::UnknownFabricatorError, name)
|
43
43
|
end
|
44
44
|
|
45
|
-
private
|
46
|
-
|
47
45
|
def self.fail_if_initializing(name)
|
48
|
-
raise Fabrication::MisplacedFabricateError
|
46
|
+
raise Fabrication::MisplacedFabricateError, name if Fabrication.manager.initializing?
|
49
47
|
end
|
50
|
-
|
51
48
|
end
|
data/lib/fabrication.rb
CHANGED
@@ -32,8 +32,6 @@ module Fabrication
|
|
32
32
|
module Generator
|
33
33
|
autoload :ActiveRecord, 'fabrication/generator/active_record'
|
34
34
|
autoload :ActiveRecord4, 'fabrication/generator/active_record_4'
|
35
|
-
autoload :DataMapper, 'fabrication/generator/data_mapper'
|
36
|
-
autoload :Mongoid, 'fabrication/generator/mongoid'
|
37
35
|
autoload :Sequel, 'fabrication/generator/sequel'
|
38
36
|
autoload :Base, 'fabrication/generator/base'
|
39
37
|
end
|
@@ -50,22 +48,19 @@ module Fabrication
|
|
50
48
|
def self.manager
|
51
49
|
@manager ||= Fabrication::Schematic::Manager.instance
|
52
50
|
end
|
53
|
-
|
54
|
-
def self.schematics
|
55
|
-
puts "DEPRECATION WARNING: Fabrication.schematics has been replaced by Fabrication.manager and will be removed in 3.0.0."
|
56
|
-
manager
|
57
|
-
end
|
58
51
|
end
|
59
52
|
|
60
|
-
|
53
|
+
# rubocop:disable Naming/MethodName
|
54
|
+
def Fabricator(name, options = {}, &block)
|
61
55
|
Fabrication.manager.register(name, options, &block)
|
62
56
|
end
|
63
57
|
|
64
|
-
def Fabricate(name, overrides={}, &block)
|
58
|
+
def Fabricate(name, overrides = {}, &block)
|
65
59
|
Fabricate.create(name, overrides, &block).tap do |object|
|
66
60
|
Fabrication::Cucumber::Fabrications[name] = object if Fabrication::Config.register_with_steps?
|
67
61
|
end
|
68
62
|
end
|
63
|
+
# rubocop:enable Naming/MethodName
|
69
64
|
|
70
65
|
module FabricationMethods
|
71
66
|
def fabrications
|
data/lib/fabrication/config.rb
CHANGED
@@ -2,14 +2,16 @@ module Fabrication
|
|
2
2
|
module Config
|
3
3
|
extend self
|
4
4
|
|
5
|
-
def configure
|
5
|
+
def configure
|
6
|
+
yield self
|
7
|
+
end
|
6
8
|
|
7
9
|
def reset_defaults
|
8
10
|
@fabricator_path =
|
9
11
|
@path_prefix =
|
10
|
-
|
11
|
-
|
12
|
-
|
12
|
+
@sequence_start =
|
13
|
+
@generators =
|
14
|
+
nil
|
13
15
|
end
|
14
16
|
|
15
17
|
def fabricator_path
|
@@ -17,44 +19,43 @@ module Fabrication
|
|
17
19
|
end
|
18
20
|
alias fabricator_paths fabricator_path
|
19
21
|
|
20
|
-
def fabricator_dir
|
21
|
-
puts "DEPRECATION WARNING: Fabrication::Config.fabricator_dir has been replaced by Fabrication::Config.fabricator_path"
|
22
|
-
fabricator_path
|
23
|
-
end
|
24
|
-
|
25
22
|
def fabricator_path=(folders)
|
26
|
-
@fabricator_path = (
|
23
|
+
@fabricator_path = ([] << folders).flatten
|
27
24
|
end
|
28
25
|
|
29
|
-
|
30
|
-
puts "DEPRECATION WARNING: Fabrication::Config.fabricator_dir has been replaced by Fabrication::Config.fabricator_path"
|
31
|
-
self.fabricator_path = folders
|
32
|
-
end
|
26
|
+
attr_writer :sequence_start, :register_with_steps
|
33
27
|
|
34
|
-
|
35
|
-
|
28
|
+
def sequence_start
|
29
|
+
@sequence_start ||= 0
|
30
|
+
end
|
36
31
|
|
37
32
|
def path_prefix=(folders)
|
38
|
-
@path_prefix = (
|
33
|
+
@path_prefix = ([] << folders).flatten
|
39
34
|
end
|
40
35
|
|
41
36
|
def path_prefix
|
42
|
-
@path_prefix ||= [defined?(Rails) ? Rails.root :
|
37
|
+
@path_prefix ||= [defined?(Rails) ? Rails.root : '.']
|
43
38
|
end
|
44
39
|
alias path_prefixes path_prefix
|
45
40
|
|
46
|
-
attr_writer :register_with_steps
|
47
41
|
def register_with_steps?
|
48
42
|
@register_with_steps ||= nil
|
49
43
|
end
|
50
44
|
|
51
|
-
def generators
|
45
|
+
def generators
|
46
|
+
@generators ||= []
|
47
|
+
end
|
52
48
|
|
53
49
|
def generator_for(default_generators, klass)
|
54
50
|
(generators + default_generators).detect { |gen| gen.supports?(klass) }
|
55
51
|
end
|
56
52
|
|
57
|
-
def recursion_limit
|
58
|
-
|
53
|
+
def recursion_limit
|
54
|
+
@recursion_limit ||= 20
|
55
|
+
end
|
56
|
+
|
57
|
+
def recursion_limit=(limit)
|
58
|
+
@recursion_limit = limit
|
59
|
+
end
|
59
60
|
end
|
60
61
|
end
|
@@ -3,24 +3,27 @@ module Fabrication
|
|
3
3
|
class StepFabricator
|
4
4
|
attr_reader :model
|
5
5
|
|
6
|
-
def initialize(model_name, opts ={})
|
6
|
+
def initialize(model_name, opts = {})
|
7
7
|
@model = dehumanize(model_name)
|
8
8
|
@fabricator = Fabrication::Support.singularize(@model).to_sym
|
9
9
|
@parent_name = opts.delete(:parent)
|
10
10
|
end
|
11
11
|
|
12
|
-
def from_table(table, extra={})
|
12
|
+
def from_table(table, extra = {})
|
13
13
|
hashes = singular? ? [table.rows_hash] : table.hashes
|
14
|
-
hashes.map do |hash|
|
14
|
+
transformed_hashes = hashes.map do |hash|
|
15
15
|
transformed_hash = Fabrication::Transform.apply_to(@model, parameterize_hash(hash))
|
16
16
|
make(transformed_hash.merge(extra))
|
17
|
-
end
|
17
|
+
end
|
18
|
+
remember(transformed_hashes)
|
19
|
+
transformed_hashes
|
18
20
|
end
|
19
21
|
|
20
|
-
def n(count, attrs={})
|
21
|
-
count.times.map { make(attrs) }.tap {|o| remember(o) }
|
22
|
+
def n(count, attrs = {})
|
23
|
+
count.times.map { make(attrs) }.tap { |o| remember(o) }
|
22
24
|
end
|
23
25
|
|
26
|
+
# rubocop:disable Naming/PredicateName
|
24
27
|
def has_many(children)
|
25
28
|
instance = Fabrications[@fabricator]
|
26
29
|
children = dehumanize(children)
|
@@ -29,9 +32,11 @@ module Fabrication
|
|
29
32
|
child.respond_to?(:save!) && child.save!
|
30
33
|
end
|
31
34
|
end
|
35
|
+
# rubocop:enable Naming/PredicateName
|
32
36
|
|
33
37
|
def parent
|
34
38
|
return unless @parent_name
|
39
|
+
|
35
40
|
Fabrications[dehumanize(@parent_name)]
|
36
41
|
end
|
37
42
|
|
@@ -54,19 +59,20 @@ module Fabrication
|
|
54
59
|
end
|
55
60
|
|
56
61
|
def dehumanize(string)
|
57
|
-
string.gsub(/\W+/,'_').downcase
|
62
|
+
string.gsub(/\W+/, '_').downcase
|
58
63
|
end
|
59
64
|
|
60
65
|
def parameterize_hash(hash)
|
61
|
-
hash.inject({}) {|h,(k,v)| h.update(dehumanize(k).to_sym => v)}
|
66
|
+
hash.inject({}) { |h, (k, v)| h.update(dehumanize(k).to_sym => v) }
|
62
67
|
end
|
63
68
|
|
64
|
-
def make(attrs={})
|
69
|
+
def make(attrs = {})
|
65
70
|
Fabricate(@fabricator, attrs.merge(parentship))
|
66
71
|
end
|
67
72
|
|
68
73
|
def parentship
|
69
74
|
return {} unless parent
|
75
|
+
|
70
76
|
parent_class_name = parent.class.to_s.underscore
|
71
77
|
|
72
78
|
parent_instance = parent
|
@@ -77,18 +83,19 @@ module Fabrication
|
|
77
83
|
|
78
84
|
{ parent_class_name => parent_instance }
|
79
85
|
end
|
80
|
-
|
81
86
|
end
|
82
87
|
|
83
88
|
module Fabrications
|
84
|
-
|
89
|
+
def self.fabrications
|
90
|
+
@fabrications ||= {}
|
91
|
+
end
|
85
92
|
|
86
93
|
def self.[](fabricator)
|
87
|
-
|
94
|
+
fabrications[fabricator.to_sym]
|
88
95
|
end
|
89
96
|
|
90
97
|
def self.[]=(fabricator, fabrication)
|
91
|
-
|
98
|
+
fabrications[fabricator.to_sym] = fabrication
|
92
99
|
end
|
93
100
|
end
|
94
101
|
end
|
@@ -1,5 +1,7 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
module Fabrication
|
2
|
+
class DuplicateFabricatorError < StandardError
|
3
|
+
def initialize(string)
|
4
|
+
super("'#{string}' is already defined")
|
5
|
+
end
|
4
6
|
end
|
5
7
|
end
|
@@ -1,5 +1,7 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
module Fabrication
|
2
|
+
class InfiniteRecursionError < StandardError
|
3
|
+
def initialize(name)
|
4
|
+
super("You appear to have infinite recursion with the `#{name}` fabricator")
|
5
|
+
end
|
4
6
|
end
|
5
7
|
end
|
@@ -1,5 +1,9 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
module Fabrication
|
2
|
+
class MisplacedFabricateError < StandardError
|
3
|
+
def initialize(name)
|
4
|
+
super("You tried to fabricate `#{name}` while Fabricators were still loading. " \
|
5
|
+
"Check your fabricator files and make sure you didn't accidentally type " \
|
6
|
+
'`Fabricate` instead of `Fabricator` in there somewhere.')
|
7
|
+
end
|
4
8
|
end
|
5
9
|
end
|
@@ -1,6 +1,7 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
module Fabrication
|
2
|
+
class UnfabricatableError < StandardError
|
3
|
+
def initialize(name, original_error)
|
4
|
+
super("No class found for '#{name}' (original exception: #{original_error.message})")
|
5
|
+
end
|
5
6
|
end
|
6
7
|
end
|
@@ -1,7 +1,7 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
module Fabrication
|
2
|
+
class UnknownFabricatorError < StandardError
|
3
|
+
def initialize(name)
|
4
|
+
super("No Fabricator defined for '#{name}'")
|
5
|
+
end
|
5
6
|
end
|
6
|
-
|
7
7
|
end
|
@@ -1,19 +1,22 @@
|
|
1
|
-
|
1
|
+
module Fabrication
|
2
|
+
module Generator
|
3
|
+
class ActiveRecord < Fabrication::Generator::Base
|
4
|
+
def self.supports?(klass)
|
5
|
+
# Some gems will declare an ActiveRecord module for their own purposes
|
6
|
+
# so we can't assume because we have the ActiveRecord module that we also
|
7
|
+
# have ActiveRecord::Base. Because defined? can return nil we ensure that nil
|
8
|
+
# becomes false.
|
9
|
+
defined?(::ActiveRecord) && defined?(::ActiveRecord::Base) &&
|
10
|
+
klass.ancestors.include?(::ActiveRecord::Base) || false
|
11
|
+
end
|
2
12
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
def build_instance
|
12
|
-
if _klass.respond_to?(:protected_attributes)
|
13
|
-
self._instance = _klass.new(_attributes, without_protection: true)
|
14
|
-
else
|
15
|
-
self._instance = _klass.new(_attributes)
|
13
|
+
def build_instance
|
14
|
+
self._instance = if _klass.respond_to?(:protected_attributes)
|
15
|
+
_klass.new(_attributes, without_protection: true)
|
16
|
+
else
|
17
|
+
_klass.new(_attributes)
|
18
|
+
end
|
19
|
+
end
|
16
20
|
end
|
17
21
|
end
|
18
|
-
|
19
22
|
end
|
@@ -1,103 +1,115 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
module Fabrication
|
2
|
+
module Generator
|
3
|
+
class Base
|
4
|
+
def self.supports?(_klass)
|
5
|
+
true
|
6
|
+
end
|
4
7
|
|
5
|
-
|
6
|
-
|
8
|
+
def build(attributes = [], callbacks = {})
|
9
|
+
process_attributes(attributes)
|
7
10
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
11
|
+
if callbacks[:initialize_with]
|
12
|
+
build_instance_with_constructor_override(callbacks[:initialize_with])
|
13
|
+
elsif callbacks[:on_init]
|
14
|
+
build_instance_with_init_callback(callbacks[:on_init])
|
15
|
+
else
|
16
|
+
build_instance
|
17
|
+
end
|
18
|
+
execute_callbacks(callbacks[:after_build])
|
19
|
+
_instance
|
20
|
+
end
|
18
21
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
22
|
+
def create(attributes = [], callbacks = [])
|
23
|
+
build(attributes, callbacks)
|
24
|
+
execute_callbacks(callbacks[:before_validation])
|
25
|
+
execute_callbacks(callbacks[:after_validation])
|
26
|
+
execute_callbacks(callbacks[:before_save])
|
27
|
+
execute_callbacks(callbacks[:before_create])
|
28
|
+
persist
|
29
|
+
execute_callbacks(callbacks[:after_create])
|
30
|
+
execute_callbacks(callbacks[:after_save])
|
31
|
+
_instance
|
32
|
+
end
|
30
33
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
+
def execute_callbacks(callbacks)
|
35
|
+
callbacks&.each { |callback| _instance.instance_exec(_instance, _transient_attributes, &callback) }
|
36
|
+
end
|
34
37
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
38
|
+
def to_params(attributes = [])
|
39
|
+
process_attributes(attributes)
|
40
|
+
_attributes.respond_to?(:with_indifferent_access) ? _attributes.with_indifferent_access : _attributes
|
41
|
+
end
|
39
42
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
43
|
+
def to_hash(attributes = [], _callbacks = [])
|
44
|
+
process_attributes(attributes)
|
45
|
+
Fabrication::Support.hash_class.new.tap do |hash|
|
46
|
+
_attributes.map do |name, value|
|
47
|
+
if value.respond_to?(:id)
|
48
|
+
hash["#{name}_id"] = value.id
|
49
|
+
else
|
50
|
+
hash[name] = value
|
51
|
+
end
|
52
|
+
end
|
48
53
|
end
|
49
54
|
end
|
50
|
-
end
|
51
|
-
end
|
52
55
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
56
|
+
def build_instance_with_constructor_override(callback)
|
57
|
+
self._instance = instance_eval(&callback)
|
58
|
+
set_attributes
|
59
|
+
end
|
57
60
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
61
|
+
def build_instance_with_init_callback(callback)
|
62
|
+
self._instance = _klass.new(*callback.call)
|
63
|
+
set_attributes
|
64
|
+
end
|
62
65
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
66
|
+
def build_instance
|
67
|
+
self._instance = _klass.new
|
68
|
+
set_attributes
|
69
|
+
end
|
67
70
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
71
|
+
def set_attributes
|
72
|
+
if _instance.respond_to?(:attributes=)
|
73
|
+
_instance.attributes = _attributes
|
74
|
+
else
|
75
|
+
_attributes.each do |k, v|
|
76
|
+
_instance.send("#{k}=", v)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
73
80
|
|
74
|
-
|
75
|
-
|
76
|
-
|
81
|
+
def initialize(klass)
|
82
|
+
self._klass = klass
|
83
|
+
end
|
77
84
|
|
78
|
-
|
79
|
-
|
80
|
-
|
85
|
+
def respond_to_missing?(method_name, _include_private = false)
|
86
|
+
_attributes.key?(method_name)
|
87
|
+
end
|
81
88
|
|
82
|
-
|
89
|
+
def method_missing(method_name, *args, &block)
|
90
|
+
_attributes.fetch(method_name) { super }
|
91
|
+
end
|
83
92
|
|
84
|
-
|
93
|
+
protected
|
85
94
|
|
86
|
-
|
87
|
-
@_attributes ||= {}
|
88
|
-
end
|
95
|
+
attr_accessor :_klass, :_instance, :_transient_attributes
|
89
96
|
|
90
|
-
|
91
|
-
|
92
|
-
|
97
|
+
def _attributes
|
98
|
+
@_attributes ||= {}
|
99
|
+
end
|
93
100
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
101
|
+
def persist
|
102
|
+
_instance.save! if _instance.respond_to?(:save!)
|
103
|
+
end
|
104
|
+
|
105
|
+
def process_attributes(attributes)
|
106
|
+
self._transient_attributes = ({})
|
107
|
+
attributes.each do |attribute|
|
108
|
+
_attributes[attribute.name] = attribute.processed_value(_attributes)
|
109
|
+
_transient_attributes[attribute.name] = _attributes[attribute.name] if attribute.transient?
|
110
|
+
end
|
111
|
+
_attributes.reject! { |k| _transient_attributes.keys.include?(k) }
|
112
|
+
end
|
99
113
|
end
|
100
|
-
_attributes.reject! { |k| _transient_attributes.keys.include?(k) }
|
101
114
|
end
|
102
|
-
|
103
115
|
end
|