couchrest_model 2.1.0.rc1 → 2.2.0.beta1
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.
- 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
|