veneer 0.1.0
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/.document +5 -0
- data/.gitignore +5 -0
- data/LICENSE +20 -0
- data/README.textile +138 -0
- data/Rakefile +64 -0
- data/VERSION +1 -0
- data/datamapper_setup.rb +2 -0
- data/lib/veneer.rb +35 -0
- data/lib/veneer/adapters/activerecord.rb +2 -0
- data/lib/veneer/adapters/activerecord/class_wrapper.rb +90 -0
- data/lib/veneer/adapters/activerecord/instance_wrapper.rb +11 -0
- data/lib/veneer/adapters/datamapper.rb +2 -0
- data/lib/veneer/adapters/datamapper/class_wrapper.rb +54 -0
- data/lib/veneer/adapters/datamapper/instance_wrapper.rb +23 -0
- data/lib/veneer/base/class_wrapper.rb +53 -0
- data/lib/veneer/base/conditional.rb +77 -0
- data/lib/veneer/base/instance_wrapper.rb +38 -0
- data/lib/veneer/core_ext/kernel.rb +17 -0
- data/lib/veneer/errors.rb +9 -0
- data/lib/veneer/proxy.rb +4 -0
- data/test/macros/class_wrapper/create_macro.rb +54 -0
- data/test/macros/class_wrapper/delete_macro.rb +31 -0
- data/test/macros/class_wrapper/find_macro.rb +112 -0
- data/test/macros/instance_wrapper/destroy_macro.rb +36 -0
- data/test/macros/instance_wrapper/new_record_macro.rb +35 -0
- data/test/macros/instance_wrapper/save_macro.rb +55 -0
- data/test/macros/veneer_constants_interface.rb +26 -0
- data/test/support/helpers.rb +18 -0
- data/test/test_helper.rb +16 -0
- data/test/veneer/adapters/active_record/active_record_setup.rb +28 -0
- data/test/veneer/adapters/active_record/class_wrapper_test.rb +21 -0
- data/test/veneer/adapters/active_record/instance_wrapper_test.rb +21 -0
- data/test/veneer/adapters/datamapper/class_wrapper_test.rb +22 -0
- data/test/veneer/adapters/datamapper/datamapper_setup.rb +25 -0
- data/test/veneer/adapters/datamapper/instance_wrapper_test.rb +21 -0
- data/test/veneer/base/conditonal_test.rb +118 -0
- data/test/veneer/proxy_test.rb +190 -0
- data/veneer.gemspec +95 -0
- metadata +109 -0
@@ -0,0 +1,23 @@
|
|
1
|
+
module DataMapper
|
2
|
+
module Resource
|
3
|
+
module VeneerInterface
|
4
|
+
class InstanceWrapper < ::Veneer::Base::InstanceWrapper
|
5
|
+
|
6
|
+
def save!
|
7
|
+
r = instance.save
|
8
|
+
raise ::Veneer::Errors::NotSaved unless r
|
9
|
+
r
|
10
|
+
end
|
11
|
+
|
12
|
+
def new_record?
|
13
|
+
instance.respond_to?(:new?) ? instance.new? : instance.new_record?
|
14
|
+
end
|
15
|
+
|
16
|
+
def destroy
|
17
|
+
instance.destroy
|
18
|
+
self
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Veneer
|
2
|
+
module Base
|
3
|
+
class ClassWrapper < BasicObject
|
4
|
+
attr_reader :klass, :opts
|
5
|
+
def initialize(klass, opts)
|
6
|
+
@klass, @opts = klass, opts
|
7
|
+
end
|
8
|
+
|
9
|
+
# @api public
|
10
|
+
def create!(opts = {})
|
11
|
+
instance = new(opts)
|
12
|
+
instance.save!
|
13
|
+
instance
|
14
|
+
end
|
15
|
+
|
16
|
+
# @api public
|
17
|
+
def create(opts = {})
|
18
|
+
instance = new(opts)
|
19
|
+
instance.save
|
20
|
+
instance
|
21
|
+
end
|
22
|
+
|
23
|
+
# @api implementor
|
24
|
+
def new(opts = {})
|
25
|
+
::Kernel.raise Errors::NotImplemented
|
26
|
+
end
|
27
|
+
|
28
|
+
# @api public
|
29
|
+
def first(opts={})
|
30
|
+
conditional = ::Veneer::Conditional.from_hash(opts)
|
31
|
+
::Kernel.Veneer(find_first(conditional))
|
32
|
+
end
|
33
|
+
|
34
|
+
# @api public
|
35
|
+
def all(opts={})
|
36
|
+
conditional = ::Veneer::Conditional.from_hash(opts)
|
37
|
+
find_many(conditional).map{|element| ::Kernel.Veneer(element)}
|
38
|
+
end
|
39
|
+
|
40
|
+
# Should return an array or array like structure with elements matching the provided conditional
|
41
|
+
# @api implementor
|
42
|
+
def find_many(conditional)
|
43
|
+
::Kernel.raise Errors::NotImplemented
|
44
|
+
end
|
45
|
+
|
46
|
+
# A single object matching the conditional
|
47
|
+
# @api_implementor
|
48
|
+
def find_first(conditional)
|
49
|
+
::Kernel.raise Errors::NotImplemented
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
module Veneer
|
2
|
+
class Conditional
|
3
|
+
|
4
|
+
def self.from_hash(hash)
|
5
|
+
new(hash)
|
6
|
+
end
|
7
|
+
|
8
|
+
attr_reader :options
|
9
|
+
def initialize(opts)
|
10
|
+
@options = HashWithIndifferentAccess.new(opts || {})
|
11
|
+
odr = Array.new([@options.delete(:order)].flatten.compact)
|
12
|
+
@ordering = odr.nil? || odr.empty? ? [] : begin
|
13
|
+
odr.map do |order|
|
14
|
+
field, direction = order.split(" ")
|
15
|
+
Order.new(field, (direction || :desc))
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
conds = opts.fetch(:conditions, {})
|
20
|
+
@conditions = conds.map do |k,v|
|
21
|
+
field, operator = k.to_s.split(" ")
|
22
|
+
args = [field, v]
|
23
|
+
args << operator.to_sym if operator
|
24
|
+
Veneer::Conditional::Condition.new(*args)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def limit
|
29
|
+
@options[:limit]
|
30
|
+
end
|
31
|
+
|
32
|
+
def offset
|
33
|
+
@options[:offset]
|
34
|
+
end
|
35
|
+
|
36
|
+
def order
|
37
|
+
@ordering
|
38
|
+
end
|
39
|
+
|
40
|
+
def conditions
|
41
|
+
@conditions
|
42
|
+
end
|
43
|
+
|
44
|
+
class Order
|
45
|
+
attr_reader :field, :direction
|
46
|
+
def initialize(field, direction = :desc)
|
47
|
+
@field = field.to_sym
|
48
|
+
@direction = direction.to_sym
|
49
|
+
end
|
50
|
+
|
51
|
+
def ascending?
|
52
|
+
direction == :asc
|
53
|
+
end
|
54
|
+
|
55
|
+
def decending?
|
56
|
+
!ascending?
|
57
|
+
end
|
58
|
+
|
59
|
+
def ==(other)
|
60
|
+
self.class == other.class &&
|
61
|
+
field == other.field &&
|
62
|
+
direction == other.direction
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
class Condition
|
67
|
+
attr_accessor :field, :operator, :value
|
68
|
+
|
69
|
+
VALID_OPERATORS = [:eql, :gt, :gte, :lt, :lte, :in, :not]
|
70
|
+
|
71
|
+
def initialize(field, value, operator = :eql)
|
72
|
+
@field, @value, @operator = field.to_sym, value, operator.to_sym
|
73
|
+
raise Veneer::Errors::ConditionalOperatorNotSupported, "#{operator.inspect} not a valid operator" unless VALID_OPERATORS.include?(operator)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Veneer
|
2
|
+
module Base
|
3
|
+
class InstanceWrapper
|
4
|
+
attr_accessor :instance, :options
|
5
|
+
def initialize(instance, opts = {})
|
6
|
+
@instance, @options = instance, opts
|
7
|
+
end
|
8
|
+
|
9
|
+
# Checks equality of the instances
|
10
|
+
# @api public
|
11
|
+
def ==(other)
|
12
|
+
case other
|
13
|
+
when Veneer::Base::InstanceWrapper
|
14
|
+
instance == other.instance
|
15
|
+
else
|
16
|
+
instance == other
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# Updates the attributes by trying to use the keys of the
|
21
|
+
# attributes hash as a setter method (:"#{key}=") to the value of the hash
|
22
|
+
# then the object is saved
|
23
|
+
# Adapter implementors may want to overwrite may want to overwrite
|
24
|
+
# @api public
|
25
|
+
def update(attributes = {})
|
26
|
+
attributes.each do |attr,value|
|
27
|
+
instance.send(:"#{attr}=",value)
|
28
|
+
end
|
29
|
+
save
|
30
|
+
end
|
31
|
+
|
32
|
+
# send all methods to the instance
|
33
|
+
def method_missing(*args, &blk)
|
34
|
+
instance.send(*args, &blk)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Kernel
|
2
|
+
def Veneer(obj, opts = {})
|
3
|
+
case obj
|
4
|
+
when Class
|
5
|
+
obj::VeneerInterface::ClassWrapper.new(obj, opts)
|
6
|
+
when Veneer::Base::ClassWrapper, Veneer::Base::InstanceWrapper
|
7
|
+
obj
|
8
|
+
when nil
|
9
|
+
nil
|
10
|
+
else
|
11
|
+
obj.class::VeneerInterface::InstanceWrapper.new(obj, opts)
|
12
|
+
end
|
13
|
+
rescue NameError => e
|
14
|
+
puts e.message
|
15
|
+
raise Veneer::Errors::NotCompatible
|
16
|
+
end # Veneer()
|
17
|
+
end
|
data/lib/veneer/proxy.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
class Test::Unit::TestCase
|
2
|
+
def self.veneer_should_implement_create_with_valid_attributes
|
3
|
+
context "implements create with valid attributes" do
|
4
|
+
should "setup the spec correctly" do
|
5
|
+
assert_not_nil @klass
|
6
|
+
assert_kind_of Class, @klass
|
7
|
+
assert_not_nil @valid_attributes
|
8
|
+
assert_kind_of Hash, @valid_attributes
|
9
|
+
end
|
10
|
+
|
11
|
+
teardown do
|
12
|
+
Veneer(@klass).destroy_all
|
13
|
+
end
|
14
|
+
|
15
|
+
should "create the object from the hash" do
|
16
|
+
r = Veneer(@klass).create(@valid_attributes)
|
17
|
+
assert_instance_of @klass::VeneerInterface::InstanceWrapper, r
|
18
|
+
end
|
19
|
+
|
20
|
+
should "create the object from the hash with create!" do
|
21
|
+
r = Veneer(@klass).create!(@valid_attributes)
|
22
|
+
assert_instance_of @klass::VeneerInterface::InstanceWrapper, r
|
23
|
+
end
|
24
|
+
|
25
|
+
should "create a new instance of the object" do
|
26
|
+
r = Veneer(@klass).new(@valid_attributes)
|
27
|
+
assert_instance_of @klass::VeneerInterface::InstanceWrapper, r
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.veneer_should_implement_create_with_invalid_attributes
|
32
|
+
context "implements create! with invalid attributes" do
|
33
|
+
should "setup the spec correctly" do
|
34
|
+
assert_not_nil @klass
|
35
|
+
assert_kind_of Class, @klass
|
36
|
+
assert_not_nil @invalid_attributes
|
37
|
+
assert_kind_of Hash, @invalid_attributes
|
38
|
+
end
|
39
|
+
|
40
|
+
should "raise when creating could not save" do
|
41
|
+
assert_raise Veneer::Errors::NotSaved do
|
42
|
+
Veneer(@klass).create!(@invalid_attributes)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
should "not raise when create can not save" do
|
47
|
+
assert_nothing_raised do
|
48
|
+
Veneer(@klass).create(@invalid_attributes)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
class Test::Unit::TestCase
|
2
|
+
def self.veneer_should_impelement_destroy_all
|
3
|
+
context "implements destroy_all" do
|
4
|
+
should "setup the test correctly" do
|
5
|
+
assert_not_nil @klass
|
6
|
+
assert_kind_of Class, @klass
|
7
|
+
assert_not_nil @valid_attributes
|
8
|
+
assert_kind_of Hash, @valid_attributes
|
9
|
+
end
|
10
|
+
|
11
|
+
context "destroy_all" do
|
12
|
+
setup do
|
13
|
+
Veneer(@klass).destroy_all
|
14
|
+
assert_equal 0, Veneer(@klass).all.size
|
15
|
+
(0..5).each do |i|
|
16
|
+
Veneer(@klass).new(:name => "foo#{i}", :order_field1 => i).save
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
should "setup the spec correctly" do
|
21
|
+
assert_equal 6, Veneer(@klass).all.size
|
22
|
+
end
|
23
|
+
|
24
|
+
should "destroy all records" do
|
25
|
+
Veneer(@klass).destroy_all
|
26
|
+
assert_equal 0, Veneer(@klass).all.size
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
class Test::Unit::TestCase
|
2
|
+
def self.veneer_should_implement_find
|
3
|
+
context "implements find" do
|
4
|
+
setup do
|
5
|
+
Veneer(@klass).destroy_all
|
6
|
+
(0..5).each do |i|
|
7
|
+
Veneer(@klass).new(:order_field1 => i).save!
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
teardown{ Veneer(@klass).destroy_all }
|
12
|
+
|
13
|
+
should "impelement a find_all method" do
|
14
|
+
result = Veneer(@klass).find_many(Veneer::Conditional.from_hash({}))
|
15
|
+
assert_kind_of Array, result
|
16
|
+
end
|
17
|
+
|
18
|
+
should "implement a find_first method" do
|
19
|
+
result = Veneer(@klass).find_first(Veneer::Conditional.from_hash({}))
|
20
|
+
end
|
21
|
+
|
22
|
+
should "implement limit" do
|
23
|
+
total = Veneer(@klass).find_many(Veneer::Conditional.from_hash({}))
|
24
|
+
assert_not_equal 3, total.size
|
25
|
+
result = Veneer(@klass).find_many(Veneer::Conditional.from_hash(:limit => 3))
|
26
|
+
assert_equal 3, result.size
|
27
|
+
end
|
28
|
+
|
29
|
+
should "implement order" do
|
30
|
+
result = Veneer(@klass).find_many(Veneer::Conditional.from_hash(:order => "order_field1"))
|
31
|
+
raw = result.map{|i| i.order_field1 }.compact
|
32
|
+
sorted = raw.sort.reverse
|
33
|
+
assert_equal raw, sorted
|
34
|
+
end
|
35
|
+
|
36
|
+
should "implement order decending" do
|
37
|
+
result = Veneer(@klass).find_many(Veneer::Conditional.from_hash(:order => "order_field1 desc"))
|
38
|
+
raw = result.map{|i| i.order_field1 }.compact
|
39
|
+
sorted = raw.sort.reverse
|
40
|
+
assert_equal raw, sorted
|
41
|
+
end
|
42
|
+
|
43
|
+
should "implement order ascending" do
|
44
|
+
result = Veneer(@klass).find_many(Veneer::Conditional.from_hash(:order => "order_field1 asc"))
|
45
|
+
raw = result.map{|i| i.order_field1}.compact
|
46
|
+
sorted = raw.sort
|
47
|
+
assert_equal raw, sorted
|
48
|
+
end
|
49
|
+
|
50
|
+
should "impelment offset" do
|
51
|
+
total = Veneer(@klass).find_many(Veneer::Conditional.from_hash({}))
|
52
|
+
result = Veneer(@klass).find_many(Veneer::Conditional.from_hash({:offset => 2, :limit => 2}))
|
53
|
+
|
54
|
+
assert_equal((total[2..3]), result)
|
55
|
+
end
|
56
|
+
|
57
|
+
context "conditions" do
|
58
|
+
setup do
|
59
|
+
Veneer(@klass).new(:name => "bar").save
|
60
|
+
Veneer(@klass).new(:name => "foo").save
|
61
|
+
Veneer(@klass).new(:name => "foobar").save
|
62
|
+
end
|
63
|
+
|
64
|
+
should "implement basic conditions" do
|
65
|
+
total = Veneer(@klass).find_many(Veneer::Conditional.from_hash({}))
|
66
|
+
result = Veneer(@klass).find_many(Veneer::Conditional.from_hash(:conditions => {:name => "foo"}))
|
67
|
+
assert_equal 1, result.size
|
68
|
+
end
|
69
|
+
|
70
|
+
should "implement :not conditions" do
|
71
|
+
Veneer(@klass).all(:conditions => {:name => nil}).map(&:destroy)
|
72
|
+
total = Veneer(@klass).find_many(Veneer::Conditional.from_hash({}))
|
73
|
+
result = Veneer(@klass).find_many(Veneer::Conditional.from_hash(:conditions => {"name not" => "bar"}))
|
74
|
+
assert_equal((total.size - 1), result.size)
|
75
|
+
end
|
76
|
+
|
77
|
+
should "implement gt conditions" do
|
78
|
+
total = Veneer(@klass).find_many(Veneer::Conditional.from_hash({}))
|
79
|
+
expected = total.select{|i| !i.order_field1.nil? && i.order_field1 > 3}
|
80
|
+
result = Veneer(@klass).find_many(Veneer::Conditional.from_hash(:conditions => {"order_field1 gt" => 3}))
|
81
|
+
assert_equal expected.size, result.size
|
82
|
+
end
|
83
|
+
|
84
|
+
should "implement gte conditions" do
|
85
|
+
total = Veneer(@klass).find_many(Veneer::Conditional.from_hash({}))
|
86
|
+
expected = total.select{|i| !i.order_field1.nil? && i.order_field1 >= 3}
|
87
|
+
result = Veneer(@klass).find_many(Veneer::Conditional.from_hash(:conditions => {"order_field1 gte" => 3}))
|
88
|
+
assert_equal 3, result.size
|
89
|
+
end
|
90
|
+
|
91
|
+
should "implement :lt condition" do
|
92
|
+
result = Veneer(@klass).find_many(Veneer::Conditional.from_hash(:conditions => {"order_field1 lt" => 3}))
|
93
|
+
assert_equal 3, result.size
|
94
|
+
end
|
95
|
+
|
96
|
+
should "implement a lte condition" do
|
97
|
+
total = Veneer(@klass).find_many(Veneer::Conditional.from_hash({}))
|
98
|
+
expected = total.select{|i| !i.order_field1.nil? && i.order_field1 <= 3}
|
99
|
+
result = Veneer(@klass).find_many(Veneer::Conditional.from_hash(:conditions => {"order_field1 lte" => 3}))
|
100
|
+
assert_equal expected.size, result.size
|
101
|
+
end
|
102
|
+
|
103
|
+
should "implement an :in condition" do
|
104
|
+
total = Veneer(@klass).find_many(Veneer::Conditional.from_hash({}))
|
105
|
+
expected = total.select{|i| ["foo", "bar"].include?(i.name)}
|
106
|
+
result = Veneer(@klass).find_many(Veneer::Conditional.from_hash(:conditions => {"name in" => ["foo", "bar"]}))
|
107
|
+
assert_equal expected.size, result.size
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
class Test::Unit::TestCase
|
2
|
+
def self.veneer_should_implement_destroy
|
3
|
+
context "on an instance" do
|
4
|
+
should "setup the test correctly" do
|
5
|
+
assert_not_nil @klass
|
6
|
+
assert_kind_of Class, @klass
|
7
|
+
assert_not_nil @valid_attributes
|
8
|
+
assert_kind_of Hash, @valid_attributes
|
9
|
+
end
|
10
|
+
|
11
|
+
setup do
|
12
|
+
Veneer(@klass).destroy_all
|
13
|
+
@valid = Veneer(@klass).new(@valid_attributes)
|
14
|
+
end
|
15
|
+
|
16
|
+
should "setup the spec" do
|
17
|
+
assert @valid.save
|
18
|
+
r = Veneer(@klass).first(:conditions => {:name => @valid.instance.name})
|
19
|
+
assert_equal @valid, r
|
20
|
+
end
|
21
|
+
|
22
|
+
should "destroy the object" do
|
23
|
+
@valid.save
|
24
|
+
v = @valid
|
25
|
+
assert_equal v, @valid.destroy
|
26
|
+
end
|
27
|
+
|
28
|
+
should "remove the object from the collection" do
|
29
|
+
@valid.save
|
30
|
+
assert_equal @valid, Veneer(@klass).first(:conditions => {:name => @valid.name})
|
31
|
+
@valid.destroy
|
32
|
+
assert_nil Veneer(@klass).first(:conditions => {:name => @valid.name})
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|