couchrest_model 1.1.0.beta2 → 1.1.0.beta3
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -1
- data/README.md +50 -3
- data/VERSION +1 -1
- data/benchmarks/dirty.rb +118 -0
- data/couchrest_model.gemspec +1 -0
- data/history.txt +12 -0
- data/lib/couchrest/model/base.rb +15 -23
- data/lib/couchrest/model/casted_array.rb +26 -1
- data/lib/couchrest/model/casted_by.rb +23 -0
- data/lib/couchrest/model/casted_hash.rb +76 -0
- data/lib/couchrest/model/casted_model.rb +9 -6
- data/lib/couchrest/model/collection.rb +10 -1
- data/lib/couchrest/model/configuration.rb +4 -4
- data/lib/couchrest/model/design_doc.rb +65 -71
- data/lib/couchrest/model/designs/view.rb +26 -19
- data/lib/couchrest/model/designs.rb +0 -2
- data/lib/couchrest/model/dirty.rb +49 -0
- data/lib/couchrest/model/extended_attachments.rb +7 -1
- data/lib/couchrest/model/persistence.rb +15 -4
- data/lib/couchrest/model/properties.rb +50 -9
- data/lib/couchrest/model/property.rb +6 -2
- data/lib/couchrest/model/proxyable.rb +13 -19
- data/lib/couchrest/model/support/couchrest_design.rb +33 -0
- data/lib/couchrest/model/views.rb +4 -18
- data/lib/couchrest_model.rb +8 -3
- data/spec/couchrest/base_spec.rb +1 -28
- data/spec/couchrest/casted_model_spec.rb +1 -1
- data/spec/couchrest/collection_spec.rb +0 -1
- data/spec/couchrest/design_doc_spec.rb +211 -0
- data/spec/couchrest/designs/view_spec.rb +41 -17
- data/spec/couchrest/designs_spec.rb +0 -5
- data/spec/couchrest/dirty_spec.rb +355 -0
- data/spec/couchrest/property_spec.rb +5 -2
- data/spec/couchrest/proxyable_spec.rb +0 -11
- data/spec/couchrest/subclass_spec.rb +6 -16
- data/spec/couchrest/view_spec.rb +6 -50
- data/spec/fixtures/base.rb +1 -1
- data/spec/fixtures/more/card.rb +2 -2
- data/spec/spec_helper.rb +2 -0
- metadata +9 -4
- data/Gemfile.lock +0 -76
- data/lib/couchrest/model/support/couchrest.rb +0 -19
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -11,6 +11,14 @@ it is not possible to load ActiveModel into programs that do not use ActiveSuppo
|
|
11
11
|
|
12
12
|
CouchRest Model is only properly tested on CouchDB version 1.0 or newer.
|
13
13
|
|
14
|
+
*WARNING:* As of April 2011 and the release of version 1.1.0, the default model type key is 'model' instead of 'couchrest-type'. Simply updating your project will not work unless you migrate your data or set the configuration option in your initializers:
|
15
|
+
|
16
|
+
CouchRest::Model::Base.configure do |config|
|
17
|
+
config.model_type_key = 'couchrest-type'
|
18
|
+
end
|
19
|
+
|
20
|
+
This is because CouchRest Model's are not couchrest specific and may be used in any other system such as a Javascript library, the model type should reflect this.
|
21
|
+
|
14
22
|
## Install
|
15
23
|
|
16
24
|
### Gem
|
@@ -57,6 +65,7 @@ Try some of these gems that add extra funcionality to couchrest_model:
|
|
57
65
|
* [couch_photo](http://github.com/moonmaster9000/couch_photo) - attach images to documents with variations (Matt Parker)
|
58
66
|
* [copycouch](http://github.com/moonmaster9000/copycouch) - single document replication on documents (Matt Parker)
|
59
67
|
* [recloner](https://github.com/moonmaster9000/recloner) - clone documents easily (Matt Parker)
|
68
|
+
* [couchrest_localised_properties](https://github.com/samlown/couchrest_localised_properties) - Transparent support for localised properties (Sam Lown)
|
60
69
|
|
61
70
|
If you have an extension that you'd us to add to this list, please get in touch!
|
62
71
|
|
@@ -148,7 +157,7 @@ Boolean or TrueClass types will create a getter with question mark at the end:
|
|
148
157
|
|
149
158
|
@cat.awake? # true
|
150
159
|
|
151
|
-
Adding the
|
160
|
+
Adding the `:default` option will ensure the attribute always has a value.
|
152
161
|
|
153
162
|
A read-only property will only have a getter method, and its value is set when the document
|
154
163
|
is read from the database. You can however update a read-only attribute using the `write_attribute` method:
|
@@ -378,6 +387,43 @@ Use pagination as follows:
|
|
378
387
|
# In your view, with the kaminari gem loaded:
|
379
388
|
paginate @posts
|
380
389
|
|
390
|
+
### Design Documents and Views
|
391
|
+
|
392
|
+
Views must be defined in a Design Document for CouchDB to be able to perform searches. Each model therefore must have its own Design Document. Deciding when to update the model's design doc is a difficult issue, as in production you don't want to be constantly checking for updates and in development maximum flexability is important. CouchRest Model solves this issue by providing the `auto_update_design_doc` configuration option and is true by default.
|
393
|
+
|
394
|
+
Each time a view or other design method is requested a quick GET for the design will be sent to ensure it is up to date with the latest changes. Results are cached in the current thread for the complete design document's URL, including the database, to try and limit requests. This should be fine for most projects, but dealing with multiple sub-databases may require a different strategy.
|
395
|
+
|
396
|
+
Setting the option to false will require a manual update of each model's design doc whenever you know a change has happened. This will be useful in cases when you do not want CouchRest Model to interfere with the views already store in the CouchRest database, or you'd like to deploy your own update strategy. Here's an example of a module that will update all submodules:
|
397
|
+
|
398
|
+
module CouchRestMigration
|
399
|
+
def self.update_design_docs
|
400
|
+
CouchRest::Model::Base.subclasses.each{|klass| klass.save_design_doc! if klass.respond_to?(:save_design_doc!)}
|
401
|
+
end
|
402
|
+
end
|
403
|
+
|
404
|
+
# Running this from your applications initializers would be a good idea,
|
405
|
+
# for example in Rail's application.rb or environments/production.rb:
|
406
|
+
config.after_initialize do
|
407
|
+
CouchRestMigration.update_design_docs
|
408
|
+
end
|
409
|
+
|
410
|
+
If you're dealing with multiple databases, using proxied models, or databases that are created on-the-fly, a more sophisticated approach might be required:
|
411
|
+
|
412
|
+
module CouchRestMigration
|
413
|
+
def self.update_all_design_docs
|
414
|
+
update_design_docs(COUCHREST_DATABASE)
|
415
|
+
Company.all.each do |company|
|
416
|
+
update_design_docs(company.proxy_database)
|
417
|
+
end
|
418
|
+
end
|
419
|
+
def self.update_design_docs(db)
|
420
|
+
CouchRest::Model::Base.subclasses.each{|klass| klass.save_design_doc!(db) if klass.respond_to?(:save_design_doc!}
|
421
|
+
end
|
422
|
+
end
|
423
|
+
|
424
|
+
# Command to run after a capistrano migration:
|
425
|
+
$ rails runner "CouchRestMigratin.update_all_design_docs"
|
426
|
+
|
381
427
|
|
382
428
|
## Assocations
|
383
429
|
|
@@ -546,7 +592,7 @@ such as validating for uniqueness and associations.
|
|
546
592
|
|
547
593
|
CouchRest Model supports a few configuration options. These can be set either for the whole Model code
|
548
594
|
base or for a specific model of your chosing. To configure globally, provide something similar to the
|
549
|
-
following in your projects
|
595
|
+
following in your projects initializers or environments:
|
550
596
|
|
551
597
|
CouchRest::Model::Base.configure do |config|
|
552
598
|
config.mass_assign_any_attribute = true
|
@@ -562,7 +608,8 @@ To set for a specific model:
|
|
562
608
|
Options currently avilable are:
|
563
609
|
|
564
610
|
* `mass_assign_any_attribute` - false by default, when true any attribute may be updated via the update_attributes or attributes= methods.
|
565
|
-
* `model_type_key` - '
|
611
|
+
* `model_type_key` - 'model' by default, is the name of property that holds the class name of each CouchRest Model.
|
612
|
+
* `auto_update_design_doc` - true by default, every time a view is requested and this option is true, a quick check will be performed to ensure the model's design document is up to date. When disabled, you're design documents will never be updated automatically and you'll need to perform updates manually. Results are cached on a per-database and per-design basis to help lower the number of requests. See the View section for more details.
|
566
613
|
|
567
614
|
|
568
615
|
## Notable Issues
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.1.0.
|
1
|
+
1.1.0.beta3
|
data/benchmarks/dirty.rb
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'benchmark'
|
5
|
+
|
6
|
+
$:.unshift(File.dirname(__FILE__) + '/../lib')
|
7
|
+
require 'couchrest_model'
|
8
|
+
|
9
|
+
class BenchmarkCasted < Hash
|
10
|
+
include CouchRest::Model::CastedModel
|
11
|
+
|
12
|
+
property :name
|
13
|
+
end
|
14
|
+
|
15
|
+
class BenchmarkModel < CouchRest::Model::Base
|
16
|
+
use_database CouchRest.database!(ENV['BENCHMARK_DB'] || "http://localhost:5984/test")
|
17
|
+
|
18
|
+
property :string, String
|
19
|
+
property :number, Integer
|
20
|
+
property :casted, BenchmarkCasted
|
21
|
+
property :casted_list, [BenchmarkCasted]
|
22
|
+
end
|
23
|
+
|
24
|
+
# set dirty configuration, return previous configuration setting
|
25
|
+
def set_dirty(value)
|
26
|
+
orig = nil
|
27
|
+
CouchRest::Model::Base.configure do |config|
|
28
|
+
orig = config.use_dirty
|
29
|
+
config.use_dirty = value
|
30
|
+
end
|
31
|
+
BenchmarkModel.instance_eval do
|
32
|
+
self.use_dirty = value
|
33
|
+
end
|
34
|
+
orig
|
35
|
+
end
|
36
|
+
|
37
|
+
def supports_dirty?
|
38
|
+
CouchRest::Model::Base.respond_to?(:use_dirty)
|
39
|
+
end
|
40
|
+
|
41
|
+
def run_benchmark
|
42
|
+
n = 50000 # property operation count
|
43
|
+
db_n = 1000 # database operation count
|
44
|
+
b = BenchmarkModel.new
|
45
|
+
|
46
|
+
Benchmark.bm(30) do |x|
|
47
|
+
|
48
|
+
# property assigning
|
49
|
+
|
50
|
+
x.report("assign string:") do
|
51
|
+
n.times { b.string = "test" }
|
52
|
+
end
|
53
|
+
|
54
|
+
next if ENV["BENCHMARK_STRING"]
|
55
|
+
|
56
|
+
x.report("assign integer:") do
|
57
|
+
n.times { b.number = 1 }
|
58
|
+
end
|
59
|
+
|
60
|
+
x.report("assign casted hash:") do
|
61
|
+
n.times { b.casted = { 'name' => 'test' } }
|
62
|
+
end
|
63
|
+
|
64
|
+
x.report("assign casted hash list:") do
|
65
|
+
n.times { b.casted_list = [{ 'name' => 'test' }] }
|
66
|
+
end
|
67
|
+
|
68
|
+
# property reading
|
69
|
+
|
70
|
+
x.report("read string") do
|
71
|
+
n.times { b.string }
|
72
|
+
end
|
73
|
+
|
74
|
+
x.report("read integer") do
|
75
|
+
n.times { b.number }
|
76
|
+
end
|
77
|
+
|
78
|
+
x.report("read casted hash") do
|
79
|
+
n.times { b.casted }
|
80
|
+
end
|
81
|
+
|
82
|
+
x.report("read casted hash list") do
|
83
|
+
n.times { b.casted_list }
|
84
|
+
end
|
85
|
+
|
86
|
+
if ENV['BENCHMARK_DB']
|
87
|
+
# db writing
|
88
|
+
x.report("write changed record to db") do
|
89
|
+
db_n.times { |i| b.string = "test#{i}"; b.save }
|
90
|
+
end
|
91
|
+
|
92
|
+
x.report("write unchanged record to db") do
|
93
|
+
db_n.times { b.save }
|
94
|
+
end
|
95
|
+
|
96
|
+
# db reading
|
97
|
+
x.report("read record from db") do
|
98
|
+
db_n.times { BenchmarkModel.find(b.id) }
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
begin
|
107
|
+
if supports_dirty?
|
108
|
+
if !ENV['BENCHMARK_DIRTY_OFF']
|
109
|
+
set_dirty(true)
|
110
|
+
puts "with use_dirty true"
|
111
|
+
run_benchmark
|
112
|
+
end
|
113
|
+
set_dirty(false)
|
114
|
+
puts "\nwith use_dirty false"
|
115
|
+
end
|
116
|
+
|
117
|
+
run_benchmark
|
118
|
+
end
|
data/couchrest_model.gemspec
CHANGED
data/history.txt
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
== 1.1.0.beta3
|
2
|
+
|
3
|
+
* Major changes:
|
4
|
+
* Fast Dirty Tracking! Many thanks to @sobakasu (Andrew Williams)
|
5
|
+
* Default CouchRest Model type field now set to 'model' instead of 'couchrest-type'.
|
6
|
+
|
7
|
+
* Minor enhancements:
|
8
|
+
* Adding "couchrest-hash" to Design Docs with aim to improve view update handling.
|
9
|
+
* Major changes to the way design document updates are handled internally.
|
10
|
+
* Added "auto_update_design_doc" configuration option.
|
11
|
+
* Using #descending on View object will automatically swap startkey with endkey.
|
12
|
+
|
1
13
|
== 1.1.0.beta2
|
2
14
|
|
3
15
|
* Minor enhancements:
|
data/lib/couchrest/model/base.rb
CHANGED
@@ -18,14 +18,17 @@ module CouchRest
|
|
18
18
|
include CouchRest::Model::Associations
|
19
19
|
include CouchRest::Model::Validations
|
20
20
|
include CouchRest::Model::Designs
|
21
|
+
include CouchRest::Model::Dirty
|
22
|
+
include CouchRest::Model::CastedBy
|
21
23
|
|
22
24
|
def self.subclasses
|
23
25
|
@subclasses ||= []
|
24
26
|
end
|
25
|
-
|
27
|
+
|
26
28
|
def self.inherited(subklass)
|
27
29
|
super
|
28
30
|
subklass.send(:include, CouchRest::Model::Properties)
|
31
|
+
|
29
32
|
subklass.class_eval <<-EOS, __FILE__, __LINE__ + 1
|
30
33
|
def self.inherited(subklass)
|
31
34
|
super
|
@@ -36,16 +39,12 @@ module CouchRest
|
|
36
39
|
EOS
|
37
40
|
subclasses << subklass
|
38
41
|
end
|
39
|
-
|
40
|
-
# Accessors
|
41
|
-
attr_accessor :casted_by
|
42
|
-
|
43
42
|
|
44
43
|
# Instantiate a new CouchRest::Model::Base by preparing all properties
|
45
44
|
# using the provided document hash.
|
46
45
|
#
|
47
46
|
# Options supported:
|
48
|
-
#
|
47
|
+
#
|
49
48
|
# * :directly_set_attributes: true when data comes directly from database
|
50
49
|
# * :database: provide an alternative database
|
51
50
|
#
|
@@ -59,8 +58,8 @@ module CouchRest
|
|
59
58
|
end
|
60
59
|
after_initialize if respond_to?(:after_initialize)
|
61
60
|
end
|
62
|
-
|
63
|
-
|
61
|
+
|
62
|
+
|
64
63
|
# Temp solution to make the view_by methods available
|
65
64
|
def self.method_missing(m, *args, &block)
|
66
65
|
if has_view?(m)
|
@@ -74,24 +73,17 @@ module CouchRest
|
|
74
73
|
end
|
75
74
|
super
|
76
75
|
end
|
77
|
-
|
76
|
+
|
78
77
|
### instance methods
|
79
|
-
|
80
|
-
# Gets a reference to the actual document in the DB
|
81
|
-
# Calls up to the next document if there is one,
|
82
|
-
# Otherwise we're at the top and we return self
|
83
|
-
def base_doc
|
84
|
-
return self if base_doc?
|
85
|
-
@casted_by.base_doc
|
86
|
-
end
|
87
|
-
|
78
|
+
|
88
79
|
# Checks if we're the top document
|
80
|
+
# (overrides base_doc? in casted_by.rb)
|
89
81
|
def base_doc?
|
90
82
|
!@casted_by
|
91
83
|
end
|
92
|
-
|
84
|
+
|
93
85
|
## Compatibility with ActiveSupport and older frameworks
|
94
|
-
|
86
|
+
|
95
87
|
# Hack so that CouchRest::Document, which descends from Hash,
|
96
88
|
# doesn't appear to Rails routing as a Hash of options
|
97
89
|
def is_a?(klass)
|
@@ -103,14 +95,14 @@ module CouchRest
|
|
103
95
|
def persisted?
|
104
96
|
!new?
|
105
97
|
end
|
106
|
-
|
98
|
+
|
107
99
|
def to_key
|
108
|
-
new? ? nil : [id]
|
100
|
+
new? ? nil : [id]
|
109
101
|
end
|
110
102
|
|
111
103
|
alias :to_param :id
|
112
104
|
alias :new_record? :new?
|
113
105
|
alias :new_document? :new?
|
114
|
-
end
|
106
|
+
end
|
115
107
|
end
|
116
108
|
end
|
@@ -5,6 +5,7 @@
|
|
5
5
|
|
6
6
|
module CouchRest::Model
|
7
7
|
class CastedArray < Array
|
8
|
+
include CouchRest::Model::Dirty
|
8
9
|
attr_accessor :casted_by
|
9
10
|
attr_accessor :property
|
10
11
|
|
@@ -14,15 +15,39 @@ module CouchRest::Model
|
|
14
15
|
end
|
15
16
|
|
16
17
|
def << obj
|
18
|
+
couchrest_parent_will_change! if use_dirty?
|
17
19
|
super(instantiate_and_cast(obj))
|
18
20
|
end
|
19
21
|
|
20
22
|
def push(obj)
|
23
|
+
couchrest_parent_will_change! if use_dirty?
|
24
|
+
super(instantiate_and_cast(obj))
|
25
|
+
end
|
26
|
+
|
27
|
+
def pop
|
28
|
+
couchrest_parent_will_change! if use_dirty? && self.length > 0
|
29
|
+
super
|
30
|
+
end
|
31
|
+
|
32
|
+
def shift
|
33
|
+
couchrest_parent_will_change! if use_dirty? && self.length > 0
|
34
|
+
super
|
35
|
+
end
|
36
|
+
|
37
|
+
def unshift(obj)
|
38
|
+
couchrest_parent_will_change! if use_dirty?
|
21
39
|
super(instantiate_and_cast(obj))
|
22
40
|
end
|
23
41
|
|
24
42
|
def []= index, obj
|
25
|
-
|
43
|
+
value = instantiate_and_cast(obj)
|
44
|
+
couchrest_parent_will_change! if use_dirty? && value != self[index]
|
45
|
+
super(index, value)
|
46
|
+
end
|
47
|
+
|
48
|
+
def clear
|
49
|
+
couchrest_parent_will_change! if use_dirty? && self.length > 0
|
50
|
+
super
|
26
51
|
end
|
27
52
|
|
28
53
|
protected
|
@@ -0,0 +1,23 @@
|
|
1
|
+
|
2
|
+
module CouchRest::Model
|
3
|
+
module CastedBy
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
included do
|
6
|
+
self.send(:attr_accessor, :casted_by)
|
7
|
+
end
|
8
|
+
|
9
|
+
# Gets a reference to the actual document in the DB
|
10
|
+
# Calls up to the next document if there is one,
|
11
|
+
# Otherwise we're at the top and we return self
|
12
|
+
def base_doc
|
13
|
+
return self if base_doc?
|
14
|
+
@casted_by ? @casted_by.base_doc : nil
|
15
|
+
end
|
16
|
+
|
17
|
+
# Checks if we're the top document
|
18
|
+
def base_doc?
|
19
|
+
false
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
#
|
2
|
+
# Wrapper around Hash so that the casted_by attribute is set.
|
3
|
+
|
4
|
+
module CouchRest::Model
|
5
|
+
class CastedHash < Hash
|
6
|
+
include CouchRest::Model::Dirty
|
7
|
+
attr_accessor :casted_by
|
8
|
+
|
9
|
+
# needed for dirty
|
10
|
+
def attributes
|
11
|
+
self
|
12
|
+
end
|
13
|
+
|
14
|
+
def []= key, obj
|
15
|
+
couchrest_attribute_will_change!(key) if use_dirty? && obj != self[key]
|
16
|
+
super(key, obj)
|
17
|
+
end
|
18
|
+
|
19
|
+
def delete(key)
|
20
|
+
couchrest_attribute_will_change!(key) if use_dirty? && include?(key)
|
21
|
+
super(key)
|
22
|
+
end
|
23
|
+
|
24
|
+
def merge!(other_hash)
|
25
|
+
if use_dirty? && other_hash && other_hash.kind_of?(Hash)
|
26
|
+
other_hash.keys.each do |key|
|
27
|
+
if self[key] != other_hash[key] || !include?(key)
|
28
|
+
couchrest_attribute_will_change!(key)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
super(other_hash)
|
33
|
+
end
|
34
|
+
|
35
|
+
def replace(other_hash)
|
36
|
+
if use_dirty? && other_hash && other_hash.kind_of?(Hash)
|
37
|
+
# new keys and changed keys
|
38
|
+
other_hash.keys.each do |key|
|
39
|
+
if self[key] != other_hash[key] || !include?(key)
|
40
|
+
couchrest_attribute_will_change!(key)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
# old keys
|
44
|
+
old_keys = self.keys.reject { |key| other_hash.include?(key) }
|
45
|
+
old_keys.each { |key| couchrest_attribute_will_change!(key) }
|
46
|
+
end
|
47
|
+
|
48
|
+
super(other_hash)
|
49
|
+
end
|
50
|
+
|
51
|
+
def clear
|
52
|
+
self.keys.each { |key| couchrest_attribute_will_change!(key) } if use_dirty?
|
53
|
+
super
|
54
|
+
end
|
55
|
+
|
56
|
+
def delete_if
|
57
|
+
if use_dirty? && block_given?
|
58
|
+
self.keys.each do |key|
|
59
|
+
couchrest_attribute_will_change!(key) if yield key, self[key]
|
60
|
+
end
|
61
|
+
end
|
62
|
+
super
|
63
|
+
end
|
64
|
+
|
65
|
+
# ruby 1.9
|
66
|
+
def keep_if
|
67
|
+
if use_dirty? && block_given?
|
68
|
+
self.keys.each do |key|
|
69
|
+
couchrest_attribute_will_change!(key) if !yield key, self[key]
|
70
|
+
end
|
71
|
+
end
|
72
|
+
super
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
end
|
@@ -10,30 +10,32 @@ module CouchRest::Model
|
|
10
10
|
include CouchRest::Model::PropertyProtection
|
11
11
|
include CouchRest::Model::Associations
|
12
12
|
include CouchRest::Model::Validations
|
13
|
-
|
13
|
+
include CouchRest::Model::Dirty
|
14
|
+
# attr_accessor :casted_by
|
14
15
|
end
|
15
|
-
|
16
|
+
|
16
17
|
def initialize(keys = {})
|
17
18
|
raise StandardError unless self.is_a? Hash
|
18
19
|
prepare_all_attributes(keys)
|
19
20
|
super()
|
20
21
|
end
|
21
|
-
|
22
|
+
|
22
23
|
def []= key, value
|
24
|
+
couchrest_attribute_will_change!(key) if self[key] != value
|
23
25
|
super(key.to_s, value)
|
24
26
|
end
|
25
|
-
|
27
|
+
|
26
28
|
def [] key
|
27
29
|
super(key.to_s)
|
28
30
|
end
|
29
|
-
|
31
|
+
|
30
32
|
# Gets a reference to the top level extended
|
31
33
|
# document that a model is saved inside of
|
32
34
|
def base_doc
|
33
35
|
return nil unless @casted_by
|
34
36
|
@casted_by.base_doc
|
35
37
|
end
|
36
|
-
|
38
|
+
|
37
39
|
# False if the casted model has already
|
38
40
|
# been saved in the containing document
|
39
41
|
def new?
|
@@ -64,5 +66,6 @@ module CouchRest::Model
|
|
64
66
|
end
|
65
67
|
end
|
66
68
|
alias :attributes= :update_attributes_without_saving
|
69
|
+
|
67
70
|
end
|
68
71
|
end
|
@@ -1,7 +1,13 @@
|
|
1
1
|
module CouchRest
|
2
2
|
module Model
|
3
|
+
# Warning! The Collection module is seriously depricated.
|
4
|
+
# Use the new Design Views instead, as this code copies many other parts
|
5
|
+
# of CouchRest Model.
|
6
|
+
#
|
7
|
+
# Expect this to be removed soon.
|
8
|
+
#
|
3
9
|
module Collection
|
4
|
-
|
10
|
+
|
5
11
|
def self.included(base)
|
6
12
|
base.extend(ClassMethods)
|
7
13
|
end
|
@@ -131,6 +137,9 @@ module CouchRest
|
|
131
137
|
else
|
132
138
|
@view_name = "#{design_doc}/#{view_name}"
|
133
139
|
end
|
140
|
+
|
141
|
+
# Save the design doc, ready for use
|
142
|
+
@container_class.save_design_doc(@database)
|
134
143
|
end
|
135
144
|
|
136
145
|
# See Collection.paginate
|
@@ -10,10 +10,12 @@ module CouchRest
|
|
10
10
|
included do
|
11
11
|
add_config :model_type_key
|
12
12
|
add_config :mass_assign_any_attribute
|
13
|
-
|
13
|
+
add_config :auto_update_design_doc
|
14
|
+
|
14
15
|
configure do |config|
|
15
|
-
config.model_type_key = '
|
16
|
+
config.model_type_key = 'model' # was 'couchrest-type'
|
16
17
|
config.mass_assign_any_attribute = false
|
18
|
+
config.auto_update_design_doc = true
|
17
19
|
end
|
18
20
|
end
|
19
21
|
|
@@ -47,5 +49,3 @@ module CouchRest
|
|
47
49
|
end
|
48
50
|
end
|
49
51
|
end
|
50
|
-
|
51
|
-
|