couchrest_model 1.0.0.beta8 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. data/.gitignore +9 -0
  2. data/{spec/spec.opts → .rspec} +0 -1
  3. data/Gemfile +4 -0
  4. data/Gemfile.lock +77 -0
  5. data/README.md +144 -57
  6. data/Rakefile +12 -43
  7. data/VERSION +1 -0
  8. data/couchrest_model.gemspec +35 -0
  9. data/history.txt +23 -1
  10. data/init.rb +1 -0
  11. data/lib/couchrest/model/associations.rb +17 -1
  12. data/lib/couchrest/model/base.rb +5 -5
  13. data/lib/couchrest/model/casted_model.rb +2 -2
  14. data/lib/couchrest/model/class_proxy.rb +6 -0
  15. data/lib/couchrest/model/collection.rb +3 -0
  16. data/lib/couchrest/model/configuration.rb +51 -0
  17. data/lib/couchrest/model/design_doc.rb +2 -5
  18. data/lib/couchrest/model/document_queries.rb +20 -3
  19. data/lib/couchrest/model/persistence.rb +15 -1
  20. data/lib/couchrest/model/properties.rb +97 -23
  21. data/lib/couchrest/model/property.rb +5 -4
  22. data/lib/couchrest/model/property_protection.rb +71 -0
  23. data/lib/couchrest/model/typecast.rb +12 -7
  24. data/lib/couchrest/model/view.rb +190 -0
  25. data/lib/couchrest/model/views.rb +3 -3
  26. data/lib/couchrest/model.rb +1 -1
  27. data/lib/couchrest/railtie.rb +3 -2
  28. data/lib/couchrest_model.rb +7 -14
  29. data/lib/rails/generators/couchrest_model/model/model_generator.rb +2 -1
  30. data/spec/.gitignore +1 -0
  31. data/spec/couchrest/base_spec.rb +3 -3
  32. data/spec/couchrest/casted_model_spec.rb +63 -49
  33. data/spec/couchrest/class_proxy_spec.rb +6 -0
  34. data/spec/couchrest/configuration_spec.rb +78 -0
  35. data/spec/couchrest/persistence_spec.rb +10 -4
  36. data/spec/couchrest/{attribute_protection_spec.rb → property_protection_spec.rb} +29 -2
  37. data/spec/couchrest/property_spec.rb +61 -0
  38. data/spec/couchrest/subclass_spec.rb +2 -2
  39. data/spec/couchrest/view_spec.rb +6 -0
  40. data/spec/fixtures/more/article.rb +1 -1
  41. data/spec/spec_helper.rb +4 -3
  42. metadata +96 -32
  43. data/lib/couchrest/model/attribute_protection.rb +0 -74
  44. data/lib/couchrest/model/attributes.rb +0 -75
