veneer 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. data/.document +5 -0
  2. data/.gitignore +5 -0
  3. data/LICENSE +20 -0
  4. data/README.textile +138 -0
  5. data/Rakefile +64 -0
  6. data/VERSION +1 -0
  7. data/datamapper_setup.rb +2 -0
  8. data/lib/veneer.rb +35 -0
  9. data/lib/veneer/adapters/activerecord.rb +2 -0
  10. data/lib/veneer/adapters/activerecord/class_wrapper.rb +90 -0
  11. data/lib/veneer/adapters/activerecord/instance_wrapper.rb +11 -0
  12. data/lib/veneer/adapters/datamapper.rb +2 -0
  13. data/lib/veneer/adapters/datamapper/class_wrapper.rb +54 -0
  14. data/lib/veneer/adapters/datamapper/instance_wrapper.rb +23 -0
  15. data/lib/veneer/base/class_wrapper.rb +53 -0
  16. data/lib/veneer/base/conditional.rb +77 -0
  17. data/lib/veneer/base/instance_wrapper.rb +38 -0
  18. data/lib/veneer/core_ext/kernel.rb +17 -0
  19. data/lib/veneer/errors.rb +9 -0
  20. data/lib/veneer/proxy.rb +4 -0
  21. data/test/macros/class_wrapper/create_macro.rb +54 -0
  22. data/test/macros/class_wrapper/delete_macro.rb +31 -0
  23. data/test/macros/class_wrapper/find_macro.rb +112 -0
  24. data/test/macros/instance_wrapper/destroy_macro.rb +36 -0
  25. data/test/macros/instance_wrapper/new_record_macro.rb +35 -0
  26. data/test/macros/instance_wrapper/save_macro.rb +55 -0
  27. data/test/macros/veneer_constants_interface.rb +26 -0
  28. data/test/support/helpers.rb +18 -0
  29. data/test/test_helper.rb +16 -0
  30. data/test/veneer/adapters/active_record/active_record_setup.rb +28 -0
  31. data/test/veneer/adapters/active_record/class_wrapper_test.rb +21 -0
  32. data/test/veneer/adapters/active_record/instance_wrapper_test.rb +21 -0
  33. data/test/veneer/adapters/datamapper/class_wrapper_test.rb +22 -0
  34. data/test/veneer/adapters/datamapper/datamapper_setup.rb +25 -0
  35. data/test/veneer/adapters/datamapper/instance_wrapper_test.rb +21 -0
  36. data/test/veneer/base/conditonal_test.rb +118 -0
  37. data/test/veneer/proxy_test.rb +190 -0
  38. data/veneer.gemspec +95 -0
  39. metadata +109 -0
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
@@ -0,0 +1,5 @@
1
+ *.sw?
2
+ .DS_Store
3
+ coverage
4
+ rdoc
5
+ pkg
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Daniel Neighman
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,138 @@
1
+ h1. veneer
2
+
3
+ Veneer is an interface that sits above Data Sources.
4
+ It differs from ActiveModel in that it doesn't require errors or validations or anything like that.
5
+ Veneer instead aims to provide a simple interface for
6
+ * querying
7
+ * creating
8
+ * saving
9
+ * deleting
10
+
11
+ h2. Creating and Saving an instance
12
+
13
+ To create an instance of an object wrap the class in a vaneer call and create or get a new instance.
14
+
15
+ <pre><code>obj = Veneer(MyModel).new(:some => "attribute")
16
+ obj.save
17
+
18
+ # OR
19
+
20
+ obj = Veneer(MyModel).create(:some => "attribute")
21
+ </code></pre>
22
+
23
+ There are also version that will raise exceptions
24
+
25
+ <pre><code>obj = Veneer(MyModel).new(:some => "attribute").save!
26
+
27
+ # OR
28
+
29
+ obj = Veneer(MyModel).create!(:some => "attribute")
30
+ </code></pre>
31
+
32
+ h2. Deleting
33
+
34
+ You can delete all the instances of a model or a single instance.
35
+
36
+ <pre><code>Veneer(MyModel).destroy_all # delete all instances
37
+
38
+ @some_veneer_model.destroy
39
+ </code></pre>
40
+
41
+ h2. Queries
42
+
43
+ Veneer lets you query models with a simple interface. Only simple queries are supported.
44
+
45
+ You can query a single object, or multiple objects.
46
+
47
+ <pre><code>Veneer(MyModel).all(:conditions => {:name => "foo"})
48
+
49
+ Veneer(MyModel).all(:conditions => {"age gte" => 18}, :limit => 5)
50
+ </code></pre>
51
+
52
+ The supported options are:
53
+
54
+ * :limit
55
+ * :offset
56
+ * :order
57
+ * :conditions
58
+
59
+ h3. Limit & Offset
60
+
61
+ The :limit option will limit the number of returned results.
62
+
63
+ The :offset option, when set to an integer x will begin the results at the xth result.
64
+
65
+ h3. Order
66
+
67
+ Ordering should be set as a string. By default, the order is decending.
68
+
69
+ The format of the string is:
70
+
71
+ <pre><code>"<field> (<directon>), <field> (direction), ..."
72
+
73
+ # eg
74
+ Veneer(MyModel).all(:order => "name, age desc")
75
+ </code></pre>
76
+
77
+ h3. Conditions
78
+
79
+ Conditions are a very simple set of conditions on the fields of the model. The for of the conditions are:
80
+
81
+ <pre><code>:conditions => {"field operator" => value}</code></pre>
82
+
83
+ The supported operators are
84
+
85
+ * eql
86
+ * not
87
+ * lt (less than)
88
+ * lte (less than or equal to)
89
+ * gt (greater than)
90
+ * gte (greater than or equal to)
91
+ * in (in an array)
92
+
93
+ By default, the operator is set to eql
94
+
95
+ <pre><code>
96
+ Veneer(MyModel).all(:conditions => {"name in" => ["fred", "barney"], "age gte" => 18})
97
+ Veneer(MyModel).first(:conditions => {:name => "fred"})
98
+ </code></pre>
99
+
100
+ The results of a query are all wrapped as Veneer instances.
101
+
102
+ h3. All Together
103
+
104
+ <pre><code>Veneer(MyModel).all(:order => "name, age asc", :limit => 5, :offset => 15, :conditions => {"name not" => "betty", "age lt" => 18})
105
+ </code></pre>
106
+
107
+ h2. Object methods
108
+
109
+ All methods that aren't found on the adapter, are passed through to the instance. So to access any attributes on the actual model instance, just call the method on it.
110
+
111
+ h2. Current Support
112
+
113
+ Veneer currently has built in support for ActiveRecord and DataMapper.
114
+
115
+ Veneer works on a VeneerInterface inner module though so you can easily impelment you're adapter without requireing it to be in the veneer repo (although pull requests are welcome)
116
+
117
+ To use DataMapper or ActiveRecord
118
+
119
+ <pre><code>
120
+ require 'veneer/adapters/activerecord'
121
+ require 'veneer/adapters/datamapper'
122
+ </code></pre>
123
+
124
+
125
+ == Note on Patches/Pull Requests
126
+
127
+ * Fork the project.
128
+ * Make your feature addition or bug fix.
129
+ * Add tests for it. This is important so I don't break it in a
130
+ future version unintentionally.
131
+ * Commit, do not mess with rakefile, version, or history.
132
+ (if you want to have your own version, that is fine but
133
+ bump version in a commit by itself I can ignore when I pull)
134
+ * Send me a pull request. Bonus points for topic branches.
135
+
136
+ == Copyright
137
+
138
+ Copyright (c) 2009 Daniel Neighman. See LICENSE for details.
@@ -0,0 +1,64 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "veneer"
8
+ gem.summary = %Q{A thin veneer over data stores}
9
+ gem.description = %Q{Veneer provides basic querying, saving, deleteing and creating of data stores.}
10
+ gem.email = "has.sox@gmail.com"
11
+ gem.homepage = "http://github.com/hassox/veneer"
12
+ gem.authors = ["Daniel Neighman"]
13
+ gem.rubyforge_project = "veneer"
14
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
15
+ end
16
+ Jeweler::RubyforgeTasks.new do |rubyforge|
17
+ rubyforge.doc_task = "rdoc"
18
+ end
19
+ rescue LoadError
20
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
21
+ end
22
+
23
+ #require 'spec/rake/spectask'
24
+ #Spec::Rake::SpecTask.new(:spec) do |spec|
25
+ # spec.libs << 'lib' << 'spec'
26
+ # spec.spec_files = FileList['spec/**/*_spec.rb']
27
+ #end
28
+ #
29
+ #Spec::Rake::SpecTask.new(:rcov) do |spec|
30
+ # spec.libs << 'lib' << 'spec'
31
+ # spec.pattern = 'spec/**/*_spec.rb'
32
+ # spec.rcov = true
33
+ #end
34
+ #
35
+ #task :spec => :check_dependencies
36
+ #
37
+ #task :default => :spec
38
+
39
+ task :default => [:test_units]
40
+ require 'rake/testtask'
41
+ desc "Run test suite."
42
+ Rake::TestTask.new("test"){ |test|
43
+ test.pattern = "test/*_test.rb"
44
+ test.verbose = true
45
+ test.warning = true
46
+ test.libs << "test"
47
+ test.test_files = FileList["test/test*.rb", "test/**/*_test.rb"]
48
+ }
49
+
50
+ task :test => :check_dependencies
51
+
52
+ require 'rake/rdoctask'
53
+ Rake::RDocTask.new do |rdoc|
54
+ if File.exist?('VERSION')
55
+ version = File.read('VERSION')
56
+ else
57
+ version = ""
58
+ end
59
+
60
+ rdoc.rdoc_dir = 'rdoc'
61
+ rdoc.title = "veneer #{version}"
62
+ rdoc.rdoc_files.include('README*')
63
+ rdoc.rdoc_files.include('lib/**/*.rb')
64
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,2 @@
1
+ require 'dm-core'
2
+
@@ -0,0 +1,35 @@
1
+ require 'active_support/core_ext/hash'
2
+ $:.unshift File.expand_path(File.join(File.dirname(__FILE__), "lib"))
3
+
4
+ require 'veneer/core_ext/kernel'
5
+
6
+ unless defined?(BasicObject)
7
+ begin
8
+ require 'blankslate'
9
+ ::BasicObject = BlankSlate
10
+ class BasicObject
11
+ def ==(other)
12
+ object_id == other.object_id
13
+ end
14
+
15
+ def equal?(other)
16
+ object_id == other.object_id
17
+ end
18
+ end
19
+ rescue => e
20
+ puts "Please install builder: gem install builder"
21
+ raise e.class, e.message, e.backtrace
22
+ end
23
+ end
24
+
25
+ module Veneer
26
+ autoload :Errors, 'veneer/errors'
27
+ autoload :Proxy, 'veneer/proxy'
28
+ autoload :Conditional, 'veneer/base/conditional'
29
+
30
+ module Base
31
+ autoload :ClassWrapper, 'veneer/base/class_wrapper'
32
+ autoload :InstanceWrapper, 'veneer/base/instance_wrapper'
33
+ end
34
+ end
35
+
@@ -0,0 +1,2 @@
1
+ require 'veneer/adapters/activerecord/class_wrapper'
2
+ require 'veneer/adapters/activerecord/instance_wrapper'
@@ -0,0 +1,90 @@
1
+ module ActiveRecord
2
+ class Base
3
+ module VeneerInterface
4
+ class ClassWrapper < Veneer::Base::ClassWrapper
5
+ def new(opts = {})
6
+ ::Kernel::Veneer(klass.new(opts))
7
+ end
8
+
9
+ def destroy_all
10
+ klass.destroy_all
11
+ end
12
+
13
+ def find_first(conditional)
14
+ opts = conditional_to_ar_opts(conditional)
15
+ klass.find(:first, opts)
16
+ end
17
+
18
+ def find_many(conditional)
19
+ opts = conditional_to_ar_opts(conditional)
20
+ klass.find(:all,opts)
21
+ end
22
+
23
+ private
24
+ def conditional_to_ar_opts(c)
25
+ opts = {}
26
+ opts[:limit] = c.limit if c.limit
27
+ opts[:offset] = c.offset if c.offset
28
+
29
+ unless c.order.blank?
30
+ opts[:order] = c.order.inject([]) do |ary, cnd|
31
+ ary << "#{cnd.field} #{cnd.direction}"
32
+ end.join(",")
33
+ end
34
+
35
+ unless c.conditions.blank?
36
+ val_array = []
37
+ cnds = c.conditions.inject([]) do |ary, cd|
38
+ case cd.operator
39
+ when :eql
40
+ if cd.value.nil?
41
+ ary << "#{cd.field} IS ?"
42
+ else
43
+ ary << "#{cd.field} = ?"
44
+ end
45
+ val_array << cd.value
46
+ when :not
47
+ if cd.value.nil?
48
+ ary << "#{cd.field} IS NOT ?"
49
+ else
50
+ ary << "#{cd.field} <> ?"
51
+ end
52
+ val_array << cd.value
53
+ when :gt
54
+ ary << "#{cd.field} > ?"
55
+ val_array << cd.value
56
+ when :gte
57
+ ary << "#{cd.field} >= ?"
58
+ val_array << cd.value
59
+ when :lt
60
+ ary << "#{cd.field} < ?"
61
+ val_array << cd.value
62
+ when :lte
63
+ ary << "#{cd.field} <= ?"
64
+ val_array << cd.value
65
+ when :in
66
+ ary << "#{cd.field} IN ( ? )"
67
+ val_array << cd.value
68
+ end
69
+ ary
70
+ end
71
+ opts[:conditions] = [cnds.join(" AND "), *val_array]
72
+ end
73
+ opts
74
+ end
75
+ end # ClassWrapper
76
+
77
+ class InstanceWrapper < Veneer::Base::InstanceWrapper
78
+ def save!
79
+ instance.save!
80
+ rescue ActiveRecord::RecordInvalid => e
81
+ raise ::Veneer::Errors::NotSaved
82
+ end
83
+
84
+ def save
85
+ instance.save
86
+ end
87
+ end # InstanceWrapper
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,11 @@
1
+ module ActiveRecord
2
+ class Base
3
+ module VeneerInterface
4
+ class InstanceWrapper < Veneer::Base::InstanceWrapper
5
+ def update(attributes = {})
6
+ instance.update_attributes(attributes)
7
+ end
8
+ end # InstanceWrapper
9
+ end # VeneerInterface
10
+ end # Base
11
+ end # ActiveRecord
@@ -0,0 +1,2 @@
1
+ require 'veneer/adapters/datamapper/class_wrapper'
2
+ require 'veneer/adapters/datamapper/instance_wrapper'
@@ -0,0 +1,54 @@
1
+ module DataMapper
2
+ module Resource
3
+ module VeneerInterface
4
+ class ClassWrapper < ::Veneer::Base::ClassWrapper
5
+ def new(opts = {})
6
+ ::Kernel.Veneer(klass.new(opts))
7
+ end
8
+
9
+ def destroy_all
10
+ klass.all.destroy
11
+ end
12
+
13
+ def find_first(conditional)
14
+ opts = opts_from_conditional_for_dm(conditional)
15
+ klass.first(opts)
16
+ end
17
+
18
+ def find_many(conditional)
19
+ opts = opts_from_conditional_for_dm(conditional)
20
+ klass.all(opts)
21
+ end
22
+
23
+ private
24
+ def opts_from_conditional_for_dm(c)
25
+ opts = {}
26
+
27
+ opts[:limit] = c.limit if c.limit
28
+ opts[:offset] = c.offset if c.offset
29
+
30
+ unless c.order.empty?
31
+ opts[:order] = c.order.inject([]) do |ary, cnd|
32
+ ary << cnd.field.send(cnd.direction)
33
+ ary
34
+ end
35
+ end
36
+
37
+ unless c.conditions.empty?
38
+ c.conditions.each do |cd|
39
+ case cd.operator
40
+ when :eql
41
+ opts[cd.field] = cd.value
42
+ when :not, :gt, :gte, :lt, :lte
43
+ opts[cd.field.send(cd.operator)] = cd.value
44
+ when :in
45
+ opts[cd.field] = ::Array.new([cd.value].flatten.compact)
46
+ end
47
+ end
48
+ end
49
+ opts
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end