veneer 0.2.0 → 0.4.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/.gitignore +1 -0
- data/Gemfile +12 -1
- data/README.md +55 -87
- data/Rakefile +1 -1
- data/lib/veneer.rb +6 -1
- data/lib/veneer/adapters/activerecord.rb +2 -0
- data/lib/veneer/adapters/activerecord/class_wrapper.rb +99 -5
- data/lib/veneer/adapters/activerecord/instance_wrapper.rb +4 -2
- data/lib/veneer/adapters/activerecord/pre_3.0_class_wrapper.rb +62 -1
- data/lib/veneer/adapters/activerecord/property.rb +22 -0
- data/lib/veneer/adapters/datamapper.rb +1 -0
- data/lib/veneer/adapters/datamapper/class_wrapper.rb +90 -6
- data/lib/veneer/adapters/datamapper/property.rb +25 -0
- data/lib/veneer/adapters/mongomapper.rb +1 -0
- data/lib/veneer/adapters/mongomapper/class_wrapper.rb +68 -0
- data/lib/veneer/adapters/mongomapper/property.rb +16 -0
- data/lib/veneer/base/class_wrapper.rb +110 -7
- data/lib/veneer/base/property.rb +27 -0
- data/lib/veneer/lint.rb +4 -180
- data/lib/veneer/lint/adapter.rb +282 -0
- data/lib/veneer/lint/base.rb +10 -0
- data/lib/veneer/lint/properties.rb +78 -0
- data/lib/veneer/version.rb +1 -1
- data/test/support/helpers.rb +10 -1
- data/test/test_helper.rb +3 -3
- data/test/veneer/activerecord/test_adapter.rb +80 -0
- data/test/veneer/activerecord/test_properties.rb +73 -0
- data/test/veneer/datamapper/test_adapter.rb +71 -0
- data/test/veneer/datamapper/test_properties.rb +59 -0
- data/test/veneer/{adapters/test_mongomapper.rb → mongomapper/test_adapter.rb} +35 -11
- data/test/veneer/mongomapper/test_properties.rb +56 -0
- data/test/veneer_test.rb +35 -0
- data/veneer.gemspec +2 -0
- metadata +57 -51
- data/test/veneer/adapters/test_active_record.rb +0 -56
- data/test/veneer/adapters/test_datamapper.rb +0 -56
data/.gitignore
CHANGED
data/Gemfile
CHANGED
@@ -1,4 +1,15 @@
|
|
1
|
-
|
1
|
+
source "http://rubygems.org"
|
2
2
|
|
3
3
|
# Specify your gem's dependencies in ..gemspec
|
4
4
|
gemspec
|
5
|
+
|
6
|
+
gem 'rake'
|
7
|
+
gem 'shoulda'
|
8
|
+
gem 'activerecord'
|
9
|
+
gem 'mongo_mapper'
|
10
|
+
gem 'dm-core'
|
11
|
+
gem 'dm-migrations'
|
12
|
+
gem 'dm-aggregates'
|
13
|
+
gem 'dm-sqlite-adapter'
|
14
|
+
gem 'sqlite3-ruby'
|
15
|
+
gem 'mysql2'
|
data/README.md
CHANGED
@@ -7,119 +7,87 @@ Veneer aims to provide plugin, engine, and library authors with a consistant int
|
|
7
7
|
It differs from ActiveModel in that it doesn't provide any validation support, serialization, callbacks, state machine or anything like that. Veneer is intended to work _with_ ActiveModel to provide a data store independant interface to create reusable code.
|
8
8
|
|
9
9
|
Veneer instead aims to provide a simple interface for
|
10
|
+
|
10
11
|
* querying
|
11
12
|
* creating
|
12
13
|
* saving
|
13
14
|
* deleting
|
14
15
|
* basic lifecycle hooks
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
16
|
+
* before validation
|
17
|
+
* before save
|
18
|
+
* after save
|
19
|
+
* before destroy
|
20
|
+
* after destroy
|
20
21
|
|
21
22
|
There is no interface for validations, since this interface is handled as part of ActiveModel
|
22
23
|
|
23
|
-
##
|
24
|
-
|
25
|
-
To create an instance of an object wrap the class in a vaneer call and create or get a new instance.
|
26
|
-
|
27
|
-
<pre><code>obj = Veneer(MyModel).new(:some => "hash", :of => "attributes")
|
28
|
-
obj.save
|
24
|
+
## Quick Intro
|
29
25
|
|
30
|
-
|
31
|
-
|
32
|
-
obj = Veneer(MyModel).create(:some => "hash", :of => "attributes")
|
33
|
-
</code></pre>
|
26
|
+
<pre><code># Assume User class model
|
34
27
|
|
35
|
-
|
28
|
+
# Create new items
|
29
|
+
Veneer(User).new(:some => "parameters") # instantiate only
|
30
|
+
Veneer(User).create(:some => "parameters") # instantiate and persist
|
31
|
+
Veneer(User).create!(:some => "parameters") # create and raise on failure
|
36
32
|
|
37
|
-
|
38
|
-
|
39
|
-
# OR
|
40
|
-
|
41
|
-
obj = Veneer(MyModel).create!(:some => "attribute")
|
42
|
-
</code></pre>
|
33
|
+
# Query
|
43
34
|
|
44
|
-
|
35
|
+
# The supported options are:
|
36
|
+
#
|
37
|
+
# * :limit
|
38
|
+
# * :offset
|
39
|
+
# * :order
|
40
|
+
# * :conditions (hash with keys => <Array|Primitive|Range>
|
45
41
|
|
46
|
-
|
42
|
+
# First can be used in place of all to get a single item
|
43
|
+
# All options can be used together
|
47
44
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
</code></pre>
|
52
|
-
|
53
|
-
### Updating
|
54
|
-
|
55
|
-
To update an instance:
|
56
|
-
|
57
|
-
<pre><code>@some\_veneer\_instance.update(:with => "attributes")
|
58
|
-
|
59
|
-
OR
|
60
|
-
|
61
|
-
@some\_veneer\_instance.update!(:with => "attributes") # raise on error
|
62
|
-
</code></pre>
|
45
|
+
Veneer(User).all(:limit => 3, :offset => 2)
|
46
|
+
Veneer(User).all(:order => ["name", "dob desc"])
|
47
|
+
Veneer(User).all(:conditions => {:some => "condition"})
|
63
48
|
|
64
|
-
|
49
|
+
# Update object
|
50
|
+
user = Veneer(User).first(:conditions => {:id => params[:id]})
|
51
|
+
user.update(:some => "new values") # updates and persists changes
|
65
52
|
|
66
|
-
|
53
|
+
# Destroy object
|
54
|
+
user = Veneer(User).first(:conditions => {:id => params[:id]})
|
55
|
+
user.destroy
|
67
56
|
|
68
|
-
|
57
|
+
Veneer(User).destroy_all
|
69
58
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
The supported options are:
|
76
|
-
|
77
|
-
* :limit
|
78
|
-
* :offset
|
79
|
-
* :order
|
80
|
-
* :conditions
|
81
|
-
|
82
|
-
## Limit & Offset
|
83
|
-
|
84
|
-
The :limit option will limit the number of returned results.
|
85
|
-
|
86
|
-
The :offset option, when set to an integer x will begin the results at the xth result.
|
87
|
-
|
88
|
-
## Order
|
89
|
-
|
90
|
-
Ordering should be set as an array. By default, the order is decending.
|
91
|
-
|
92
|
-
The format of the array is:
|
93
|
-
|
94
|
-
<pre><code>["<field> <directon>", "<field>"]
|
95
|
-
|
96
|
-
### Example
|
97
|
-
Veneer(MyModel).all(:order => [:name, "age desc")
|
98
|
-
</code></pre>
|
59
|
+
# Save
|
60
|
+
user.name = "bar"
|
61
|
+
user.save
|
62
|
+
# OR
|
63
|
+
user.save! # raise on fail
|
99
64
|
|
100
|
-
|
65
|
+
# Find associations
|
66
|
+
Veneer(User).collection_associations # grabs things like has_many and has n
|
67
|
+
Veneer(User).member_associations # grabs singular associations like belongs_to and has_one
|
101
68
|
|
102
|
-
|
69
|
+
# ====> results in
|
70
|
+
[ { :name => "asociaiton_name", :class => AssociationClass }]
|
103
71
|
|
104
|
-
|
72
|
+
# Find property names (NOT YET IMPLEMENTED. PATCHES WELCOME)
|
105
73
|
|
106
|
-
|
107
|
-
Veneer(MyModel).all(:conditions => {:name => ["fred", "barney"], :age => (18..18)})
|
108
|
-
Veneer(MyModel).first(:conditions => {:name => "fred"})
|
109
|
-
</code></pre>
|
74
|
+
Veneer(User).property_names # => [:name, :login, ...]
|
110
75
|
|
111
|
-
|
76
|
+
# Discover loaded model classes
|
77
|
+
Veneer.model_classes
|
112
78
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
* nil
|
79
|
+
# Aggregate methods
|
80
|
+
Veneer(User).count
|
81
|
+
Veneer(User).count(conditional_options_same_as_all)
|
117
82
|
|
118
|
-
|
83
|
+
Veneer(User).sum(:column_name)
|
84
|
+
Veneer(User).sum(:column_name, conditional_options_same_as_all)
|
119
85
|
|
120
|
-
|
86
|
+
Veneer(User).min(:column_name)
|
87
|
+
Veneer(User).min(:column_name, conditional_options_same_as_all)
|
121
88
|
|
122
|
-
|
89
|
+
Veneer(User).max(:column_name)
|
90
|
+
Veneer(User).max(:column_name, conditional_options_same_as_all)
|
123
91
|
</code></pre>
|
124
92
|
|
125
93
|
## Object methods
|
@@ -128,7 +96,7 @@ All methods that aren't found on the adapter, are passed through to the instance
|
|
128
96
|
|
129
97
|
## Current Support
|
130
98
|
|
131
|
-
Veneer currently has built in support for ActiveRecord and DataMapper.
|
99
|
+
Veneer currently has built in support for ActiveRecord and DataMapper and MongoMapper.
|
132
100
|
|
133
101
|
Veneer works on a VeneerInterface inner module though so you can easily impelment your adapter without requiring it to be in the veneer repo (although pull requests are welcome) (see Building Your Adapter)
|
134
102
|
|
data/Rakefile
CHANGED
data/lib/veneer.rb
CHANGED
@@ -24,11 +24,16 @@ module Veneer
|
|
24
24
|
autoload :Errors, 'veneer/errors'
|
25
25
|
autoload :Proxy, 'veneer/proxy'
|
26
26
|
autoload :Conditional, 'veneer/base/conditional'
|
27
|
-
|
27
|
+
|
28
28
|
|
29
29
|
module Base
|
30
30
|
autoload :ClassWrapper, 'veneer/base/class_wrapper'
|
31
31
|
autoload :InstanceWrapper, 'veneer/base/instance_wrapper'
|
32
|
+
autoload :Property, 'veneer/base/property'
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.model_classes
|
36
|
+
Base::ClassWrapper.subclasses.map{|adapter| adapter.model_classes }.flatten.compact
|
32
37
|
end
|
33
38
|
end
|
34
39
|
|
@@ -2,10 +2,84 @@ module ActiveRecord
|
|
2
2
|
class Base
|
3
3
|
module VeneerInterface
|
4
4
|
class ClassWrapper < Veneer::Base::ClassWrapper
|
5
|
+
delegate :validators_on, :to => :klass
|
6
|
+
|
7
|
+
def self.except_classes
|
8
|
+
@@except_classes ||= [
|
9
|
+
"CGI::Session::ActiveRecordStore::Session",
|
10
|
+
"ActiveRecord::SessionStore::Session"
|
11
|
+
]
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.model_classes
|
15
|
+
klasses = ::ActiveRecord::Base.descendants
|
16
|
+
klasses.select do |klass|
|
17
|
+
!klass.abstract_class? && !except_classes.include?(klass.name)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
5
21
|
def new(opts = {})
|
6
22
|
::Kernel::Veneer(klass.new(opts))
|
7
23
|
end
|
8
24
|
|
25
|
+
def collection_associations
|
26
|
+
@collection_associations ||= begin
|
27
|
+
associations = []
|
28
|
+
[:has_many, :has_and_belongs_to_many].each do |macro|
|
29
|
+
associations += klass.reflect_on_all_associations(macro)
|
30
|
+
end
|
31
|
+
associations.inject([]) do |ary, reflection|
|
32
|
+
ary << {
|
33
|
+
:name => reflection.name,
|
34
|
+
:class => reflection.class_name.constantize
|
35
|
+
}
|
36
|
+
ary
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def member_associations
|
42
|
+
@member_associations ||= begin
|
43
|
+
associations = []
|
44
|
+
[:belongs_to, :has_one].each do |macro|
|
45
|
+
associations += klass.reflect_on_all_associations(macro)
|
46
|
+
end
|
47
|
+
associations.inject([]) do |ary, reflection|
|
48
|
+
ary << {
|
49
|
+
:name => reflection.name,
|
50
|
+
:class => reflection.class_name.constantize
|
51
|
+
}
|
52
|
+
ary
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def properties
|
58
|
+
@properties ||= begin
|
59
|
+
klass.columns.map do |property|
|
60
|
+
name = property.name.to_sym
|
61
|
+
::ActiveRecord::Base::VeneerInterface::Property.new(
|
62
|
+
self,
|
63
|
+
{
|
64
|
+
:name => name,
|
65
|
+
:type => property.type,
|
66
|
+
:constraints => {
|
67
|
+
:length => property.limit,
|
68
|
+
:nullable? => property.null,
|
69
|
+
:precision => property.precision,
|
70
|
+
:scale => property.scale,
|
71
|
+
},
|
72
|
+
:primary => primary_keys.include?(name),
|
73
|
+
}
|
74
|
+
)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def primary_keys
|
80
|
+
@primary_keys ||= [klass.primary_key.to_sym]
|
81
|
+
end
|
82
|
+
|
9
83
|
def destroy_all
|
10
84
|
klass.destroy_all
|
11
85
|
end
|
@@ -15,16 +89,36 @@ module ActiveRecord
|
|
15
89
|
end
|
16
90
|
|
17
91
|
def find_many(opts)
|
18
|
-
build_query(opts)
|
92
|
+
build_query(opts).all
|
93
|
+
end
|
94
|
+
|
95
|
+
def count(opts ={})
|
96
|
+
opts = ::Hashie::Mash.new(opts)
|
97
|
+
build_query(opts).count
|
98
|
+
end
|
99
|
+
|
100
|
+
def sum(field, opts={})
|
101
|
+
opts = ::Hashie::Mash.new(opts)
|
102
|
+
build_query(opts).sum(field)
|
103
|
+
end
|
104
|
+
|
105
|
+
def max(field, opts={})
|
106
|
+
opts = ::Hashie::Mash.new(opts)
|
107
|
+
build_query(opts).maximum(field)
|
108
|
+
end
|
109
|
+
|
110
|
+
def min(field, opts={})
|
111
|
+
opts = ::Hashie::Mash.new(opts)
|
112
|
+
build_query(opts).minimum(field)
|
19
113
|
end
|
20
114
|
|
21
115
|
private
|
22
116
|
def build_query(opts)
|
23
117
|
query = klass
|
24
|
-
query.where(opts.conditions) if opts.conditions.present?
|
25
|
-
query.limit(opts.limit)
|
26
|
-
query.offset(opts.offset)
|
27
|
-
query.order(opts.order)
|
118
|
+
query = query.where(opts.conditions.to_hash) if opts.conditions.present?
|
119
|
+
query = query.limit(opts.limit.to_i) if opts.limit?
|
120
|
+
query = query.offset(opts.offset.to_i) if opts.offset?
|
121
|
+
query = query.order(opts.order) if opts.order?
|
28
122
|
query
|
29
123
|
end
|
30
124
|
end # ClassWrapper
|
@@ -2,10 +2,56 @@ module ActiveRecord
|
|
2
2
|
class Base
|
3
3
|
module VeneerInterface
|
4
4
|
class ClassWrapper < Veneer::Base::ClassWrapper
|
5
|
+
def self.except_classes
|
6
|
+
@@except_classes ||= [
|
7
|
+
"CGI::Session::ActiveRecordStore::Session",
|
8
|
+
"ActiveRecord::SessionStore::Session"
|
9
|
+
]
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.model_classes
|
13
|
+
klasses = ::ActiveRecord::Base.__send__(:subclasses)
|
14
|
+
klasses.select do |klass|
|
15
|
+
!klass.abstract_class? && !except_classes.include?(klass.name)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
5
19
|
def new(opts = {})
|
6
20
|
::Kernel::Veneer(klass.new(opts))
|
7
21
|
end
|
8
22
|
|
23
|
+
def collection_associations
|
24
|
+
@collection_associations ||= begin
|
25
|
+
associations = []
|
26
|
+
[:has_many, :has_and_belongs_to_many].each do |macro|
|
27
|
+
associations += klass.reflect_on_all_associations(macro)
|
28
|
+
end
|
29
|
+
associations.inject([]) do |ary, reflection|
|
30
|
+
ary << {
|
31
|
+
:name => reflection.name,
|
32
|
+
:class => reflection.class_name.constantize
|
33
|
+
}
|
34
|
+
ary
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def member_associations
|
40
|
+
@member_associations ||= begin
|
41
|
+
associations = []
|
42
|
+
[:belongs_to, :has_one].each do |macro|
|
43
|
+
associations += klass.reflect_on_all_associations(macro)
|
44
|
+
end
|
45
|
+
associations.inject([]) do |ary, reflection|
|
46
|
+
ary << {
|
47
|
+
:name => reflection.name,
|
48
|
+
:class => reflection.class_name.constantize
|
49
|
+
}
|
50
|
+
ary
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
9
55
|
def destroy_all
|
10
56
|
klass.destroy_all
|
11
57
|
end
|
@@ -17,8 +63,23 @@ module ActiveRecord
|
|
17
63
|
def find_many(opts)
|
18
64
|
klass.find(:all,opts.to_hash.symbolize_keys)
|
19
65
|
end
|
20
|
-
end # ClassWrapper
|
21
66
|
|
67
|
+
def count(opts={})
|
68
|
+
if opts[:conditions]
|
69
|
+
klass.count(:conditions => opts[:conditions])
|
70
|
+
else
|
71
|
+
klass.count
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def sum(field, opts={})
|
76
|
+
if opts[:conditions]
|
77
|
+
klass.sum(field, :conditions => opts[:conditions])
|
78
|
+
else
|
79
|
+
klass.sum(field)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end # ClassWrapper
|
22
83
|
end
|
23
84
|
end
|
24
85
|
end
|