nakajima-fixjour 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,9 @@
1
+ class Hash
2
+ # Makes a hash able to be accessed via symbol or string keys.
3
+ def make_indifferent!
4
+ keys_values = self.dup
5
+ indifferent = Hash.new { |h,k| h[k.to_s] if Symbol === k }
6
+ replace(indifferent)
7
+ merge!(keys_values)
8
+ end
9
+ end
data/lib/fixjour.rb ADDED
@@ -0,0 +1,14 @@
1
+ $LOAD_PATH << File.dirname(__FILE__)
2
+
3
+ require 'rubygems'
4
+ require 'activerecord'
5
+ require 'core_ext/hash'
6
+ require 'fixjour/verify'
7
+ require 'fixjour/errors'
8
+ require 'fixjour/builders'
9
+
10
+ # This method is just for prettiness
11
+ def Fixjour(&block)
12
+ return Fixjour unless block_given?
13
+ Fixjour.module_eval(&block)
14
+ end
@@ -0,0 +1,68 @@
1
+ module Fixjour
2
+ class << self
3
+ # The list of classes that have builders defined.
4
+ def builders
5
+ @builders ||= Set.new
6
+ end
7
+
8
+ # Registers a class' builder. This allows us to make sure
9
+ # redundant builders aren't defined, which can lead to confusion
10
+ # when trying to figure out where objects are being created.
11
+ def add_builder(klass)
12
+ unless builders.add?(klass)
13
+ raise RedundantBuilder.new("You already defined a builder for #{klass.inspect}")
14
+ end
15
+ end
16
+
17
+ # This method should always return a valid instance of
18
+ # a model object.
19
+ def define_builder(klass, &block)
20
+ add_builder(klass)
21
+
22
+ name = name_for(klass)
23
+
24
+ define_new(name, block)
25
+ define_create(name)
26
+ define_valid_attributes(name)
27
+ end
28
+
29
+ private
30
+
31
+ def name_for(klass)
32
+ klass.model_name.singular
33
+ end
34
+
35
+ # Defines the new_* method
36
+ def define_new(name, block)
37
+ define_method("new_#{name}") do |*args|
38
+ overrides = args.first || { }
39
+ block.bind(self).call(overrides)
40
+ end
41
+ end
42
+
43
+ # Defines the create_* method
44
+ def define_create(name)
45
+ define_method("create_#{name}") do |*args|
46
+ model = send("new_#{name}", *args)
47
+ model.save!
48
+ model
49
+ end
50
+ end
51
+
52
+ # Defines the valid_*_attributes method
53
+ def define_valid_attributes(name)
54
+ define_method("valid_#{name}_attributes") do |*args|
55
+ if instance_variable_get("@__valid_#{name}_attrs").nil?
56
+ valid_attributes = send("new_#{name}").attributes
57
+ valid_attributes.delete_if { |key, value| value.nil? }
58
+ instance_variable_set("@__valid_#{name}_attrs", valid_attributes)
59
+ end
60
+
61
+ overrides = args.extract_options!
62
+ attrs = instance_variable_get("@__valid_#{name}_attrs").merge(overrides)
63
+ attrs.make_indifferent!
64
+ attrs
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,14 @@
1
+ module Fixjour
2
+ # Raised when a builder returns an invalid object
3
+ class InvalidBuilder < StandardError; end
4
+
5
+ # Raised when a builder returns an object of the wrong type
6
+ class WrongBuilderType < StandardError; end
7
+
8
+ # Raised when a builder is defined for a class that already
9
+ # has one.
10
+ class RedundantBuilder < StandardError; end
11
+
12
+ # Raised when a builder block saves the object.
13
+ class BuilderSavedRecord < StandardError; end
14
+ end
@@ -0,0 +1,36 @@
1
+ module Fixjour
2
+ class << self
3
+ # Checks each builder to ensure that they:
4
+ #
5
+ # * Return valid objects
6
+ # * The new_* methods return new records
7
+ # * The creation methods return objects of the proper type
8
+ def verify!
9
+ builders.each do |klass|
10
+ result = validity_checker.send("new_#{name_for(klass)}")
11
+
12
+ unless result.valid?
13
+ raise InvalidBuilder.new("The builder for #{klass} returns an invalid object")
14
+ end
15
+
16
+ unless result.new_record?
17
+ raise BuilderSavedRecord.new("The builder for #{klass} must not save the object")
18
+ end
19
+
20
+ unless result.is_a?(klass)
21
+ raise WrongBuilderType.new("The builder for #{klass} must return instance of #{klass}")
22
+ end
23
+ end
24
+ end
25
+
26
+ private
27
+
28
+ def validity_checker
29
+ @evaluator ||= begin
30
+ klass = Class.new
31
+ klass.send :include, self
32
+ klass.new
33
+ end
34
+ end
35
+ end
36
+ end
metadata ADDED
@@ -0,0 +1,67 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: nakajima-fixjour
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Pat Nakajima
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-12-29 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: activerecord
17
+ version_requirement:
18
+ version_requirements: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: "0"
23
+ version:
24
+ description:
25
+ email: patnakajima@gmail.com
26
+ executables: []
27
+
28
+ extensions: []
29
+
30
+ extra_rdoc_files: []
31
+
32
+ files:
33
+ - lib/core_ext
34
+ - lib/core_ext/hash.rb
35
+ - lib/fixjour
36
+ - lib/fixjour/builders.rb
37
+ - lib/fixjour/errors.rb
38
+ - lib/fixjour/verify.rb
39
+ - lib/fixjour.rb
40
+ has_rdoc: true
41
+ homepage: http://github.com/nakajima/fixjour
42
+ post_install_message:
43
+ rdoc_options: []
44
+
45
+ require_paths:
46
+ - lib
47
+ required_ruby_version: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: "0"
52
+ version:
53
+ required_rubygems_version: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: "0"
58
+ version:
59
+ requirements: []
60
+
61
+ rubyforge_project:
62
+ rubygems_version: 1.2.0
63
+ signing_key:
64
+ specification_version: 2
65
+ summary: Object creation methods everyone already has
66
+ test_files: []
67
+