nakajima-fixjour 0.0.5 → 0.0.6
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 +45 -26
- data/lib/fixjour/errors.rb +6 -0
- data/lib/fixjour/merging_proxy.rb +21 -0
- data/lib/fixjour/overrides_hash.rb +5 -0
- data/lib/fixjour/redundant_check.rb +0 -11
- data/lib/fixjour.rb +3 -0
- metadata +2 -1
data/lib/fixjour/builders.rb
CHANGED
@@ -1,61 +1,79 @@
|
|
1
1
|
module Fixjour
|
2
2
|
class << self
|
3
|
-
|
4
|
-
begin
|
5
|
-
module_eval(&block)
|
6
|
-
rescue NameError => e
|
7
|
-
if evaluator.respond_to?(e.name)
|
8
|
-
raise NonBlockBuilderReference.new("You must use a builder block in order to reference other Fixjour creation methods.")
|
9
|
-
else
|
10
|
-
raise e
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
3
|
+
attr_accessor :allow_redundancy
|
14
4
|
|
15
5
|
# The list of classes that have builders defined.
|
16
6
|
def builders
|
17
7
|
@builders ||= Set.new
|
18
8
|
end
|
19
9
|
|
20
|
-
# Registers a class' builder. This allows us to make sure
|
21
|
-
# redundant builders aren't defined, which can lead to confusion
|
22
|
-
# when trying to figure out where objects are being created.
|
23
|
-
def add_builder(klass)
|
24
|
-
unless builders.add?(klass)
|
25
|
-
raise RedundantBuilder.new("You already defined a builder for #{klass.inspect}")
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
10
|
# This method should always return a valid instance of
|
30
11
|
# a model object.
|
31
12
|
def define_builder(klass, options={}, &block)
|
32
13
|
add_builder(klass)
|
33
14
|
|
34
|
-
name = name_for(klass)
|
35
|
-
|
36
15
|
if block_given?
|
37
|
-
define_new(
|
16
|
+
define_new(klass, &block)
|
38
17
|
else
|
39
|
-
define_new(
|
18
|
+
define_new(klass) do |overrides|
|
40
19
|
klass.new(options.merge(overrides))
|
41
20
|
end
|
42
21
|
end
|
43
22
|
|
23
|
+
name = name_for(klass)
|
24
|
+
|
44
25
|
define_create(name)
|
45
26
|
define_valid_attributes(name)
|
46
27
|
end
|
47
28
|
|
29
|
+
# Adds builders to Fixjour.
|
30
|
+
def evaluate(&block)
|
31
|
+
begin
|
32
|
+
module_eval(&block)
|
33
|
+
rescue NameError => e
|
34
|
+
if evaluator.respond_to?(e.name)
|
35
|
+
raise NonBlockBuilderReference.new("You must use a builder block in order to reference other Fixjour creation methods.")
|
36
|
+
else
|
37
|
+
raise e
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# Checks to see whether or not a builder is defined. Duh.
|
43
|
+
def builder_defined?(builder)
|
44
|
+
case builder
|
45
|
+
when Class then builders.include?(builders)
|
46
|
+
when String, Symbol then builders.map(&:name).include?(builder)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
48
50
|
private
|
49
51
|
|
52
|
+
# Registers a class' builder. This allows us to make sure
|
53
|
+
# redundant builders aren't defined, which can lead to confusion
|
54
|
+
# when trying to figure out where objects are being created.
|
55
|
+
def add_builder(klass)
|
56
|
+
unless builders.add?(klass) or Fixjour.allow_redundancy
|
57
|
+
raise RedundantBuilder.new("You already defined a builder for #{klass.inspect}")
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
50
61
|
def name_for(klass)
|
51
62
|
klass.name.underscore
|
52
63
|
end
|
53
64
|
|
54
65
|
# Defines the new_* method
|
55
|
-
def define_new(
|
66
|
+
def define_new(klass, &block)
|
67
|
+
name = name_for(klass)
|
56
68
|
define_method("new_#{name}") do |*args|
|
57
69
|
overrides = OverridesHash.new(args.first || { })
|
58
|
-
|
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)
|
59
77
|
result
|
60
78
|
end
|
61
79
|
end
|
@@ -86,6 +104,7 @@ module Fixjour
|
|
86
104
|
end
|
87
105
|
end
|
88
106
|
|
107
|
+
# Anonymous class used for reflecting on current Fixjour state.
|
89
108
|
def evaluator
|
90
109
|
@evaluator ||= begin
|
91
110
|
klass = Class.new
|
data/lib/fixjour/errors.rb
CHANGED
@@ -8,5 +8,11 @@ module Fixjour
|
|
8
8
|
# Raised when a builder block saves the object.
|
9
9
|
class BuilderSavedRecord < StandardError; end
|
10
10
|
|
11
|
+
# Raised when a Fixjour creation method is called in
|
12
|
+
# the wrong context.
|
11
13
|
class NonBlockBuilderReference < StandardError; end
|
14
|
+
|
15
|
+
# Raised when a builder is defined for a class that already
|
16
|
+
# has one.
|
17
|
+
class RedundantBuilder < StandardError; end
|
12
18
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Fixjour
|
2
|
+
# Proxy passed to builder blocks as first argument when a builder
|
3
|
+
# block takes two arguments. Automatically merges overrides when
|
4
|
+
# the #new method is called.
|
5
|
+
class MergingProxy
|
6
|
+
instance_methods.each { |m| undef_method(m) unless m =~ /__|inspect/ }
|
7
|
+
|
8
|
+
def initialize(klass, overrides)
|
9
|
+
@klass = klass
|
10
|
+
@overrides = overrides
|
11
|
+
end
|
12
|
+
|
13
|
+
def new(defaults={})
|
14
|
+
@klass.new(defaults.merge(@overrides))
|
15
|
+
end
|
16
|
+
|
17
|
+
def method_missing(sym, *args, &block)
|
18
|
+
@klass.respond_to?(sym) ? @klass.send(sym, *args, &block) : super
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -1,4 +1,7 @@
|
|
1
1
|
module Fixjour
|
2
|
+
# The overrides hash passed into each of the Fixjour
|
3
|
+
# methods is wrapped in this class to make the delete
|
4
|
+
# method private and add the ability to process.
|
2
5
|
class OverridesHash < Hash
|
3
6
|
private :delete
|
4
7
|
|
@@ -6,6 +9,8 @@ module Fixjour
|
|
6
9
|
replace(hash)
|
7
10
|
end
|
8
11
|
|
12
|
+
# Allows for processing of the overrides hash. Deletes
|
13
|
+
# the option when it's present, then yields the value.
|
9
14
|
def process(option)
|
10
15
|
if value = delete(option)
|
11
16
|
yield value if block_given?
|
@@ -1,19 +1,8 @@
|
|
1
1
|
module Fixjour
|
2
|
-
# Raised when a builder is defined for a class that already
|
3
|
-
# has one.
|
4
|
-
class RedundantBuilder < StandardError; end
|
5
|
-
|
6
2
|
def self.included(klass)
|
7
3
|
klass.extend(RedundancyChecker)
|
8
4
|
end
|
9
5
|
|
10
|
-
def self.builder_defined?(builder)
|
11
|
-
case builder
|
12
|
-
when Class then builders.include?(builders)
|
13
|
-
when String, Symbol then builders.map(&:name).include?(builder)
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
6
|
module RedundancyChecker
|
18
7
|
BUILDER_METHOD_PATTERN = /^(new|create|valid)_(\w+)(_attributes)?$/
|
19
8
|
|
data/lib/fixjour.rb
CHANGED
@@ -3,6 +3,7 @@ $LOAD_PATH << File.dirname(__FILE__)
|
|
3
3
|
require 'rubygems'
|
4
4
|
require 'activerecord'
|
5
5
|
require 'core_ext/hash'
|
6
|
+
require 'fixjour/merging_proxy'
|
6
7
|
require 'fixjour/redundant_check'
|
7
8
|
require 'fixjour/overrides_hash'
|
8
9
|
require 'fixjour/verify'
|
@@ -12,6 +13,8 @@ require 'fixjour/builders'
|
|
12
13
|
# This method is just for prettiness
|
13
14
|
def Fixjour(options={}, &block)
|
14
15
|
return Fixjour unless block_given?
|
16
|
+
Fixjour.allow_redundancy = options[:allow_redundancy]
|
15
17
|
Fixjour.evaluate(&block)
|
16
18
|
Fixjour.verify! if options[:verify]
|
19
|
+
Fixjour.allow_redundancy = false
|
17
20
|
end
|
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.0.
|
4
|
+
version: 0.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Pat Nakajima
|
@@ -34,6 +34,7 @@ files:
|
|
34
34
|
- lib/core_ext/hash.rb
|
35
35
|
- lib/fixjour
|
36
36
|
- lib/fixjour/builders.rb
|
37
|
+
- lib/fixjour/merging_proxy.rb
|
37
38
|
- lib/fixjour/errors.rb
|
38
39
|
- lib/fixjour/verify.rb
|
39
40
|
- lib/fixjour/redundant_check.rb
|