fixjour 0.0.6 → 0.0.7
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.
- data/lib/fixjour/builders.rb +10 -50
- data/lib/fixjour/definitions.rb +36 -0
- data/lib/fixjour/errors.rb +5 -1
- data/lib/fixjour/generator.rb +27 -0
- data/lib/fixjour/overrides_hash.rb +2 -2
- data/lib/fixjour/redundant_check.rb +4 -0
- data/lib/fixjour/verify.rb +24 -4
- data/lib/fixjour.rb +3 -0
- metadata +6 -4
data/lib/fixjour/builders.rb
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
module Fixjour
|
|
2
2
|
class << self
|
|
3
|
+
include Definitions
|
|
4
|
+
|
|
3
5
|
attr_accessor :allow_redundancy
|
|
4
|
-
|
|
6
|
+
|
|
5
7
|
# The list of classes that have builders defined.
|
|
6
8
|
def builders
|
|
7
9
|
@builders ||= Set.new
|
|
@@ -19,19 +21,19 @@ module Fixjour
|
|
|
19
21
|
klass.new(options.merge(overrides))
|
|
20
22
|
end
|
|
21
23
|
end
|
|
22
|
-
|
|
24
|
+
|
|
23
25
|
name = name_for(klass)
|
|
24
|
-
|
|
26
|
+
|
|
25
27
|
define_create(name)
|
|
26
28
|
define_valid_attributes(name)
|
|
27
29
|
end
|
|
28
|
-
|
|
30
|
+
|
|
29
31
|
# Adds builders to Fixjour.
|
|
30
32
|
def evaluate(&block)
|
|
31
33
|
begin
|
|
32
34
|
module_eval(&block)
|
|
33
35
|
rescue NameError => e
|
|
34
|
-
if evaluator.respond_to?(e.name)
|
|
36
|
+
if e.name && evaluator.respond_to?(e.name)
|
|
35
37
|
raise NonBlockBuilderReference.new("You must use a builder block in order to reference other Fixjour creation methods.")
|
|
36
38
|
else
|
|
37
39
|
raise e
|
|
@@ -46,9 +48,9 @@ module Fixjour
|
|
|
46
48
|
when String, Symbol then builders.map(&:name).include?(builder)
|
|
47
49
|
end
|
|
48
50
|
end
|
|
49
|
-
|
|
51
|
+
|
|
50
52
|
private
|
|
51
|
-
|
|
53
|
+
|
|
52
54
|
# Registers a class' builder. This allows us to make sure
|
|
53
55
|
# redundant builders aren't defined, which can lead to confusion
|
|
54
56
|
# when trying to figure out where objects are being created.
|
|
@@ -57,53 +59,11 @@ module Fixjour
|
|
|
57
59
|
raise RedundantBuilder.new("You already defined a builder for #{klass.inspect}")
|
|
58
60
|
end
|
|
59
61
|
end
|
|
60
|
-
|
|
62
|
+
|
|
61
63
|
def name_for(klass)
|
|
62
64
|
klass.name.underscore
|
|
63
65
|
end
|
|
64
|
-
|
|
65
|
-
# Defines the new_* method
|
|
66
|
-
def define_new(klass, &block)
|
|
67
|
-
name = name_for(klass)
|
|
68
|
-
define_method("new_#{name}") do |*args|
|
|
69
|
-
overrides = OverridesHash.new(args.first || { })
|
|
70
|
-
|
|
71
|
-
args = case block.arity
|
|
72
|
-
when 1 then [overrides]
|
|
73
|
-
when 2 then [MergingProxy.new(klass, overrides), overrides]
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
result = block.bind(self).call(*args)
|
|
77
|
-
result
|
|
78
|
-
end
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
# Defines the create_* method
|
|
82
|
-
def define_create(name)
|
|
83
|
-
define_method("create_#{name}") do |*args|
|
|
84
|
-
model = send("new_#{name}", *args)
|
|
85
|
-
model.save!
|
|
86
|
-
model
|
|
87
|
-
end
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
# Defines the valid_*_attributes method
|
|
91
|
-
def define_valid_attributes(name)
|
|
92
|
-
define_method("valid_#{name}_attributes") do |*args|
|
|
93
|
-
if instance_variable_get("@__valid_#{name}_attrs").nil?
|
|
94
|
-
valid_attributes = send("new_#{name}").attributes
|
|
95
|
-
valid_attributes.delete_if { |key, value| value.nil? }
|
|
96
|
-
instance_variable_set("@__valid_#{name}_attrs", valid_attributes)
|
|
97
|
-
end
|
|
98
66
|
|
|
99
|
-
overrides = args.extract_options!
|
|
100
|
-
attrs = instance_variable_get("@__valid_#{name}_attrs").merge(overrides)
|
|
101
|
-
attrs.stringify_keys!
|
|
102
|
-
attrs.make_indifferent!
|
|
103
|
-
attrs
|
|
104
|
-
end
|
|
105
|
-
end
|
|
106
|
-
|
|
107
67
|
# Anonymous class used for reflecting on current Fixjour state.
|
|
108
68
|
def evaluator
|
|
109
69
|
@evaluator ||= begin
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
module Fixjour
|
|
2
|
+
module Definitions
|
|
3
|
+
# Defines the new_* method
|
|
4
|
+
def define_new(klass, &block)
|
|
5
|
+
define_method("new_#{name_for(klass)}") do |*args|
|
|
6
|
+
Generator.new(klass, block).call(self, args.extract_options!)
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
# Defines the create_* method
|
|
11
|
+
def define_create(name)
|
|
12
|
+
define_method("create_#{name}") do |*args|
|
|
13
|
+
model = send("new_#{name}", *args)
|
|
14
|
+
model.save!
|
|
15
|
+
model
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Defines the valid_*_attributes method
|
|
20
|
+
def define_valid_attributes(name)
|
|
21
|
+
define_method("valid_#{name}_attributes") do |*args|
|
|
22
|
+
if instance_variable_get("@__valid_#{name}_attrs").nil?
|
|
23
|
+
valid_attributes = send("new_#{name}").attributes
|
|
24
|
+
valid_attributes.delete_if { |key, value| value.nil? }
|
|
25
|
+
instance_variable_set("@__valid_#{name}_attrs", valid_attributes)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
overrides = args.extract_options!
|
|
29
|
+
attrs = instance_variable_get("@__valid_#{name}_attrs").merge(overrides)
|
|
30
|
+
attrs.stringify_keys!
|
|
31
|
+
attrs.make_indifferent!
|
|
32
|
+
attrs
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
data/lib/fixjour/errors.rb
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
module Fixjour
|
|
2
|
-
# Raised when a builder returns an invalid object
|
|
2
|
+
# Raised when a builder returns an invalid object.
|
|
3
3
|
class InvalidBuilder < StandardError; end
|
|
4
4
|
|
|
5
|
+
# Raised when a builder will return an invalid object
|
|
6
|
+
# due to a validates_uniqueness_of validation.
|
|
7
|
+
class DangerousBuilder < StandardError; end
|
|
8
|
+
|
|
5
9
|
# Raised when a builder returns an object of the wrong type
|
|
6
10
|
class WrongBuilderType < StandardError; end
|
|
7
11
|
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
module Fixjour
|
|
2
|
+
# This generates a new instance of a model object for
|
|
3
|
+
# the new_[model] method.
|
|
4
|
+
class Generator
|
|
5
|
+
attr_reader :klass, :block
|
|
6
|
+
|
|
7
|
+
def initialize(klass, block)
|
|
8
|
+
@klass, @block = klass, block
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def call(context, overrides={})
|
|
12
|
+
overrides = OverridesHash.new(overrides)
|
|
13
|
+
result = block.bind(context).call(*args(overrides))
|
|
14
|
+
case result
|
|
15
|
+
when Hash then klass.new(result.merge(overrides))
|
|
16
|
+
else result
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def args(overrides)
|
|
21
|
+
case block.arity
|
|
22
|
+
when 1 then [overrides]
|
|
23
|
+
when 2 then [MergingProxy.new(klass, overrides), overrides]
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -12,8 +12,8 @@ module Fixjour
|
|
|
12
12
|
# Allows for processing of the overrides hash. Deletes
|
|
13
13
|
# the option when it's present, then yields the value.
|
|
14
14
|
def process(option)
|
|
15
|
-
|
|
16
|
-
yield value if block_given?
|
|
15
|
+
delete(option).tap do |value|
|
|
16
|
+
yield value if value and block_given?
|
|
17
17
|
end
|
|
18
18
|
end
|
|
19
19
|
end
|
|
@@ -3,6 +3,10 @@ module Fixjour
|
|
|
3
3
|
klass.extend(RedundancyChecker)
|
|
4
4
|
end
|
|
5
5
|
|
|
6
|
+
# Uses method_added hook to make sure no redundant builder methods
|
|
7
|
+
# get defined after a builder has already created them. For example,
|
|
8
|
+
# if you have a Comment builder, this hook will ensure that any attempt
|
|
9
|
+
# to define a #new_comment method will raise an exception.
|
|
6
10
|
module RedundancyChecker
|
|
7
11
|
BUILDER_METHOD_PATTERN = /^(new|create|valid)_(\w+)(_attributes)?$/
|
|
8
12
|
|
data/lib/fixjour/verify.rb
CHANGED
|
@@ -7,20 +7,40 @@ module Fixjour
|
|
|
7
7
|
# * The creation methods return objects of the proper type
|
|
8
8
|
def verify!
|
|
9
9
|
builders.each do |klass|
|
|
10
|
-
result =
|
|
10
|
+
result = new_record(klass)
|
|
11
11
|
|
|
12
12
|
unless result.valid?
|
|
13
|
-
|
|
13
|
+
error(klass, InvalidBuilder, "returns an invalid object: #{result.errors.inspect}")
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
unless result.new_record?
|
|
17
|
-
|
|
17
|
+
error(klass, BuilderSavedRecord, "must return a new record")
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
unless result.is_a?(klass)
|
|
21
|
-
|
|
21
|
+
error(klass, WrongBuilderType, "must return an instance of #{klass}")
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
result.save!
|
|
25
|
+
|
|
26
|
+
unless new_record(klass).valid?
|
|
27
|
+
msg = ""
|
|
28
|
+
msg << "returns invalid an invalid object after another object has been saved.\n"
|
|
29
|
+
msg << "This could be caused by a validates_uniqueness_of validation in your model.\n"
|
|
30
|
+
msg << "Use something like the faker gem to alleviate this issue."
|
|
31
|
+
error(klass, DangerousBuilder, msg)
|
|
22
32
|
end
|
|
23
33
|
end
|
|
24
34
|
end
|
|
35
|
+
|
|
36
|
+
private
|
|
37
|
+
|
|
38
|
+
def error(klass, exception, msg)
|
|
39
|
+
raise exception.new("The builder for #{klass} #{msg} ")
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def new_record(klass)
|
|
43
|
+
evaluator.send("new_#{name_for(klass)}")
|
|
44
|
+
end
|
|
25
45
|
end
|
|
26
46
|
end
|
data/lib/fixjour.rb
CHANGED
|
@@ -3,11 +3,14 @@ $LOAD_PATH << File.dirname(__FILE__)
|
|
|
3
3
|
require 'rubygems'
|
|
4
4
|
require 'activerecord'
|
|
5
5
|
require 'core_ext/hash'
|
|
6
|
+
require 'core_ext/object'
|
|
6
7
|
require 'fixjour/merging_proxy'
|
|
7
8
|
require 'fixjour/redundant_check'
|
|
8
9
|
require 'fixjour/overrides_hash'
|
|
9
10
|
require 'fixjour/verify'
|
|
10
11
|
require 'fixjour/errors'
|
|
12
|
+
require 'fixjour/generator'
|
|
13
|
+
require 'fixjour/definitions'
|
|
11
14
|
require 'fixjour/builders'
|
|
12
15
|
|
|
13
16
|
# This method is just for prettiness
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: fixjour
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.7
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Pat Nakajima
|
|
@@ -35,11 +35,13 @@ files:
|
|
|
35
35
|
- lib/core_ext/hash.rb
|
|
36
36
|
- lib/fixjour
|
|
37
37
|
- lib/fixjour/builders.rb
|
|
38
|
-
- lib/fixjour/
|
|
38
|
+
- lib/fixjour/definitions.rb
|
|
39
39
|
- lib/fixjour/errors.rb
|
|
40
|
-
- lib/fixjour/
|
|
41
|
-
- lib/fixjour/
|
|
40
|
+
- lib/fixjour/generator.rb
|
|
41
|
+
- lib/fixjour/merging_proxy.rb
|
|
42
42
|
- lib/fixjour/overrides_hash.rb
|
|
43
|
+
- lib/fixjour/redundant_check.rb
|
|
44
|
+
- lib/fixjour/verify.rb
|
|
43
45
|
- lib/fixjour.rb
|
|
44
46
|
has_rdoc: true
|
|
45
47
|
homepage: http://github.com/nakajima/fixjour
|