couchrest_model 2.1.0.rc1 → 2.2.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -1
- data/.travis.yml +15 -4
- data/Gemfile.activesupport-4.x +4 -0
- data/Gemfile.activesupport-5.x +4 -0
- data/README.md +2 -0
- data/VERSION +1 -1
- data/couchrest_model.gemspec +3 -2
- data/history.md +14 -1
- data/lib/couchrest/model/associations.rb +3 -8
- data/lib/couchrest/model/base.rb +15 -7
- data/lib/couchrest/model/casted_array.rb +22 -34
- data/lib/couchrest/model/configuration.rb +2 -0
- data/lib/couchrest/model/design.rb +4 -3
- data/lib/couchrest/model/designs/view.rb +37 -32
- data/lib/couchrest/model/dirty.rb +93 -19
- data/lib/couchrest/model/embeddable.rb +2 -14
- data/lib/couchrest/model/extended_attachments.rb +2 -4
- data/lib/couchrest/model/persistence.rb +14 -17
- data/lib/couchrest/model/properties.rb +46 -54
- data/lib/couchrest/model/property.rb +0 -3
- data/lib/couchrest/model/proxyable.rb +20 -4
- data/lib/couchrest/model/validations/uniqueness.rb +4 -1
- data/lib/couchrest_model.rb +2 -2
- data/spec/fixtures/models/article.rb +1 -1
- data/spec/fixtures/models/card.rb +2 -1
- data/spec/fixtures/models/person.rb +1 -0
- data/spec/fixtures/models/project.rb +3 -0
- data/spec/unit/assocations_spec.rb +73 -73
- data/spec/unit/attachment_spec.rb +34 -34
- data/spec/unit/base_spec.rb +102 -102
- data/spec/unit/casted_array_spec.rb +7 -7
- data/spec/unit/casted_spec.rb +7 -7
- data/spec/unit/configuration_spec.rb +11 -11
- data/spec/unit/connection_spec.rb +30 -30
- data/spec/unit/core_extensions/{time_parsing.rb → time_parsing_spec.rb} +21 -21
- data/spec/unit/design_spec.rb +38 -38
- data/spec/unit/designs/design_mapper_spec.rb +26 -26
- data/spec/unit/designs/migrations_spec.rb +13 -13
- data/spec/unit/designs/view_spec.rb +319 -274
- data/spec/unit/designs_spec.rb +39 -39
- data/spec/unit/dirty_spec.rb +188 -103
- data/spec/unit/embeddable_spec.rb +119 -117
- data/spec/unit/inherited_spec.rb +4 -4
- data/spec/unit/persistence_spec.rb +122 -122
- data/spec/unit/properties_spec.rb +466 -16
- data/spec/unit/property_protection_spec.rb +32 -32
- data/spec/unit/property_spec.rb +45 -436
- data/spec/unit/proxyable_spec.rb +140 -82
- data/spec/unit/subclass_spec.rb +14 -14
- data/spec/unit/translations_spec.rb +5 -5
- data/spec/unit/typecast_spec.rb +131 -131
- data/spec/unit/utils/migrate_spec.rb +2 -2
- data/spec/unit/validations_spec.rb +31 -31
- metadata +27 -12
- data/lib/couchrest/model/casted_hash.rb +0 -84
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dc3de5182b5c551856bd3dbbbdea62fe97feccf8
|
4
|
+
data.tar.gz: 1aac104a38f10500bcfbf6d3812442b7fa6ca677
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f5c34608cb902751b5671abc660a23203cd7f340fcc05eefc670be5859f7693bb482bf05c400fd5789abfdd09affd9379ecc6589924b5ac70805a05fc0b81421
|
7
|
+
data.tar.gz: 39b5d65f53d8cb283f86fbfa0a3d6c27edea311dede32422cce4a0225cc42f98f2ed672cd65e01f48d176cc18a031f2758bbb12011f5391f7f57800ea88bcd80
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
@@ -1,14 +1,25 @@
|
|
1
|
+
language: ruby
|
2
|
+
gemfile:
|
3
|
+
- Gemfile.activesupport-4.x
|
4
|
+
- Gemfile.activesupport-5.x
|
1
5
|
rvm:
|
2
6
|
- 2.3.0
|
3
|
-
- 2.2.
|
7
|
+
- 2.2.4
|
4
8
|
- 2.1.10
|
5
9
|
- 2.0.0
|
6
10
|
- jruby
|
11
|
+
- rbx
|
7
12
|
services: couchdb
|
8
|
-
matrix:
|
9
|
-
allow_failures:
|
10
|
-
- rvm: jruby
|
11
13
|
before_install:
|
12
14
|
- gem install bundler
|
13
15
|
env:
|
14
16
|
- JRUBY_OPTS=--2.0
|
17
|
+
matrix:
|
18
|
+
allow_failures:
|
19
|
+
- rvm: 2.0.0
|
20
|
+
gemfile: Gemfile.activesupport-5.x
|
21
|
+
- rvm: 2.1.10
|
22
|
+
gemfile: Gemfile.activesupport-5.x
|
23
|
+
- rvm: jruby
|
24
|
+
gemfile: Gemfile.activesupport-5.x
|
25
|
+
- rvm: rbx # Has problems with Array#insert inheritence
|
data/README.md
CHANGED
@@ -19,6 +19,8 @@ See the [update history](https://github.com/couchrest/couchrest_model/blob/maste
|
|
19
19
|
|
20
20
|
### Upgrading from an earlier version?
|
21
21
|
|
22
|
+
*Pre 2.2:* As of August 2016, dirty tracking has been radically re-factored away from ActiveModel::Dirty, which only has support for basic attributes, into a solution that uses [Hashdiff](https://github.com/liufengyun/hashdiff), more details available in the [pull request](https://github.com/couchrest/couchrest_model/pull/211). The result is that some of ActiveModel's Dirty methods are no longer available, these are: `changes_applied`, `restore_attributes`, `previous_changes`, and `changed_attributes`.
|
23
|
+
|
22
24
|
*Pre 2.0:* As of June 2012, couchrest model no longer supports the `view_by` and `view` calls from the model. Views are no only accessed via a design document. If you have older code and wish to upgrade, please ensure you move to the new syntax for using views.
|
23
25
|
|
24
26
|
*Pre 1.1:* As of April 2011 and the release of version 1.1.0, the default model type key is 'type' instead of 'couchrest-type'. Simply updating your project will not work unless you migrate your data or set the configuration option in your initializers:
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.
|
1
|
+
2.2.0.beta1
|
data/couchrest_model.gemspec
CHANGED
@@ -23,9 +23,10 @@ Gem::Specification.new do |s|
|
|
23
23
|
s.require_paths = ["lib"]
|
24
24
|
|
25
25
|
s.add_dependency("couchrest", "2.0.0")
|
26
|
-
s.add_dependency("activemodel", "
|
26
|
+
s.add_dependency("activemodel", ">= 4.0.2")
|
27
27
|
s.add_dependency("tzinfo", ">= 0.3.22")
|
28
|
-
s.
|
28
|
+
s.add_dependency("hashdiff", "~> 0.3")
|
29
|
+
s.add_development_dependency("rspec", "~> 3.5.0")
|
29
30
|
s.add_development_dependency("rack-test", ">= 0.5.7")
|
30
31
|
s.add_development_dependency("rake", ">= 0.8.0")
|
31
32
|
s.add_development_dependency("test-unit")
|
data/history.md
CHANGED
@@ -1,6 +1,19 @@
|
|
1
1
|
# CouchRest Model Change History
|
2
2
|
|
3
|
-
## 2.
|
3
|
+
## 2.2.0.beta1 - pending
|
4
|
+
|
5
|
+
* Radical re-factor of dirty tracking using Hashdiff gem, providing reliable change detection with nested data. ([PR](https://github.com/couchrest/couchrest_model/pull/211) @samlown)
|
6
|
+
* Implement proxy for factory methods ([PR](https://github.com/couchrest/couchrest_model/pull/210) @ellneal)
|
7
|
+
* Add view option to specify a custom emit value for views ([PR](https://github.com/couchrest/couchrest_model/pull/209) @ellneal)
|
8
|
+
* Support proxying to multiple databases ([PR](https://github.com/couchrest/couchrest_model/pull/206) @ellneal)
|
9
|
+
* Support concurrent auto design doc updates ([PR](https://github.com/couchrest/couchrest_model/pull/201) @ghempton)
|
10
|
+
* Upgrading to rspec 3.5 and adding ActiveSupport 5.X tests (@samlown)
|
11
|
+
|
12
|
+
## 2.1.0 - skipped!
|
13
|
+
|
14
|
+
* No release, moved straight to 2.2.0.
|
15
|
+
|
16
|
+
## 2.1.0.rc1 - 2016-07-06
|
4
17
|
|
5
18
|
* Adding "persistent" connection configuration property (@samlown)
|
6
19
|
* Releasing 2.1.0 off of CouchRest 2.0.0.
|
@@ -1,12 +1,8 @@
|
|
1
1
|
module CouchRest
|
2
2
|
module Model
|
3
|
+
# Basic support for relationships between CouchRest::Model::Base
|
3
4
|
module Associations
|
4
|
-
|
5
|
-
# Basic support for relationships between CouchRest::Model::Base
|
6
|
-
|
7
|
-
def self.included(base)
|
8
|
-
base.extend(ClassMethods)
|
9
|
-
end
|
5
|
+
extend ActiveSupport::Concern
|
10
6
|
|
11
7
|
module ClassMethods
|
12
8
|
|
@@ -240,8 +236,7 @@ module CouchRest
|
|
240
236
|
|
241
237
|
# Override CastedArray instantiation_and_cast method for a simpler
|
242
238
|
# version that will not try to cast the model.
|
243
|
-
def instantiate_and_cast(obj
|
244
|
-
couchrest_parent_will_change! if change && use_dirty?
|
239
|
+
def instantiate_and_cast(obj)
|
245
240
|
obj.casted_by = casted_by if obj.respond_to?(:casted_by)
|
246
241
|
obj.casted_by_property = casted_by_property if obj.respond_to?(:casted_by_property)
|
247
242
|
obj
|
data/lib/couchrest/model/base.rb
CHANGED
@@ -45,19 +45,22 @@ module CouchRest
|
|
45
45
|
#
|
46
46
|
# Options supported:
|
47
47
|
#
|
48
|
-
# * :
|
48
|
+
# * :write_all_attributes, true when data comes directly from database so we can set protected and read-only attributes.
|
49
49
|
# * :database, provide an alternative database
|
50
50
|
#
|
51
51
|
# If a block is provided the new model will be passed into the
|
52
52
|
# block so that it can be populated.
|
53
|
-
def initialize(attributes = {}, options = {})
|
53
|
+
def initialize(attributes = {}, options = {}, &block)
|
54
54
|
super()
|
55
|
-
|
56
|
-
#
|
55
|
+
|
56
|
+
# Always force the type of model
|
57
|
+
self[self.model_type_key] = self.class.model_type_value
|
58
|
+
|
59
|
+
# Some instances may require a different database
|
57
60
|
self.database = options[:database] unless options[:database].nil?
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
+
|
62
|
+
# Deal with the attributes
|
63
|
+
write_attributes_for_initialization(attributes, options)
|
61
64
|
|
62
65
|
yield self if block_given?
|
63
66
|
|
@@ -65,6 +68,11 @@ module CouchRest
|
|
65
68
|
run_callbacks(:initialize) { self }
|
66
69
|
end
|
67
70
|
|
71
|
+
def self.build(attrs = {}, options = {}, &block)
|
72
|
+
|
73
|
+
|
74
|
+
end
|
75
|
+
|
68
76
|
alias :new_record? :new?
|
69
77
|
alias :new_document? :new?
|
70
78
|
|
@@ -5,6 +5,7 @@
|
|
5
5
|
|
6
6
|
module CouchRest::Model
|
7
7
|
class CastedArray < Array
|
8
|
+
include CouchRest::Model::Configuration
|
8
9
|
include CouchRest::Model::CastedBy
|
9
10
|
include CouchRest::Model::Dirty
|
10
11
|
attr_accessor :casted_by_property
|
@@ -29,43 +30,15 @@ module CouchRest::Model
|
|
29
30
|
super(instantiate_and_cast(obj))
|
30
31
|
end
|
31
32
|
|
32
|
-
def []=
|
33
|
-
|
34
|
-
couchrest_parent_will_change! if use_dirty? && value != self[index]
|
35
|
-
super(index, value)
|
33
|
+
def []=(index, obj)
|
34
|
+
super(index, instantiate_and_cast(obj))
|
36
35
|
end
|
37
36
|
|
38
|
-
def insert
|
39
|
-
values =
|
40
|
-
couchrest_parent_will_change! if use_dirty?
|
37
|
+
def insert(index, *args)
|
38
|
+
values = args.map{|obj| instantiate_and_cast(obj)}
|
41
39
|
super(index, *values)
|
42
40
|
end
|
43
41
|
|
44
|
-
def pop
|
45
|
-
couchrest_parent_will_change! if use_dirty? && self.length > 0
|
46
|
-
super
|
47
|
-
end
|
48
|
-
|
49
|
-
def shift
|
50
|
-
couchrest_parent_will_change! if use_dirty? && self.length > 0
|
51
|
-
super
|
52
|
-
end
|
53
|
-
|
54
|
-
def clear
|
55
|
-
couchrest_parent_will_change! if use_dirty? && self.length > 0
|
56
|
-
super
|
57
|
-
end
|
58
|
-
|
59
|
-
def delete(obj)
|
60
|
-
couchrest_parent_will_change! if use_dirty? && self.length > 0
|
61
|
-
super(obj)
|
62
|
-
end
|
63
|
-
|
64
|
-
def delete_at(index)
|
65
|
-
couchrest_parent_will_change! if use_dirty? && self.length > 0
|
66
|
-
super(index)
|
67
|
-
end
|
68
|
-
|
69
42
|
def build(*args)
|
70
43
|
obj = casted_by_property.build(*args)
|
71
44
|
self.push(obj)
|
@@ -76,11 +49,26 @@ module CouchRest::Model
|
|
76
49
|
map{ |v| (v.respond_to?(:as_couch_json) ? v.as_couch_json : v)}
|
77
50
|
end
|
78
51
|
|
52
|
+
# Overwrite the standard dirty tracking clearing.
|
53
|
+
# We don't have any properties, but we do need to check
|
54
|
+
# entries in our array.
|
55
|
+
def clear_changes_information
|
56
|
+
if use_dirty?
|
57
|
+
each do |val|
|
58
|
+
if val.respond_to?(:clear_changes_information)
|
59
|
+
val.clear_changes_information
|
60
|
+
end
|
61
|
+
end
|
62
|
+
@original_change_data = current_change_data
|
63
|
+
else
|
64
|
+
@original_change_data = nil
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
79
68
|
protected
|
80
69
|
|
81
|
-
def instantiate_and_cast(obj
|
70
|
+
def instantiate_and_cast(obj)
|
82
71
|
property = casted_by_property
|
83
|
-
couchrest_parent_will_change! if change && use_dirty?
|
84
72
|
if casted_by && property && obj.class != property.type
|
85
73
|
property.cast_value(casted_by, obj)
|
86
74
|
else
|
@@ -15,12 +15,14 @@ module CouchRest
|
|
15
15
|
add_config :connection
|
16
16
|
add_config :connection_config_file
|
17
17
|
add_config :time_fraction_digits
|
18
|
+
add_config :disable_dirty_tracking
|
18
19
|
|
19
20
|
configure do |config|
|
20
21
|
config.model_type_key = 'type' # was 'couchrest-type'
|
21
22
|
config.mass_assign_any_attribute = false
|
22
23
|
config.auto_update_design_doc = true
|
23
24
|
config.time_fraction_digits = 3
|
25
|
+
config.disable_dirty_tracking = false
|
24
26
|
|
25
27
|
config.environment = :development
|
26
28
|
config.connection_config_file = File.join(Dir.pwd, 'config', 'couchdb.yml')
|
@@ -17,6 +17,7 @@ module CouchRest
|
|
17
17
|
def initialize(model, prefix = nil)
|
18
18
|
self.model = model
|
19
19
|
self.method_name = self.class.method_name(prefix)
|
20
|
+
@lock = Mutex.new
|
20
21
|
suffix = prefix ? "_#{prefix}" : ''
|
21
22
|
self["_id"] = "_design/#{model.to_s}#{suffix}"
|
22
23
|
apply_defaults
|
@@ -26,7 +27,8 @@ module CouchRest
|
|
26
27
|
if auto_update
|
27
28
|
db ||= database
|
28
29
|
if cache_checksum(db) != checksum
|
29
|
-
|
30
|
+
# Only allow one thread to update the design document at a time
|
31
|
+
@lock.synchronize { sync!(db) }
|
30
32
|
set_cache_checksum(db, checksum)
|
31
33
|
end
|
32
34
|
end
|
@@ -39,6 +41,7 @@ module CouchRest
|
|
39
41
|
# Load up the last copy. We never blindly overwrite the remote copy
|
40
42
|
# as it may contain views that are not used or known about by
|
41
43
|
# our model.
|
44
|
+
|
42
45
|
doc = load_from_database(db)
|
43
46
|
|
44
47
|
if !doc || doc['couchrest-hash'] != checksum
|
@@ -181,5 +184,3 @@ module CouchRest
|
|
181
184
|
end
|
182
185
|
end
|
183
186
|
end
|
184
|
-
|
185
|
-
|
@@ -5,10 +5,10 @@ module CouchRest
|
|
5
5
|
#
|
6
6
|
# A proxy class that allows view queries to be created using
|
7
7
|
# chained method calls. After each call a new instance of the method
|
8
|
-
# is created based on the original in a similar fashion to ruby's Sequel
|
8
|
+
# is created based on the original in a similar fashion to ruby's Sequel
|
9
9
|
# library, or Rails 3's Arel.
|
10
10
|
#
|
11
|
-
# CouchDB views have inherent limitations, so joins and filters as used in
|
11
|
+
# CouchDB views have inherent limitations, so joins and filters as used in
|
12
12
|
# a normal relational database are not possible.
|
13
13
|
#
|
14
14
|
class View
|
@@ -52,7 +52,7 @@ module CouchRest
|
|
52
52
|
# == View Execution Methods
|
53
53
|
#
|
54
54
|
# Request to the CouchDB database using the current query values.
|
55
|
-
|
55
|
+
|
56
56
|
# Return each row wrapped in a ViewRow object. Unlike the raw
|
57
57
|
# CouchDB request, this will provide an empty array if there
|
58
58
|
# are no results.
|
@@ -65,7 +65,7 @@ module CouchRest
|
|
65
65
|
else
|
66
66
|
if execute && result['rows']
|
67
67
|
@rows ||= result['rows'].map{|v| ViewRow.new(v, model, use_database)}
|
68
|
-
else
|
68
|
+
else
|
69
69
|
[ ]
|
70
70
|
end
|
71
71
|
end
|
@@ -81,7 +81,7 @@ module CouchRest
|
|
81
81
|
end
|
82
82
|
|
83
83
|
# Provide all the documents from the view. If the view has not been
|
84
|
-
# prepared with the +include_docs+ option, each document will be
|
84
|
+
# prepared with the +include_docs+ option, each document will be
|
85
85
|
# loaded individually.
|
86
86
|
def docs
|
87
87
|
if block_given?
|
@@ -93,17 +93,17 @@ module CouchRest
|
|
93
93
|
end
|
94
94
|
end
|
95
95
|
|
96
|
-
# If another request has been made on the view, this will return
|
96
|
+
# If another request has been made on the view, this will return
|
97
97
|
# the first document in the set. If not, a new query object will be
|
98
|
-
# generated with a limit of 1 so that only the first document is
|
98
|
+
# generated with a limit of 1 so that only the first document is
|
99
99
|
# loaded.
|
100
100
|
def first
|
101
101
|
result ? all.first : limit(1).all.first
|
102
102
|
end
|
103
103
|
|
104
104
|
# Same as first but will order the view in descending order. This
|
105
|
-
# does not however reverse the search keys or the offset, so if you
|
106
|
-
# are using a +startkey+ and +endkey+ you might end up with
|
105
|
+
# does not however reverse the search keys or the offset, so if you
|
106
|
+
# are using a +startkey+ and +endkey+ you might end up with
|
107
107
|
# unexpected results.
|
108
108
|
#
|
109
109
|
# If in doubt, don't use this method!
|
@@ -127,7 +127,7 @@ module CouchRest
|
|
127
127
|
#
|
128
128
|
# Trying to use this method with the group option will raise an error.
|
129
129
|
#
|
130
|
-
# If no reduce function is defined, a query will be performed
|
130
|
+
# If no reduce function is defined, a query will be performed
|
131
131
|
# to return the total number of rows, this is the equivalant of:
|
132
132
|
#
|
133
133
|
# view.limit(0).total_rows
|
@@ -142,7 +142,7 @@ module CouchRest
|
|
142
142
|
end
|
143
143
|
end
|
144
144
|
|
145
|
-
# Check to see if the array of documents is empty. This *will*
|
145
|
+
# Check to see if the array of documents is empty. This *will*
|
146
146
|
# perform the query and return all documents ready to use, if you don't
|
147
147
|
# want to load anything, use +#total_rows+ or +#count+ instead.
|
148
148
|
def empty?
|
@@ -181,7 +181,7 @@ module CouchRest
|
|
181
181
|
#
|
182
182
|
# In this example, the raw option will be ignored, and the total rows
|
183
183
|
# will still be accessible.
|
184
|
-
#
|
184
|
+
#
|
185
185
|
def [](value)
|
186
186
|
execute[value]
|
187
187
|
end
|
@@ -194,8 +194,8 @@ module CouchRest
|
|
194
194
|
|
195
195
|
|
196
196
|
# == View Filter Methods
|
197
|
-
#
|
198
|
-
# View filters return a copy of the view instance with the query
|
197
|
+
#
|
198
|
+
# View filters return a copy of the view instance with the query
|
199
199
|
# modified appropriatly. Errors will be raised if the methods
|
200
200
|
# are combined in an incorrect fashion.
|
201
201
|
#
|
@@ -208,10 +208,10 @@ module CouchRest
|
|
208
208
|
update_query(:key => value)
|
209
209
|
end
|
210
210
|
|
211
|
-
# Find all index keys that start with the value provided. May or may
|
211
|
+
# Find all index keys that start with the value provided. May or may
|
212
212
|
# not be used in conjunction with the +endkey+ option.
|
213
213
|
#
|
214
|
-
# When the +#descending+ option is used (not the default), the start
|
214
|
+
# When the +#descending+ option is used (not the default), the start
|
215
215
|
# and end keys should be reversed, as per the CouchDB API.
|
216
216
|
#
|
217
217
|
# Cannot be used if the key has been set.
|
@@ -220,7 +220,7 @@ module CouchRest
|
|
220
220
|
update_query(:startkey => value)
|
221
221
|
end
|
222
222
|
|
223
|
-
# The result set should start from the position of the provided document.
|
223
|
+
# The result set should start from the position of the provided document.
|
224
224
|
# The value may be provided as an object that responds to the +#id+ call
|
225
225
|
# or a string.
|
226
226
|
def startkey_doc(value)
|
@@ -237,19 +237,19 @@ module CouchRest
|
|
237
237
|
update_query(:endkey => value)
|
238
238
|
end
|
239
239
|
|
240
|
-
# The result set should end at the position of the provided document.
|
241
|
-
# The value may be provided as an object that responds to the +#id+
|
240
|
+
# The result set should end at the position of the provided document.
|
241
|
+
# The value may be provided as an object that responds to the +#id+
|
242
242
|
# call or a string.
|
243
243
|
def endkey_doc(value)
|
244
244
|
update_query(:endkey_docid => value.is_a?(String) ? value : value.id)
|
245
245
|
end
|
246
246
|
|
247
247
|
# Keys is a special CouchDB option that will cause the view request to be POSTed
|
248
|
-
# including an array of keys. Only documents with the matching keys will be
|
249
|
-
# returned. This is much faster than sending multiple requests for a set
|
248
|
+
# including an array of keys. Only documents with the matching keys will be
|
249
|
+
# returned. This is much faster than sending multiple requests for a set
|
250
250
|
# non-consecutive documents.
|
251
251
|
#
|
252
|
-
# If no values are provided, this method will act as a wrapper around
|
252
|
+
# If no values are provided, this method will act as a wrapper around
|
253
253
|
# the rows result set, providing an array of keys.
|
254
254
|
def keys(*keys)
|
255
255
|
if keys.empty?
|
@@ -302,16 +302,16 @@ module CouchRest
|
|
302
302
|
# Control whether the reduce function reduces to a set of distinct keys
|
303
303
|
# or to a single result row.
|
304
304
|
#
|
305
|
-
# By default the value is false, and can only be set when the view's
|
305
|
+
# By default the value is false, and can only be set when the view's
|
306
306
|
# +#reduce+ option has been set.
|
307
307
|
def group
|
308
308
|
raise "View#reduce must have been set before grouping is permitted" unless query[:reduce]
|
309
309
|
update_query(:group => true)
|
310
310
|
end
|
311
311
|
|
312
|
-
# Will set the level the grouping should be performed to. As per the
|
312
|
+
# Will set the level the grouping should be performed to. As per the
|
313
313
|
# CouchDB API, it only makes sense when the index key is an array.
|
314
|
-
#
|
314
|
+
#
|
315
315
|
# This will automatically set the group option.
|
316
316
|
def group_level(value)
|
317
317
|
group.update_query(:group_level => value.to_i)
|
@@ -325,7 +325,7 @@ module CouchRest
|
|
325
325
|
|
326
326
|
# Allow the results of a query to be provided "stale". Setting to 'ok'
|
327
327
|
# will disable all view updates for the query.
|
328
|
-
# When 'update_after' is provided the index will be update after the
|
328
|
+
# When 'update_after' is provided the index will be update after the
|
329
329
|
# result has been returned.
|
330
330
|
def stale(value)
|
331
331
|
unless (['ok', 'update_after'].include?(value.to_s))
|
@@ -445,17 +445,17 @@ module CouchRest
|
|
445
445
|
create_model_methods(design_doc, name, opts)
|
446
446
|
end
|
447
447
|
|
448
|
-
# Simplified view definition. A new view will be added to the
|
448
|
+
# Simplified view definition. A new view will be added to the
|
449
449
|
# provided design document using the name and options.
|
450
450
|
#
|
451
|
-
# If the view name starts with "by_" and +:by+ is not provided in
|
451
|
+
# If the view name starts with "by_" and +:by+ is not provided in
|
452
452
|
# the options, the new view's map method will be interpreted and
|
453
453
|
# generated automatically. For example:
|
454
454
|
#
|
455
455
|
# View.define(Meeting, design, "by_date_and_name")
|
456
456
|
#
|
457
|
-
# Will create a view that searches by the date and name properties.
|
458
|
-
# Explicity setting the attributes to use is possible using the
|
457
|
+
# Will create a view that searches by the date and name properties.
|
458
|
+
# Explicity setting the attributes to use is possible using the
|
459
459
|
# +:by+ option. For example:
|
460
460
|
#
|
461
461
|
# View.define(Meeting, design, "by_date_and_name", :by => [:date, :firstname, :lastname])
|
@@ -491,18 +491,23 @@ module CouchRest
|
|
491
491
|
end
|
492
492
|
raise "View cannot be created without recognised name, :map or :by options" if opts[:by].nil?
|
493
493
|
|
494
|
+
# convert emit symbols to properties
|
495
|
+
opts[:emit] = "doc['#{opts[:emit]}']" if opts[:emit].is_a?(Symbol)
|
496
|
+
opts[:emit] = "[" + opts[:emit].map { |i| i.is_a?(Symbol) ? "doc['#{i}']" : i }.join(', ') + "]" if opts[:emit].is_a?(Array)
|
497
|
+
|
494
498
|
opts[:allow_blank] = opts[:allow_blank].nil? ? true : opts[:allow_blank]
|
495
499
|
opts[:guards] ||= []
|
496
500
|
opts[:guards].push "(doc['#{model.model_type_key}'] == '#{model.model_type_value}')"
|
497
501
|
|
498
502
|
keys = opts[:by].map{|o| "doc['#{o}']"}
|
499
|
-
|
503
|
+
emit_keys = keys.length == 1 ? keys.first : "[#{keys.join(', ')}]"
|
504
|
+
emit_value = opts[:emit] || 1;
|
500
505
|
opts[:guards] += keys.map{|k| "(#{k} != null)"} unless opts[:allow_nil]
|
501
506
|
opts[:guards] += keys.map{|k| "(#{k} != '')"} unless opts[:allow_blank]
|
502
507
|
opts[:map] = <<-EOF
|
503
508
|
function(doc) {
|
504
509
|
if (#{opts[:guards].join(' && ')}) {
|
505
|
-
emit(#{
|
510
|
+
emit(#{emit_keys}, #{emit_value});
|
506
511
|
}
|
507
512
|
}
|
508
513
|
EOF
|