@@ -0,0 +1,190 @@
1
+
2
+ #### NOTE Work in progress! Not yet used!
3
+
4
+ module CouchRest
5
+ module Model
6
+
7
+ # A proxy class that allows view queries to be created using
8
+ # chained method calls. After each call a new instance of the method
9
+ # is created based on the original in a similar fashion to ruby's sequel
10
+ # library, or Rails 3's Arel.
11
+ #
12
+ # CouchDB views have inherent limitations, so joins and filters as used in
13
+ # a normal relational database are not possible. At least not yet!
14
+ #
15
+ #
16
+ #
17
+ class View
18
+
19
+ attr_accessor :query, :design, :database, :name
20
+
21
+ # Initialize a new View object. This method should not be called from outside CouchRest Model.
22
+ def initialize(parent, new_query = {}, name = nil)
23
+ if parent.is_a? Base
24
+ raise "Name must be provided for view to be initialized" if name.nil?
25
+ @name = name
26
+ @database = parent.database
27
+ @query = { :reduce => false }
28
+ elsif parent.is_a? View
29
+ @database = parent.database
30
+ @query = parent.query.dup
31
+ else
32
+ raise "View cannot be initialized without a parent Model or View"
33
+ end
34
+ @query.update(new_query)
35
+ super
36
+ end
37
+
38
+
39
+ # == View Execution Methods
40
+ #
41
+ # Send a request to the CouchDB database using the current query values.
42
+
43
+ # Inmediatly send a request to the database for all documents provided by the query.
44
+ #
45
+ def all(&block)
46
+ args = include_docs.query
47
+
48
+ end
49
+
50
+ # Inmediatly send a request for the first result of the dataset. This will override
51
+ # any limit set in the view previously.
52
+ def first(&block)
53
+ args = limit(1).include_docs.query
54
+
55
+ end
56
+
57
+ def info
58
+
59
+ end
60
+
61
+ def offset
62
+
63
+ end
64
+
65
+ def total_rows
66
+
67
+ end
68
+
69
+ def rows
70
+
71
+ end
72
+
73
+
74
+ # == View Filter Methods
75
+ #
76
+ # View filters return an copy of the view instance with the query
77
+ # modified appropriatly. Errors will be raised if the methods
78
+ # are combined in an incorrect fashion.
79
+ #
80
+
81
+
82
+ # Find all entries in the index whose key matches the value provided.
83
+ #
84
+ # Cannot be used when the +#startkey+ or +#endkey+ have been set.
85
+ def key(value)
86
+ raise "View#key cannot be used when startkey or endkey have been set" unless query[:startkey].nil? && query[:endkey].nil?
87
+ update_query(:key => value)
88
+ end
89
+
90
+ # Find all index keys that start with the value provided. May or may not be used in
91
+ # conjunction with the +endkey+ option.
92
+ #
93
+ # When the +#descending+ option is used (not the default), the start and end keys should
94
+ # be reversed.
95
+ #
96
+ # Cannot be used if the key has been set.
97
+ def startkey(value)
98
+ raise "View#startkey cannot be used when key has been set" unless query[:key].nil?
99
+ update_query(:startkey => value)
100
+ end
101
+
102
+ # The result set should start from the position of the provided document.
103
+ # The value may be provided as an object that responds to the +#id+ call
104
+ # or a string.
105
+ def startkey_doc(value)
106
+ update_query(:startkey_docid => value.is_a?(String) ? value : value.id
107
+ end
108
+
109
+ # The opposite of +#startkey+, finds all index entries whose key is before the value specified.
110
+ #
111
+ # See the +#startkey+ method for more details and the +#inclusive_end+ option.
112
+ def endkey(value)
113
+ raise "View#endkey cannot be used when key has been set" unless query[:key].nil?
114
+ update_query(:endkey => value)
115
+ end
116
+
117
+ # The result set should end at the position of the provided document.
118
+ # The value may be provided as an object that responds to the +#id+ call
119
+ # or a string.
120
+ def endkey_doc(value)
121
+ update_query(:endkey_docid => value.is_a?(String) ? value : value.id
122
+ end
123
+
124
+
125
+ # The results should be provided in descending order.
126
+ #
127
+ # Descending is false by default, this method will enable it and cannot be undone.
128
+ def descending
129
+ update_query(:descending => true)
130
+ end
131
+
132
+ # Limit the result set to the value supplied.
133
+ def limit(value)
134
+ update_query(:limit => value)
135
+ end
136
+
137
+ # Skip the number of entries in the index specified by value. This would be
138
+ # the equivilent of an offset in SQL.
139
+ #
140
+ # The CouchDB documentation states that the skip option should not be used
141
+ # with large data sets as it is inefficient. Use the +startkey_doc+ method
142
+ # instead to skip ranges efficiently.
143
+ def skip(value = 0)
144
+ update_query(:skip => value)
145
+ end
146
+
147
+ # Use the reduce function on the view. If none is available this method will fail.
148
+ def reduce
149
+ update_query(:reduce => true)
150
+ end
151
+
152
+ # Control whether the reduce function reduces to a set of distinct keys or to a single
153
+ # result row.
154
+ #
155
+ # By default the value is false, and can only be set when the view's +#reduce+ option
156
+ # has been set.
157
+ def group
158
+ raise "View#reduce must have been set before grouping is permitted" unless query[:reduce]
159
+ update_query(:group => true)
160
+ end
161
+
162
+ def group_level(value)
163
+ raise "View#reduce and View#group must have been set before group_level is called" unless query[:reduce] && query[:group]
164
+ update_query(:group_level => value.to_i)
165
+ end
166
+
167
+
168
+ protected
169
+
170
+ def update_query(new_query = {})
171
+ self.class.new(self, new_query)
172
+ end
173
+
174
+ # Used internally to ensure that docs are provided. Should not be used outside of
175
+ # the view class under normal circumstances.
176
+ def include_docs
177
+ raise "Documents cannot be returned from a view that is prepared for a reduce" if query[:reduce]
178
+ update_query(:include_docs => true)
179
+ end
180
+
181
+
182
+ def execute(&block)
183
+
184
+
185
+ end
186
+
187
+
188
+ end
189
+ end
190
+ end
@@ -23,7 +23,7 @@ module CouchRest
23
23
  # view_by :tags,
24
24
  # :map =>
25
25
  # "function(doc) {
26
- # if (doc['couchrest-type'] == 'Post' && doc.tags) {
26
+ # if (doc['model'] == 'Post' && doc.tags) {
27
27
  # doc.tags.forEach(function(tag){
28
28
  # emit(doc.tag, 1);
29
29
  # });
@@ -39,7 +39,7 @@ module CouchRest
39
39
  # function:
40
40
  #
41
41
  # function(doc) {
42
- # if (doc['couchrest-type'] == 'Post' && doc.date) {
42
+ # if (doc['model'] == 'Post' && doc.date) {
43
43
  # emit(doc.date, null);
44
44
  # }
45
45
  # }
@@ -77,7 +77,7 @@ module CouchRest
77
77
  ducktype = opts.delete(:ducktype)
78
78
  unless ducktype || opts[:map]
79
79
  opts[:guards] ||= []
80
- opts[:guards].push "(doc['couchrest-type'] == '#{self.to_s}')"
80
+ opts[:guards].push "(doc['#{model_type_key}'] == '#{self.to_s}')"
81
81
  end
82
82
  keys.push opts
83
83
  design_doc.view_by(*keys)
@@ -3,7 +3,7 @@ module CouchRest
3
3
 
4
4
  module Model
5
5
 
6
- VERSION = "1.0.0.beta8"
6
+ VERSION = File.read(File.expand_path('../../../VERSION', __FILE__)).strip
7
7
 
8
8
  end
9
9
 
@@ -4,8 +4,9 @@ require "active_model/railtie"
4
4
  module CouchrestModel
5
5
  # = Active Record Railtie
6
6
  class Railtie < Rails::Railtie
7
- config.generators.orm :couchrest
7
+ config.generators.orm :couchrest_model
8
+ config.generators.test_framework :test_unit, :fixture => false
8
9
  end
9
10
 
10
11
  end
11
-
12
+
@@ -1,13 +1,3 @@
1
- gem 'couchrest', ">= 1.0.0.beta"
2
- require 'couchrest'
3
-
4
- gem "tzinfo", ">= 0.3.22"
5
-
6
- gem "activesupport", ">= 2.3.5"
7
- require 'active_support/core_ext'
8
- require 'active_support/json'
9
-
10
- gem "activemodel", ">= 3.0.0.beta4"
11
1
  require 'active_model'
12
2
  require "active_model/callbacks"
13
3
  require "active_model/conversion"
@@ -19,7 +9,9 @@ require "active_model/translation"
19
9
  require "active_model/validator"
20
10
  require "active_model/validations"
21
11
 
22
- gem "mime-types", ">= 1.15"
12
+ require 'active_support/core_ext'
13
+ require 'active_support/json'
14
+
23
15
  require 'mime/types'
24
16
  require "enumerator"
25
17
  require "time"
@@ -28,11 +20,14 @@ require 'digest/md5'
28
20
  require 'bigdecimal' # used in typecast
29
21
  require 'bigdecimal/util' # used in typecast
30
22
 
23
+ require 'couchrest'
24
+
31
25
  require 'couchrest/model'
32
26
  require 'couchrest/model/errors'
33
27
  require "couchrest/model/persistence"
34
28
  require "couchrest/model/typecast"
35
29
  require "couchrest/model/property"
30
+ require "couchrest/model/property_protection"
36
31
  require "couchrest/model/casted_array"
37
32
  require "couchrest/model/properties"
38
33
  require "couchrest/model/validations"
@@ -43,9 +38,8 @@ require "couchrest/model/design_doc"
43
38
  require "couchrest/model/extended_attachments"
44
39
  require "couchrest/model/class_proxy"
45
40
  require "couchrest/model/collection"
46
- require "couchrest/model/attribute_protection"
47
- require "couchrest/model/attributes"
48
41
  require "couchrest/model/associations"
42
+ require "couchrest/model/configuration"
49
43
 
50
44
  # Monkey patches applied to couchrest
51
45
  require "couchrest/model/support/couchrest"
@@ -58,4 +52,3 @@ require "couchrest/model/base"
58
52
  # Add rails support *after* everything has loaded
59
53
 
60
54
  require "couchrest/railtie"
61
-
@@ -3,7 +3,6 @@ require 'rails/generators/couchrest_model'
3
3
  module CouchrestModel
4
4
  module Generators
5
5
  class ModelGenerator < Base
6
-
7
6
  check_class_collision
8
7
 
9
8
  def create_model_file
@@ -14,6 +13,8 @@ module CouchrestModel
14
13
  return if class_path.empty?
15
14
  template 'module.rb', File.join('app/models', "#{class_path.join('/')}.rb") if behavior == :invoke
16
15
  end
16
+
17
+ hook_for :test_framework
17
18
 
18
19
  protected
19
20
 
data/spec/.gitignore ADDED
@@ -0,0 +1 @@
1
+ tmp
@@ -36,7 +36,7 @@ describe "Model Base" do
36
36
 
37
37
  it "should not failed on a nil value in argument" do
38
38
  @obj = Basic.new(nil)
39
- @obj.should == { 'couchrest-type' => 'Basic' }
39
+ @obj.should_not be_nil
40
40
  end
41
41
  end
42
42
 
@@ -210,7 +210,7 @@ describe "Model Base" do
210
210
 
211
211
  describe "a doc with template values (CR::Model spec)" do
212
212
  before(:all) do
213
- WithTemplateAndUniqueID.all.map{|o| o.destroy(true)}
213
+ WithTemplateAndUniqueID.all.map{|o| o.destroy}
214
214
  WithTemplateAndUniqueID.database.bulk_delete
215
215
  @tmpl = WithTemplateAndUniqueID.new
216
216
  @tmpl2 = WithTemplateAndUniqueID.new(:preset => 'not_value', 'important-field' => '1')
@@ -233,7 +233,7 @@ describe "Model Base" do
233
233
  describe "finding all instances of a model" do
234
234
  before(:all) do
235
235
  WithTemplateAndUniqueID.req_design_doc_refresh
236
- WithTemplateAndUniqueID.all.map{|o| o.destroy(true)}
236
+ WithTemplateAndUniqueID.all.map{|o| o.destroy}
237
237
  WithTemplateAndUniqueID.database.bulk_delete
238
238
  WithTemplateAndUniqueID.new('important-field' => '1').save
239
239
  WithTemplateAndUniqueID.new('important-field' => '2').save