nakajima-fixjour 0.1.5 → 0.1.6
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/fixjour/builder.rb +21 -0
- data/lib/fixjour/builders.rb +20 -13
- data/lib/fixjour/counter.rb +20 -10
- data/lib/fixjour/definitions.rb +9 -9
- data/lib/fixjour/redundant_check.rb +5 -6
- data/lib/fixjour/verify.rb +8 -7
- data/lib/fixjour.rb +1 -0
- metadata +2 -1
@@ -0,0 +1,21 @@
|
|
1
|
+
module Fixjour
|
2
|
+
class Builder
|
3
|
+
attr_reader :klass
|
4
|
+
|
5
|
+
def initialize(klass, options={})
|
6
|
+
@klass, @options = klass, options
|
7
|
+
end
|
8
|
+
|
9
|
+
def name
|
10
|
+
@name ||= (@options[:as] || @klass.name.underscore).to_s
|
11
|
+
end
|
12
|
+
|
13
|
+
def eql?(other)
|
14
|
+
@klass == other.klass
|
15
|
+
end
|
16
|
+
|
17
|
+
def hash
|
18
|
+
@klass.hash
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/fixjour/builders.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
module Fixjour
|
2
|
-
|
2
|
+
def counter(key=nil)
|
3
|
+
Counter.counter(key)
|
4
|
+
end
|
5
|
+
|
3
6
|
class << self
|
4
7
|
include Definitions
|
5
8
|
|
@@ -13,20 +16,19 @@ module Fixjour
|
|
13
16
|
# This method should always return a valid instance of
|
14
17
|
# a model object.
|
15
18
|
def define_builder(klass, options={}, &block)
|
16
|
-
|
19
|
+
builder = Builder.new(klass, :as => options.delete(:as))
|
20
|
+
add_builder(builder)
|
17
21
|
|
18
22
|
if block_given?
|
19
|
-
define_new(
|
23
|
+
define_new(builder, &block)
|
20
24
|
else
|
21
|
-
define_new(
|
25
|
+
define_new(builder) do |proxy, overrides|
|
22
26
|
proxy.new(options.merge(overrides))
|
23
27
|
end
|
24
28
|
end
|
25
29
|
|
26
|
-
|
27
|
-
|
28
|
-
define_create(name)
|
29
|
-
define_valid_attributes(name)
|
30
|
+
define_create(builder)
|
31
|
+
define_valid_attributes(builder)
|
30
32
|
end
|
31
33
|
|
32
34
|
# Adds builders to Fixjour.
|
@@ -45,19 +47,24 @@ module Fixjour
|
|
45
47
|
# Checks to see whether or not a builder is defined. Duh.
|
46
48
|
def builder_defined?(builder)
|
47
49
|
case builder
|
48
|
-
when Class
|
49
|
-
when String
|
50
|
+
when Class then builders.map(&:klass).include?(builders)
|
51
|
+
when String then builders.map(&:name).include?(builder)
|
52
|
+
when Symbol then builders.map(&:name).include?(builder.to_s)
|
50
53
|
end
|
51
54
|
end
|
52
55
|
|
56
|
+
def remove(builder)
|
57
|
+
builders.delete(Builder.new(builder))
|
58
|
+
end
|
59
|
+
|
53
60
|
private
|
54
61
|
|
55
62
|
# Registers a class' builder. This allows us to make sure
|
56
63
|
# redundant builders aren't defined, which can lead to confusion
|
57
64
|
# when trying to figure out where objects are being created.
|
58
|
-
def add_builder(
|
59
|
-
unless builders.add?(
|
60
|
-
raise RedundantBuilder.new("You already defined a builder for #{klass.inspect}")
|
65
|
+
def add_builder(builder)
|
66
|
+
unless builders.add?(builder) or Fixjour.allow_redundancy
|
67
|
+
raise RedundantBuilder.new("You already defined a builder for #{builder.klass.inspect}")
|
61
68
|
end
|
62
69
|
end
|
63
70
|
|
data/lib/fixjour/counter.rb
CHANGED
@@ -1,20 +1,30 @@
|
|
1
1
|
module Fixjour
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
2
|
+
class Counter
|
3
|
+
class << self
|
4
|
+
def reset(key=nil)
|
5
|
+
key ? counters.delete(key) : counters.clear
|
6
|
+
end
|
7
|
+
|
8
|
+
def counter(key)
|
9
|
+
counters[key] ||= new
|
10
|
+
counters[key].next
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def counters
|
16
|
+
@counters ||= {}
|
8
17
|
end
|
9
18
|
end
|
19
|
+
|
10
20
|
reset
|
11
21
|
|
12
|
-
def
|
13
|
-
@
|
22
|
+
def initialize
|
23
|
+
@value = 0
|
14
24
|
end
|
15
25
|
|
16
|
-
def
|
17
|
-
|
26
|
+
def next
|
27
|
+
@value += 1
|
18
28
|
end
|
19
29
|
end
|
20
30
|
end
|
data/lib/fixjour/definitions.rb
CHANGED
@@ -1,25 +1,25 @@
|
|
1
1
|
module Fixjour
|
2
2
|
module Definitions
|
3
3
|
# Defines the new_* method
|
4
|
-
def define_new(
|
5
|
-
define_method("new_#{
|
6
|
-
Generator.new(klass, block).call(self, args.extract_options!.symbolize_keys!)
|
4
|
+
def define_new(builder, &block)
|
5
|
+
define_method("new_#{builder.name}") do |*args|
|
6
|
+
Generator.new(builder.klass, block).call(self, args.extract_options!.symbolize_keys!)
|
7
7
|
end
|
8
8
|
end
|
9
9
|
|
10
10
|
# Defines the create_* method
|
11
|
-
def define_create(
|
12
|
-
define_method("create_#{name}") do |*args|
|
13
|
-
model = send("new_#{name}", *args)
|
11
|
+
def define_create(builder)
|
12
|
+
define_method("create_#{builder.name}") do |*args|
|
13
|
+
model = send("new_#{builder.name}", *args)
|
14
14
|
model.save!
|
15
15
|
model
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
19
|
# Defines the valid_*_attributes method
|
20
|
-
def define_valid_attributes(
|
21
|
-
define_method("valid_#{name}_attributes") do |*args|
|
22
|
-
valid_attributes = send("new_#{name}", *args).attributes
|
20
|
+
def define_valid_attributes(builder)
|
21
|
+
define_method("valid_#{builder.name}_attributes") do |*args|
|
22
|
+
valid_attributes = send("new_#{builder.name}", *args).attributes
|
23
23
|
valid_attributes.delete_if { |key, value| value.nil? }
|
24
24
|
valid_attributes.stringify_keys!
|
25
25
|
valid_attributes.make_indifferent!
|
@@ -2,28 +2,27 @@ module Fixjour
|
|
2
2
|
def self.included(klass)
|
3
3
|
klass.extend(RedundancyChecker)
|
4
4
|
end
|
5
|
-
|
5
|
+
|
6
6
|
# Uses method_added hook to make sure no redundant builder methods
|
7
7
|
# get defined after a builder has already created them. For example,
|
8
8
|
# if you have a Comment builder, this hook will ensure that any attempt
|
9
9
|
# to define a #new_comment method will raise an exception.
|
10
10
|
module RedundancyChecker
|
11
11
|
BUILDER_METHOD_PATTERN = /^(new|create|valid)_(\w+)(_attributes)?$/
|
12
|
-
|
12
|
+
|
13
13
|
def method_added(sym)
|
14
14
|
name = sym.to_s
|
15
|
-
|
16
15
|
if klass_name = get_klass_name(name)
|
17
|
-
if Fixjour.builder_defined?(klass_name)
|
16
|
+
if Fixjour.builder_defined?(klass_name.underscore)
|
18
17
|
raise RedundantBuilder.new("You already defined a builder for #{inspect}")
|
19
18
|
end
|
20
19
|
end
|
21
20
|
end
|
22
|
-
|
21
|
+
|
23
22
|
def get_klass_name(name)
|
24
23
|
if match = name.match(BUILDER_METHOD_PATTERN)
|
25
24
|
match[2].classify.gsub(/Attribute$/, '')
|
26
25
|
end
|
27
26
|
end
|
28
27
|
end
|
29
|
-
end
|
28
|
+
end
|
data/lib/fixjour/verify.rb
CHANGED
@@ -6,8 +6,9 @@ module Fixjour
|
|
6
6
|
# * The new_* methods return new records
|
7
7
|
# * The creation methods return objects of the proper type
|
8
8
|
def verify!
|
9
|
-
builders.each do |
|
10
|
-
|
9
|
+
builders.each do |builder|
|
10
|
+
klass = builder.klass
|
11
|
+
result = new_record(builder)
|
11
12
|
|
12
13
|
unless result.valid?
|
13
14
|
error(klass, InvalidBuilder, "returns an invalid object: #{result.errors.inspect}")
|
@@ -27,22 +28,22 @@ module Fixjour
|
|
27
28
|
rescue => e
|
28
29
|
error(klass, UnsavableBuilder, "raises #{e.inspect} when saved to the database")
|
29
30
|
end
|
30
|
-
|
31
|
-
unless new_record(
|
31
|
+
|
32
|
+
unless new_record(builder).valid?
|
32
33
|
msg = ""
|
33
34
|
msg << "returns invalid an invalid object after another object has been saved.\n"
|
34
35
|
msg << "This could be caused by a validates_uniqueness_of validation in your model.\n"
|
35
36
|
msg << "Use something like the faker gem to alleviate this issue."
|
36
37
|
error(klass, DangerousBuilder, msg)
|
37
38
|
end
|
38
|
-
|
39
|
+
|
39
40
|
raise ActiveRecord::Rollback
|
40
41
|
end
|
41
42
|
end
|
42
43
|
end
|
43
44
|
|
44
45
|
def new_record(klass)
|
45
|
-
evaluator.send("new_#{
|
46
|
+
evaluator.send("new_#{klass.name}")
|
46
47
|
end
|
47
48
|
|
48
49
|
private
|
@@ -51,4 +52,4 @@ module Fixjour
|
|
51
52
|
raise exception.new("The builder for #{klass} #{msg} ")
|
52
53
|
end
|
53
54
|
end
|
54
|
-
end
|
55
|
+
end
|
data/lib/fixjour.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nakajima-fixjour
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Pat Nakajima
|
@@ -35,6 +35,7 @@ files:
|
|
35
35
|
- lib/core_ext/hash.rb
|
36
36
|
- lib/core_ext/object.rb
|
37
37
|
- lib/fixjour
|
38
|
+
- lib/fixjour/builder.rb
|
38
39
|
- lib/fixjour/builders.rb
|
39
40
|
- lib/fixjour/counter.rb
|
40
41
|
- lib/fixjour/definitions.rb
|