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.
@@ -1,61 +1,79 @@
1
1
  module Fixjour
2
2
  class << self
3
- def evaluate(&block)
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(name, &block)
16
+ define_new(klass, &block)
38
17
  else
39
- define_new(name) do |overrides|
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(name, &block)
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
- result = block.bind(self).call(overrides)
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
@@ -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.5
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