couchrest_model 1.0.0.beta8 → 1.0.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.
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