fixjour 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,62 +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
- overrides = args.first || { }
58
- overrides.extend(OverrideProcessing)
59
- result = block.bind(self).call(overrides)
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)
60
77
  result
61
78
  end
62
79
  end
@@ -87,6 +104,7 @@ module Fixjour
87
104
  end
88
105
  end
89
106
 
107
+ # Anonymous class used for reflecting on current Fixjour state.
90
108
  def evaluator
91
109
  @evaluator ||= begin
92
110
  klass = Class.new
@@ -94,13 +112,5 @@ module Fixjour
94
112
  klass.new
95
113
  end
96
114
  end
97
-
98
- module OverrideProcessing
99
- def process(key)
100
- if value = delete(key)
101
- yield value
102
- end
103
- end
104
- end
105
115
  end
106
116
  end
@@ -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
@@ -0,0 +1,20 @@
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.
5
+ class OverridesHash < Hash
6
+ private :delete
7
+
8
+ def initialize(hash)
9
+ replace(hash)
10
+ end
11
+
12
+ # Allows for processing of the overrides hash. Deletes
13
+ # the option when it's present, then yields the value.
14
+ def process(option)
15
+ if value = delete(option)
16
+ yield value if block_given?
17
+ end
18
+ end
19
+ end
20
+ end
@@ -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,7 +3,9 @@ $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'
8
+ require 'fixjour/overrides_hash'
7
9
  require 'fixjour/verify'
8
10
  require 'fixjour/errors'
9
11
  require 'fixjour/builders'
@@ -11,6 +13,8 @@ require 'fixjour/builders'
11
13
  # This method is just for prettiness
12
14
  def Fixjour(options={}, &block)
13
15
  return Fixjour unless block_given?
16
+ Fixjour.allow_redundancy = options[:allow_redundancy]
14
17
  Fixjour.evaluate(&block)
15
18
  Fixjour.verify! if options[:verify]
19
+ Fixjour.allow_redundancy = false
16
20
  end
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.5
4
+ version: 0.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pat Nakajima
@@ -35,9 +35,11 @@ files:
35
35
  - lib/core_ext/hash.rb
36
36
  - lib/fixjour
37
37
  - lib/fixjour/builders.rb
38
+ - lib/fixjour/merging_proxy.rb
38
39
  - lib/fixjour/errors.rb
39
40
  - lib/fixjour/verify.rb
40
41
  - lib/fixjour/redundant_check.rb
42
+ - lib/fixjour/overrides_hash.rb
41
43
  - lib/fixjour.rb
42
44
  has_rdoc: true
43
45
  homepage: http://github.com/nakajima/fixjour