nakajima-fixjour 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/core_ext/hash.rb +9 -0
- data/lib/fixjour.rb +14 -0
- data/lib/fixjour/builders.rb +68 -0
- data/lib/fixjour/errors.rb +14 -0
- data/lib/fixjour/verify.rb +36 -0
- metadata +67 -0
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
|
+
|