mattetti-couchrest 0.21 → 0.22
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.
- data/lib/couchrest.rb +14 -5
- data/lib/couchrest/core/database.rb +7 -25
- data/lib/couchrest/core/document.rb +2 -2
- data/lib/couchrest/helper/upgrade.rb +51 -0
- data/lib/couchrest/mixins/callbacks.rb +3 -3
- data/lib/couchrest/mixins/properties.rb +9 -5
- data/lib/couchrest/mixins/validation.rb +8 -3
- data/lib/couchrest/mixins/views.rb +3 -3
- data/lib/couchrest/monkeypatches.rb +1 -1
- data/lib/couchrest/more/extended_document.rb +7 -10
- data/lib/couchrest/support/class.rb +136 -151
- data/lib/couchrest/validation/validation_errors.rb +1 -1
- data/lib/couchrest/validation/validators/format_validator.rb +1 -1
- data/lib/couchrest/validation/validators/length_validator.rb +1 -1
- data/spec/couchrest/core/database_spec.rb +4 -63
- data/spec/couchrest/core/document_spec.rb +0 -44
- data/spec/couchrest/more/casted_model_spec.rb +2 -1
- data/spec/couchrest/more/extended_doc_attachment_spec.rb +2 -1
- data/spec/couchrest/more/extended_doc_spec.rb +1 -1
- data/spec/couchrest/more/extended_doc_subclass_spec.rb +54 -0
- data/spec/couchrest/more/extended_doc_view_spec.rb +2 -1
- data/spec/couchrest/more/property_spec.rb +2 -1
- metadata +3 -3
- data/spec/couchrest/support/class_spec.rb +0 -59
data/lib/couchrest.rb
CHANGED
|
@@ -28,7 +28,7 @@ require 'couchrest/monkeypatches'
|
|
|
28
28
|
|
|
29
29
|
# = CouchDB, close to the metal
|
|
30
30
|
module CouchRest
|
|
31
|
-
VERSION = '0.
|
|
31
|
+
VERSION = '0.22' unless self.const_defined?("VERSION")
|
|
32
32
|
|
|
33
33
|
autoload :Server, 'couchrest/core/server'
|
|
34
34
|
autoload :Database, 'couchrest/core/database'
|
|
@@ -40,6 +40,7 @@ module CouchRest
|
|
|
40
40
|
autoload :Pager, 'couchrest/helper/pager'
|
|
41
41
|
autoload :FileManager, 'couchrest/helper/file_manager'
|
|
42
42
|
autoload :Streamer, 'couchrest/helper/streamer'
|
|
43
|
+
autoload :Upgrade, 'couchrest/helper/upgrade'
|
|
43
44
|
|
|
44
45
|
autoload :ExtendedDocument, 'couchrest/more/extended_document'
|
|
45
46
|
autoload :CastedModel, 'couchrest/more/casted_model'
|
|
@@ -68,6 +69,18 @@ module CouchRest
|
|
|
68
69
|
Object.module_eval("::#{$1}", __FILE__, __LINE__)
|
|
69
70
|
end
|
|
70
71
|
|
|
72
|
+
# extracted from Extlib
|
|
73
|
+
#
|
|
74
|
+
# Capitalizes the first word and turns underscores into spaces and strips _id.
|
|
75
|
+
# Like titleize, this is meant for creating pretty output.
|
|
76
|
+
#
|
|
77
|
+
# @example
|
|
78
|
+
# "employee_salary" #=> "Employee salary"
|
|
79
|
+
# "author_id" #=> "Author"
|
|
80
|
+
def humanize(lower_case_and_underscored_word)
|
|
81
|
+
lower_case_and_underscored_word.to_s.gsub(/_id$/, "").gsub(/_/, " ").capitalize
|
|
82
|
+
end
|
|
83
|
+
|
|
71
84
|
# todo, make this parse the url and instantiate a Server or Database instance
|
|
72
85
|
# depending on the specificity.
|
|
73
86
|
def new(*opts)
|
|
@@ -170,10 +183,6 @@ module CouchRest
|
|
|
170
183
|
def copy uri, destination
|
|
171
184
|
JSON.parse(RestClient.copy(uri, {'Destination' => destination}))
|
|
172
185
|
end
|
|
173
|
-
|
|
174
|
-
def move uri, destination
|
|
175
|
-
JSON.parse(RestClient.move(uri, {'Destination' => destination}))
|
|
176
|
-
end
|
|
177
186
|
|
|
178
187
|
def paramify_url url, params = {}
|
|
179
188
|
if params && !params.empty?
|
|
@@ -77,13 +77,15 @@ module CouchRest
|
|
|
77
77
|
end
|
|
78
78
|
|
|
79
79
|
# GET a document from CouchDB, by id. Returns a Ruby Hash.
|
|
80
|
-
def get(id)
|
|
80
|
+
def get(id, params = {})
|
|
81
81
|
slug = escape_docid(id)
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
82
|
+
url = CouchRest.paramify_url("#{@uri}/#{slug}", params)
|
|
83
|
+
result = CouchRest.get(url)
|
|
84
|
+
return result unless result.is_a?(Hash)
|
|
85
|
+
doc = if /^_design/ =~ result["_id"]
|
|
86
|
+
Design.new(result)
|
|
85
87
|
else
|
|
86
|
-
Document.new(
|
|
88
|
+
Document.new(result)
|
|
87
89
|
end
|
|
88
90
|
doc.database = self
|
|
89
91
|
doc
|
|
@@ -222,26 +224,6 @@ module CouchRest
|
|
|
222
224
|
copy_doc(doc, dest)
|
|
223
225
|
end
|
|
224
226
|
|
|
225
|
-
# MOVE an existing document to a new id. If the destination id currently exists, a rev must be provided.
|
|
226
|
-
# <tt>dest</tt> can take one of two forms if overwriting: "id_to_overwrite?rev=revision" or the actual doc
|
|
227
|
-
# hash with a '_rev' key
|
|
228
|
-
def move_doc(doc, dest)
|
|
229
|
-
raise ArgumentError, "_id and _rev are required for moving" unless doc['_id'] && doc['_rev']
|
|
230
|
-
slug = escape_docid(doc['_id'])
|
|
231
|
-
destination = if dest.respond_to?(:has_key?) && dest['_id'] && dest['_rev']
|
|
232
|
-
"#{dest['_id']}?rev=#{dest['_rev']}"
|
|
233
|
-
else
|
|
234
|
-
dest
|
|
235
|
-
end
|
|
236
|
-
CouchRest.move "#{@uri}/#{slug}?rev=#{doc['_rev']}", destination
|
|
237
|
-
end
|
|
238
|
-
|
|
239
|
-
### DEPRECATION NOTICE
|
|
240
|
-
def move(doc, dest)
|
|
241
|
-
puts "CouchRest::Database's move method is being deprecated, please use move_doc instead"
|
|
242
|
-
move_doc(doc, dest)
|
|
243
|
-
end
|
|
244
|
-
|
|
245
227
|
# Compact the database, removing old document revisions and optimizing space use.
|
|
246
228
|
def compact!
|
|
247
229
|
CouchRest.post "#{@uri}/_compact"
|
|
@@ -5,10 +5,10 @@ module CouchRest
|
|
|
5
5
|
include CouchRest::Mixins::Attachments
|
|
6
6
|
|
|
7
7
|
# def self.inherited(subklass)
|
|
8
|
-
# subklass.send(:
|
|
8
|
+
# subklass.send(:extlib_inheritable_accessor, :database)
|
|
9
9
|
# end
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
extlib_inheritable_accessor :database
|
|
12
12
|
attr_accessor :database
|
|
13
13
|
|
|
14
14
|
# override the CouchRest::Model-wide default_database
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
module CouchRest
|
|
2
|
+
class Upgrade
|
|
3
|
+
attr_accessor :olddb, :newdb, :dbname
|
|
4
|
+
def initialize dbname, old_couch, new_couch
|
|
5
|
+
@dbname = dbname
|
|
6
|
+
@olddb = old_couch.database dbname
|
|
7
|
+
@newdb = new_couch.database!(dbname)
|
|
8
|
+
@bulk_docs = []
|
|
9
|
+
end
|
|
10
|
+
def clone!
|
|
11
|
+
puts "#{dbname} - #{olddb.info['doc_count']} docs"
|
|
12
|
+
streamer = CouchRest::Streamer.new(olddb)
|
|
13
|
+
streamer.view("_all_docs_by_seq") do |row|
|
|
14
|
+
load_row_docs(row) if row
|
|
15
|
+
maybe_flush_bulks
|
|
16
|
+
end
|
|
17
|
+
flush_bulks!
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
|
|
22
|
+
def maybe_flush_bulks
|
|
23
|
+
flush_bulks! if (@bulk_docs.length > 99)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def flush_bulks!
|
|
27
|
+
url = CouchRest.paramify_url "#{@newdb.uri}/_bulk_docs", {:all_or_nothing => true}
|
|
28
|
+
puts "posting #{@bulk_docs.length} bulk docs to #{url}"
|
|
29
|
+
begin
|
|
30
|
+
CouchRest.post url, {:docs => @bulk_docs}
|
|
31
|
+
@bulk_docs = []
|
|
32
|
+
rescue Exception => e
|
|
33
|
+
puts e.response
|
|
34
|
+
raise e
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def load_row_docs(row)
|
|
39
|
+
results = @olddb.get(row["id"], {:open_revs => "all", :attachments => true})
|
|
40
|
+
results.select{|r|r["ok"]}.each do |r|
|
|
41
|
+
doc = r["ok"]
|
|
42
|
+
if /^_/.match(doc["_id"]) && !/^_design/.match(doc["_id"])
|
|
43
|
+
puts "invalid docid #{doc["_id"]} -- trimming"
|
|
44
|
+
doc["_id"] = doc["_id"].sub('_','')
|
|
45
|
+
end
|
|
46
|
+
doc.delete('_rev')
|
|
47
|
+
@bulk_docs << doc
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -426,10 +426,10 @@ module CouchRest
|
|
|
426
426
|
def define_callbacks(*symbols)
|
|
427
427
|
terminator = symbols.pop if symbols.last.is_a?(String)
|
|
428
428
|
symbols.each do |symbol|
|
|
429
|
-
self.
|
|
429
|
+
self.extlib_inheritable_accessor("_#{symbol}_terminator")
|
|
430
430
|
self.send("_#{symbol}_terminator=", terminator)
|
|
431
431
|
self.class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
|
|
432
|
-
|
|
432
|
+
extlib_inheritable_accessor :_#{symbol}_callbacks
|
|
433
433
|
self._#{symbol}_callbacks = CallbackChain.new(:#{symbol})
|
|
434
434
|
|
|
435
435
|
def self.#{symbol}_callback(*filters, &blk)
|
|
@@ -480,4 +480,4 @@ module CouchRest
|
|
|
480
480
|
end
|
|
481
481
|
end
|
|
482
482
|
end
|
|
483
|
-
end
|
|
483
|
+
end
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
require 'time'
|
|
1
2
|
require File.join(File.dirname(__FILE__), '..', 'more', 'property')
|
|
2
3
|
|
|
3
4
|
module CouchRest
|
|
@@ -7,10 +8,10 @@ module CouchRest
|
|
|
7
8
|
class IncludeError < StandardError; end
|
|
8
9
|
|
|
9
10
|
def self.included(base)
|
|
10
|
-
base.
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
base.class_eval <<-EOS, __FILE__, __LINE__
|
|
12
|
+
extlib_inheritable_accessor(:properties)
|
|
13
|
+
self.properties ||= []
|
|
14
|
+
EOS
|
|
14
15
|
base.extend(ClassMethods)
|
|
15
16
|
raise CouchRest::Mixins::Properties::IncludeError, "You can only mixin Properties in a class responding to [] and []=, if you tried to mixin CastedModel, make sure your class inherits from Hash or responds to the proper methods" unless (base.new.respond_to?(:[]) && base.new.respond_to?(:[]=))
|
|
16
17
|
end
|
|
@@ -70,7 +71,10 @@ module CouchRest
|
|
|
70
71
|
module ClassMethods
|
|
71
72
|
|
|
72
73
|
def property(name, options={})
|
|
73
|
-
|
|
74
|
+
existing_property = self.properties.find{|p| p.name == name.to_s}
|
|
75
|
+
if existing_property.nil? || (existing_property.default != options[:default])
|
|
76
|
+
define_property(name, options)
|
|
77
|
+
end
|
|
74
78
|
end
|
|
75
79
|
|
|
76
80
|
protected
|
|
@@ -49,10 +49,10 @@ module CouchRest
|
|
|
49
49
|
module Validation
|
|
50
50
|
|
|
51
51
|
def self.included(base)
|
|
52
|
-
base.
|
|
52
|
+
base.extlib_inheritable_accessor(:auto_validation)
|
|
53
53
|
base.class_eval <<-EOS, __FILE__, __LINE__
|
|
54
54
|
# Turn off auto validation by default
|
|
55
|
-
|
|
55
|
+
self.auto_validation ||= false
|
|
56
56
|
|
|
57
57
|
# Force the auto validation for the class properties
|
|
58
58
|
# This feature is still not fully ported over,
|
|
@@ -60,6 +60,11 @@ module CouchRest
|
|
|
60
60
|
def self.auto_validate!
|
|
61
61
|
self.auto_validation = true
|
|
62
62
|
end
|
|
63
|
+
|
|
64
|
+
# share the validations with subclasses
|
|
65
|
+
def self.inherited(subklass)
|
|
66
|
+
subklass.instance_variable_set(:@validations, self.validators.dup)
|
|
67
|
+
end
|
|
63
68
|
EOS
|
|
64
69
|
|
|
65
70
|
base.extend(ClassMethods)
|
|
@@ -71,7 +76,7 @@ module CouchRest
|
|
|
71
76
|
base.class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
|
|
72
77
|
def self.define_property(name, options={})
|
|
73
78
|
super
|
|
74
|
-
auto_generate_validations(properties.last)
|
|
79
|
+
auto_generate_validations(properties.last) if properties && properties.size > 0
|
|
75
80
|
autovalidation_check = true
|
|
76
81
|
end
|
|
77
82
|
RUBY_EVAL
|
|
@@ -4,9 +4,9 @@ module CouchRest
|
|
|
4
4
|
|
|
5
5
|
def self.included(base)
|
|
6
6
|
base.extend(ClassMethods)
|
|
7
|
-
base.send(:
|
|
8
|
-
base.send(:
|
|
9
|
-
base.send(:
|
|
7
|
+
base.send(:extlib_inheritable_accessor, :design_doc)
|
|
8
|
+
base.send(:extlib_inheritable_accessor, :design_doc_slug_cache)
|
|
9
|
+
base.send(:extlib_inheritable_accessor, :design_doc_fresh)
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
module ClassMethods
|
|
@@ -1,11 +1,3 @@
|
|
|
1
|
-
begin
|
|
2
|
-
# still required for Time parsing and pluralization in the validation
|
|
3
|
-
require 'extlib'
|
|
4
|
-
rescue
|
|
5
|
-
puts "CouchRest::ExtendedDocument still requires extlib (not for much longer). This is left out of the gemspec on purpose."
|
|
6
|
-
raise
|
|
7
|
-
end
|
|
8
|
-
|
|
9
1
|
require 'mime/types'
|
|
10
2
|
require File.join(File.dirname(__FILE__), "property")
|
|
11
3
|
require File.join(File.dirname(__FILE__), '..', 'mixins', 'extended_document_mixins')
|
|
@@ -22,6 +14,11 @@ module CouchRest
|
|
|
22
14
|
|
|
23
15
|
def self.inherited(subklass)
|
|
24
16
|
subklass.send(:include, CouchRest::Mixins::Properties)
|
|
17
|
+
subklass.class_eval <<-EOS, __FILE__, __LINE__
|
|
18
|
+
def self.inherited(subklass)
|
|
19
|
+
subklass.properties = self.properties.dup
|
|
20
|
+
end
|
|
21
|
+
EOS
|
|
25
22
|
end
|
|
26
23
|
|
|
27
24
|
# Accessors
|
|
@@ -205,8 +202,8 @@ module CouchRest
|
|
|
205
202
|
_run_destroy_callbacks do
|
|
206
203
|
result = database.delete_doc(self, bulk)
|
|
207
204
|
if result['ok']
|
|
208
|
-
self
|
|
209
|
-
self
|
|
205
|
+
self.delete('_rev')
|
|
206
|
+
self.delete('_id')
|
|
210
207
|
end
|
|
211
208
|
result['ok']
|
|
212
209
|
end
|
|
@@ -25,167 +25,152 @@
|
|
|
25
25
|
# example, an array without those additions being shared with either their
|
|
26
26
|
# parent, siblings, or children, which is unlike the regular class-level
|
|
27
27
|
# attributes that are shared across the entire hierarchy.
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
# @return <Array[#to_s]> List of attributes that were made into cattr_readers
|
|
45
|
-
#
|
|
46
|
-
# @api public
|
|
47
|
-
#
|
|
48
|
-
# @todo Is this inconsistent in that it does not allow you to prevent
|
|
49
|
-
# an instance_reader via :instance_reader => false
|
|
50
|
-
def cattr_reader(*syms)
|
|
51
|
-
syms.flatten.each do |sym|
|
|
52
|
-
next if sym.is_a?(Hash)
|
|
53
|
-
class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
|
|
54
|
-
unless defined? @@#{sym}
|
|
55
|
-
@@#{sym} = nil
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
def self.#{sym}
|
|
59
|
-
@@#{sym}
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
def #{sym}
|
|
63
|
-
@@#{sym}
|
|
64
|
-
end
|
|
65
|
-
RUBY
|
|
28
|
+
class Class
|
|
29
|
+
# Defines class-level and instance-level attribute reader.
|
|
30
|
+
#
|
|
31
|
+
# @param *syms<Array> Array of attributes to define reader for.
|
|
32
|
+
# @return <Array[#to_s]> List of attributes that were made into cattr_readers
|
|
33
|
+
#
|
|
34
|
+
# @api public
|
|
35
|
+
#
|
|
36
|
+
# @todo Is this inconsistent in that it does not allow you to prevent
|
|
37
|
+
# an instance_reader via :instance_reader => false
|
|
38
|
+
def cattr_reader(*syms)
|
|
39
|
+
syms.flatten.each do |sym|
|
|
40
|
+
next if sym.is_a?(Hash)
|
|
41
|
+
class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
|
|
42
|
+
unless defined? @@#{sym}
|
|
43
|
+
@@#{sym} = nil
|
|
66
44
|
end
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
def cattr_writer(*syms)
|
|
77
|
-
options = syms.last.is_a?(Hash) ? syms.pop : {}
|
|
78
|
-
syms.flatten.each do |sym|
|
|
79
|
-
class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
|
|
80
|
-
unless defined? @@#{sym}
|
|
81
|
-
@@#{sym} = nil
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
def self.#{sym}=(obj)
|
|
85
|
-
@@#{sym} = obj
|
|
86
|
-
end
|
|
87
|
-
RUBY
|
|
88
|
-
|
|
89
|
-
unless options[:instance_writer] == false
|
|
90
|
-
class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
|
|
91
|
-
def #{sym}=(obj)
|
|
92
|
-
@@#{sym} = obj
|
|
45
|
+
|
|
46
|
+
def self.#{sym}
|
|
47
|
+
@@#{sym}
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def #{sym}
|
|
51
|
+
@@#{sym}
|
|
52
|
+
end
|
|
53
|
+
RUBY
|
|
93
54
|
end
|
|
94
|
-
|
|
95
|
-
|
|
55
|
+
end unless Class.respond_to?(:cattr_reader)
|
|
56
|
+
|
|
57
|
+
# Defines class-level (and optionally instance-level) attribute writer.
|
|
58
|
+
#
|
|
59
|
+
# @param <Array[*#to_s, Hash{:instance_writer => Boolean}]> Array of attributes to define writer for.
|
|
60
|
+
# @option syms :instance_writer<Boolean> if true, instance-level attribute writer is defined.
|
|
61
|
+
# @return <Array[#to_s]> List of attributes that were made into cattr_writers
|
|
62
|
+
#
|
|
63
|
+
# @api public
|
|
64
|
+
def cattr_writer(*syms)
|
|
65
|
+
options = syms.last.is_a?(Hash) ? syms.pop : {}
|
|
66
|
+
syms.flatten.each do |sym|
|
|
67
|
+
class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
|
|
68
|
+
unless defined? @@#{sym}
|
|
69
|
+
@@#{sym} = nil
|
|
96
70
|
end
|
|
71
|
+
|
|
72
|
+
def self.#{sym}=(obj)
|
|
73
|
+
@@#{sym} = obj
|
|
74
|
+
end
|
|
75
|
+
RUBY
|
|
76
|
+
|
|
77
|
+
unless options[:instance_writer] == false
|
|
78
|
+
class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
|
|
79
|
+
def #{sym}=(obj)
|
|
80
|
+
@@#{sym} = obj
|
|
81
|
+
end
|
|
82
|
+
RUBY
|
|
97
83
|
end
|
|
98
|
-
|
|
99
|
-
# Defines class-level (and optionally instance-level) attribute accessor.
|
|
100
|
-
#
|
|
101
|
-
# @param *syms<Array[*#to_s, Hash{:instance_writer => Boolean}]> Array of attributes to define accessor for.
|
|
102
|
-
# @option syms :instance_writer<Boolean> if true, instance-level attribute writer is defined.
|
|
103
|
-
# @return <Array[#to_s]> List of attributes that were made into accessors
|
|
104
|
-
#
|
|
105
|
-
# @api public
|
|
106
|
-
def cattr_accessor(*syms)
|
|
107
|
-
cattr_reader(*syms)
|
|
108
|
-
cattr_writer(*syms)
|
|
109
|
-
end
|
|
110
|
-
|
|
111
|
-
# Defines class-level inheritable attribute reader. Attributes are available to subclasses,
|
|
112
|
-
# each subclass has a copy of parent's attribute.
|
|
113
|
-
#
|
|
114
|
-
# @param *syms<Array[#to_s]> Array of attributes to define inheritable reader for.
|
|
115
|
-
# @return <Array[#to_s]> Array of attributes converted into inheritable_readers.
|
|
116
|
-
#
|
|
117
|
-
# @api public
|
|
118
|
-
#
|
|
119
|
-
# @todo Do we want to block instance_reader via :instance_reader => false
|
|
120
|
-
# @todo It would be preferable that we do something with a Hash passed in
|
|
121
|
-
# (error out or do the same as other methods above) instead of silently
|
|
122
|
-
# moving on). In particular, this makes the return value of this function
|
|
123
|
-
# less useful.
|
|
124
|
-
def class_inheritable_reader(*ivars)
|
|
125
|
-
instance_reader = ivars.pop[:reader] if ivars.last.is_a?(Hash)
|
|
126
|
-
|
|
127
|
-
ivars.each do |ivar|
|
|
128
|
-
self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
|
129
|
-
def self.#{ivar}
|
|
130
|
-
return @#{ivar} if self.object_id == #{self.object_id} || defined?(@#{ivar})
|
|
131
|
-
ivar = superclass.#{ivar}
|
|
132
|
-
return nil if ivar.nil? && !#{self}.instance_variable_defined?("@#{ivar}")
|
|
133
|
-
@#{ivar} = ivar && !ivar.is_a?(Module) && !ivar.is_a?(Numeric) && !ivar.is_a?(TrueClass) && !ivar.is_a?(FalseClass) && !ivar.is_a?(Symbol) ? ivar.dup : ivar
|
|
134
84
|
end
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
85
|
+
end unless Class.respond_to?(:cattr_writer)
|
|
86
|
+
|
|
87
|
+
# Defines class-level (and optionally instance-level) attribute accessor.
|
|
88
|
+
#
|
|
89
|
+
# @param *syms<Array[*#to_s, Hash{:instance_writer => Boolean}]> Array of attributes to define accessor for.
|
|
90
|
+
# @option syms :instance_writer<Boolean> if true, instance-level attribute writer is defined.
|
|
91
|
+
# @return <Array[#to_s]> List of attributes that were made into accessors
|
|
92
|
+
#
|
|
93
|
+
# @api public
|
|
94
|
+
def cattr_accessor(*syms)
|
|
95
|
+
cattr_reader(*syms)
|
|
96
|
+
cattr_writer(*syms)
|
|
97
|
+
end unless Class.respond_to?(:cattr_accessor)
|
|
98
|
+
|
|
99
|
+
# Defines class-level inheritable attribute reader. Attributes are available to subclasses,
|
|
100
|
+
# each subclass has a copy of parent's attribute.
|
|
101
|
+
#
|
|
102
|
+
# @param *syms<Array[#to_s]> Array of attributes to define inheritable reader for.
|
|
103
|
+
# @return <Array[#to_s]> Array of attributes converted into inheritable_readers.
|
|
104
|
+
#
|
|
105
|
+
# @api public
|
|
106
|
+
#
|
|
107
|
+
# @todo Do we want to block instance_reader via :instance_reader => false
|
|
108
|
+
# @todo It would be preferable that we do something with a Hash passed in
|
|
109
|
+
# (error out or do the same as other methods above) instead of silently
|
|
110
|
+
# moving on). In particular, this makes the return value of this function
|
|
111
|
+
# less useful.
|
|
112
|
+
def extlib_inheritable_reader(*ivars)
|
|
113
|
+
instance_reader = ivars.pop[:reader] if ivars.last.is_a?(Hash)
|
|
114
|
+
|
|
115
|
+
ivars.each do |ivar|
|
|
116
|
+
self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
|
117
|
+
def self.#{ivar}
|
|
118
|
+
return @#{ivar} if self.object_id == #{self.object_id} || defined?(@#{ivar})
|
|
119
|
+
ivar = superclass.#{ivar}
|
|
120
|
+
return nil if ivar.nil? && !#{self}.instance_variable_defined?("@#{ivar}")
|
|
121
|
+
@#{ivar} = ivar && !ivar.is_a?(Module) && !ivar.is_a?(Numeric) && !ivar.is_a?(TrueClass) && !ivar.is_a?(FalseClass) ? ivar.dup : ivar
|
|
143
122
|
end
|
|
123
|
+
RUBY
|
|
124
|
+
unless instance_reader == false
|
|
125
|
+
self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
|
126
|
+
def #{ivar}
|
|
127
|
+
self.class.#{ivar}
|
|
128
|
+
end
|
|
129
|
+
RUBY
|
|
144
130
|
end
|
|
145
|
-
|
|
146
|
-
# Defines class-level inheritable attribute writer. Attributes are available to subclasses,
|
|
147
|
-
# each subclass has a copy of parent's attribute.
|
|
148
|
-
#
|
|
149
|
-
# @param *syms<Array[*#to_s, Hash{:instance_writer => Boolean}]> Array of attributes to
|
|
150
|
-
# define inheritable writer for.
|
|
151
|
-
# @option syms :instance_writer<Boolean> if true, instance-level inheritable attribute writer is defined.
|
|
152
|
-
# @return <Array[#to_s]> An Array of the attributes that were made into inheritable writers.
|
|
153
|
-
#
|
|
154
|
-
# @api public
|
|
155
|
-
#
|
|
156
|
-
# @todo We need a style for class_eval <<-HEREDOC. I'd like to make it
|
|
157
|
-
# class_eval(<<-RUBY, __FILE__, __LINE__), but we should codify it somewhere.
|
|
158
|
-
def class_inheritable_writer(*ivars)
|
|
159
|
-
instance_writer = ivars.pop[:instance_writer] if ivars.last.is_a?(Hash)
|
|
160
|
-
ivars.each do |ivar|
|
|
161
|
-
self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
|
162
|
-
def self.#{ivar}=(obj)
|
|
163
|
-
@#{ivar} = obj
|
|
164
131
|
end
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
132
|
+
end unless Class.respond_to?(:extlib_inheritable_reader)
|
|
133
|
+
|
|
134
|
+
# Defines class-level inheritable attribute writer. Attributes are available to subclasses,
|
|
135
|
+
# each subclass has a copy of parent's attribute.
|
|
136
|
+
#
|
|
137
|
+
# @param *syms<Array[*#to_s, Hash{:instance_writer => Boolean}]> Array of attributes to
|
|
138
|
+
# define inheritable writer for.
|
|
139
|
+
# @option syms :instance_writer<Boolean> if true, instance-level inheritable attribute writer is defined.
|
|
140
|
+
# @return <Array[#to_s]> An Array of the attributes that were made into inheritable writers.
|
|
141
|
+
#
|
|
142
|
+
# @api public
|
|
143
|
+
#
|
|
144
|
+
# @todo We need a style for class_eval <<-HEREDOC. I'd like to make it
|
|
145
|
+
# class_eval(<<-RUBY, __FILE__, __LINE__), but we should codify it somewhere.
|
|
146
|
+
def extlib_inheritable_writer(*ivars)
|
|
147
|
+
instance_writer = ivars.pop[:writer] if ivars.last.is_a?(Hash)
|
|
148
|
+
ivars.each do |ivar|
|
|
149
|
+
self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
|
150
|
+
def self.#{ivar}=(obj)
|
|
151
|
+
@#{ivar} = obj
|
|
171
152
|
end
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
# @param *syms<Array[*#to_s, Hash{:instance_writer => Boolean}]> Array of attributes to
|
|
178
|
-
# define inheritable accessor for.
|
|
179
|
-
# @option syms :instance_writer<Boolean> if true, instance-level inheritable attribute writer is defined.
|
|
180
|
-
# @return <Array[#to_s]> An Array of attributes turned into inheritable accessors.
|
|
181
|
-
#
|
|
182
|
-
# @api public
|
|
183
|
-
def class_inheritable_accessor(*syms)
|
|
184
|
-
class_inheritable_reader(*syms)
|
|
185
|
-
class_inheritable_writer(*syms)
|
|
153
|
+
RUBY
|
|
154
|
+
unless instance_writer == false
|
|
155
|
+
self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
|
156
|
+
def #{ivar}=(obj) self.class.#{ivar} = obj end
|
|
157
|
+
RUBY
|
|
186
158
|
end
|
|
187
159
|
end
|
|
188
|
-
end
|
|
160
|
+
end unless Class.respond_to?(:extlib_inheritable_writer)
|
|
161
|
+
|
|
162
|
+
# Defines class-level inheritable attribute accessor. Attributes are available to subclasses,
|
|
163
|
+
# each subclass has a copy of parent's attribute.
|
|
164
|
+
#
|
|
165
|
+
# @param *syms<Array[*#to_s, Hash{:instance_writer => Boolean}]> Array of attributes to
|
|
166
|
+
# define inheritable accessor for.
|
|
167
|
+
# @option syms :instance_writer<Boolean> if true, instance-level inheritable attribute writer is defined.
|
|
168
|
+
# @return <Array[#to_s]> An Array of attributes turned into inheritable accessors.
|
|
169
|
+
#
|
|
170
|
+
# @api public
|
|
171
|
+
def extlib_inheritable_accessor(*syms)
|
|
172
|
+
extlib_inheritable_reader(*syms)
|
|
173
|
+
extlib_inheritable_writer(*syms)
|
|
174
|
+
end unless Class.respond_to?(:extlib_inheritable_accessor)
|
|
189
175
|
end
|
|
190
176
|
|
|
191
|
-
Class.send(:include, CouchRest::ClassExtension)
|
|
@@ -60,7 +60,7 @@ module CouchRest
|
|
|
60
60
|
cattr_writer :default_error_messages
|
|
61
61
|
|
|
62
62
|
def self.default_error_message(key, field, *values)
|
|
63
|
-
field =
|
|
63
|
+
field = CouchRest.humanize(field)
|
|
64
64
|
@@default_error_messages[key] % [field, *values].flatten
|
|
65
65
|
end
|
|
66
66
|
|
|
@@ -64,7 +64,7 @@ module CouchRest
|
|
|
64
64
|
|
|
65
65
|
error_message = @options[:message] || ValidationErrors.default_error_message(:invalid, field_name)
|
|
66
66
|
|
|
67
|
-
field =
|
|
67
|
+
field = CouchRest.humanize(field_name)
|
|
68
68
|
error_message = error_message.call(field, value) if error_message.respond_to?(:call)
|
|
69
69
|
|
|
70
70
|
add_error(target, error_message, field_name)
|
|
@@ -54,7 +54,7 @@ module CouchRest
|
|
|
54
54
|
|
|
55
55
|
# XXX: HACK seems hacky to do this on every validation, probably should
|
|
56
56
|
# do this elsewhere?
|
|
57
|
-
field =
|
|
57
|
+
field = CouchRest.humanize(field_name)
|
|
58
58
|
min = @range ? @range.min : @min
|
|
59
59
|
max = @range ? @range.max : @max
|
|
60
60
|
equal = @equal
|
|
@@ -149,8 +149,8 @@ describe CouchRest::Database do
|
|
|
149
149
|
{"mild" => "yet local"},
|
|
150
150
|
{"another" => ["set","of","keys"]}
|
|
151
151
|
])
|
|
152
|
-
rs
|
|
153
|
-
@db.get(r['id'])
|
|
152
|
+
rs.each do |r|
|
|
153
|
+
@db.get(r['id']).rev.should == r["rev"]
|
|
154
154
|
end
|
|
155
155
|
end
|
|
156
156
|
|
|
@@ -170,26 +170,10 @@ describe CouchRest::Database do
|
|
|
170
170
|
{"_id" => "twoB", "mild" => "yet local"},
|
|
171
171
|
{"another" => ["set","of","keys"]}
|
|
172
172
|
])
|
|
173
|
-
rs
|
|
174
|
-
@db.get(r['id'])
|
|
173
|
+
rs.each do |r|
|
|
174
|
+
@db.get(r['id']).rev.should == r["rev"]
|
|
175
175
|
end
|
|
176
176
|
end
|
|
177
|
-
|
|
178
|
-
it "in the case of an id conflict should not insert anything" do
|
|
179
|
-
@r = @db.save_doc({'lemons' => 'from texas', 'and' => 'how', "_id" => "oneB"})
|
|
180
|
-
|
|
181
|
-
lambda do
|
|
182
|
-
rs = @db.bulk_save([
|
|
183
|
-
{"_id" => "oneB", "wild" => "and random"},
|
|
184
|
-
{"_id" => "twoB", "mild" => "yet local"},
|
|
185
|
-
{"another" => ["set","of","keys"]}
|
|
186
|
-
])
|
|
187
|
-
end.should raise_error(RestClient::RequestFailed)
|
|
188
|
-
|
|
189
|
-
lambda do
|
|
190
|
-
@db.get('twoB')
|
|
191
|
-
end.should raise_error(RestClient::ResourceNotFound)
|
|
192
|
-
end
|
|
193
177
|
|
|
194
178
|
it "should empty the bulk save cache if no documents are given" do
|
|
195
179
|
@db.save_doc({"_id" => "bulk_cache_1", "val" => "test"}, true)
|
|
@@ -570,49 +554,6 @@ describe CouchRest::Database do
|
|
|
570
554
|
end
|
|
571
555
|
end
|
|
572
556
|
|
|
573
|
-
describe "MOVE existing document" do
|
|
574
|
-
before :each do
|
|
575
|
-
@r = @db.save_doc({'artist' => 'Zappa', 'title' => 'Muffin Man'})
|
|
576
|
-
@docid = 'tracks/zappa/muffin-man'
|
|
577
|
-
@doc = @db.get(@r['id'])
|
|
578
|
-
end
|
|
579
|
-
describe "to a new location" do
|
|
580
|
-
it "should work" do
|
|
581
|
-
@db.move_doc @doc, @docid
|
|
582
|
-
newdoc = @db.get(@docid)
|
|
583
|
-
newdoc['artist'].should == 'Zappa'
|
|
584
|
-
lambda {@db.get(@r['id'])}.should raise_error(RestClient::ResourceNotFound)
|
|
585
|
-
end
|
|
586
|
-
it "should fail without an _id or _rev" do
|
|
587
|
-
lambda{@db.move({"not"=>"a real doc"})}.should raise_error(ArgumentError)
|
|
588
|
-
lambda{@db.move({"_id"=>"not a real doc"})}.should raise_error(ArgumentError)
|
|
589
|
-
end
|
|
590
|
-
end
|
|
591
|
-
describe "to an existing location" do
|
|
592
|
-
before :each do
|
|
593
|
-
@db.save_doc({'_id' => @docid, 'will-exist' => 'here'})
|
|
594
|
-
end
|
|
595
|
-
it "should fail without a rev" do
|
|
596
|
-
lambda{@db.move_doc @doc, @docid}.should raise_error(RestClient::RequestFailed)
|
|
597
|
-
lambda{@db.get(@r['id'])}.should_not raise_error
|
|
598
|
-
end
|
|
599
|
-
it "should succeed with a rev" do
|
|
600
|
-
@to_be_overwritten = @db.get(@docid)
|
|
601
|
-
@db.move_doc @doc, "#{@docid}?rev=#{@to_be_overwritten['_rev']}"
|
|
602
|
-
newdoc = @db.get(@docid)
|
|
603
|
-
newdoc['artist'].should == 'Zappa'
|
|
604
|
-
lambda {@db.get(@r['id'])}.should raise_error(RestClient::ResourceNotFound)
|
|
605
|
-
end
|
|
606
|
-
it "should succeed given the doc to overwrite" do
|
|
607
|
-
@to_be_overwritten = @db.get(@docid)
|
|
608
|
-
@db.move_doc @doc, @to_be_overwritten
|
|
609
|
-
newdoc = @db.get(@docid)
|
|
610
|
-
newdoc['artist'].should == 'Zappa'
|
|
611
|
-
lambda {@db.get(@r['id'])}.should raise_error(RestClient::ResourceNotFound)
|
|
612
|
-
end
|
|
613
|
-
end
|
|
614
|
-
end
|
|
615
|
-
|
|
616
557
|
|
|
617
558
|
it "should list documents" do
|
|
618
559
|
5.times do
|
|
@@ -199,50 +199,6 @@ describe CouchRest::Document do
|
|
|
199
199
|
end
|
|
200
200
|
end
|
|
201
201
|
end
|
|
202
|
-
|
|
203
|
-
describe "MOVE existing document" do
|
|
204
|
-
before :each do
|
|
205
|
-
@db = reset_test_db!
|
|
206
|
-
@resp = @db.save_doc({'key' => 'value'})
|
|
207
|
-
@docid = 'new-location'
|
|
208
|
-
@doc = @db.get(@resp['id'])
|
|
209
|
-
end
|
|
210
|
-
describe "to a new location" do
|
|
211
|
-
it "should work" do
|
|
212
|
-
@doc.move @docid
|
|
213
|
-
newdoc = @db.get(@docid)
|
|
214
|
-
newdoc['key'].should == 'value'
|
|
215
|
-
lambda {@db.get(@resp['id'])}.should raise_error(RestClient::ResourceNotFound)
|
|
216
|
-
end
|
|
217
|
-
it "should fail without a database" do
|
|
218
|
-
lambda{CouchRest::Document.new({"not"=>"a real doc"}).move}.should raise_error(ArgumentError)
|
|
219
|
-
lambda{CouchRest::Document.new({"_id"=>"not a real doc"}).move}.should raise_error(ArgumentError)
|
|
220
|
-
end
|
|
221
|
-
end
|
|
222
|
-
describe "to an existing location" do
|
|
223
|
-
before :each do
|
|
224
|
-
@db.save_doc({'_id' => @docid, 'will-exist' => 'here'})
|
|
225
|
-
end
|
|
226
|
-
it "should fail without a rev" do
|
|
227
|
-
lambda{@doc.move @docid}.should raise_error(RestClient::RequestFailed)
|
|
228
|
-
lambda{@db.get(@resp['id'])}.should_not raise_error
|
|
229
|
-
end
|
|
230
|
-
it "should succeed with a rev" do
|
|
231
|
-
@to_be_overwritten = @db.get(@docid)
|
|
232
|
-
@doc.move "#{@docid}?rev=#{@to_be_overwritten['_rev']}"
|
|
233
|
-
newdoc = @db.get(@docid)
|
|
234
|
-
newdoc['key'].should == 'value'
|
|
235
|
-
lambda {@db.get(@resp['id'])}.should raise_error(RestClient::ResourceNotFound)
|
|
236
|
-
end
|
|
237
|
-
it "should succeed given the doc to overwrite" do
|
|
238
|
-
@to_be_overwritten = @db.get(@docid)
|
|
239
|
-
@doc.move @to_be_overwritten
|
|
240
|
-
newdoc = @db.get(@docid)
|
|
241
|
-
newdoc['key'].should == 'value'
|
|
242
|
-
lambda {@db.get(@resp['id'])}.should raise_error(RestClient::ResourceNotFound)
|
|
243
|
-
end
|
|
244
|
-
end
|
|
245
|
-
end
|
|
246
202
|
end
|
|
247
203
|
|
|
248
204
|
describe "dealing with attachments" do
|
|
@@ -70,6 +70,7 @@ describe CouchRest::CastedModel do
|
|
|
70
70
|
|
|
71
71
|
describe "saved document with casted models" do
|
|
72
72
|
before(:each) do
|
|
73
|
+
reset_test_db!
|
|
73
74
|
@obj = DummyModel.new(:casted_attribute => {:name => 'whatever'})
|
|
74
75
|
@obj.save.should be_true
|
|
75
76
|
@obj = DummyModel.get(@obj.id)
|
|
@@ -94,4 +95,4 @@ describe CouchRest::CastedModel do
|
|
|
94
95
|
|
|
95
96
|
end
|
|
96
97
|
|
|
97
|
-
end
|
|
98
|
+
end
|
|
@@ -4,6 +4,7 @@ describe "ExtendedDocument attachments" do
|
|
|
4
4
|
|
|
5
5
|
describe "#has_attachment?" do
|
|
6
6
|
before(:each) do
|
|
7
|
+
reset_test_db!
|
|
7
8
|
@obj = Basic.new
|
|
8
9
|
@obj.save.should == true
|
|
9
10
|
@file = File.open(FIXTURE_PATH + '/attachments/test.html')
|
|
@@ -126,4 +127,4 @@ describe "ExtendedDocument attachments" do
|
|
|
126
127
|
@obj.attachment_url(@attachment_name).should == "#{Basic.database}/#{@obj.id}/#{@attachment_name}"
|
|
127
128
|
end
|
|
128
129
|
end
|
|
129
|
-
end
|
|
130
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper'
|
|
2
|
+
require File.join(FIXTURE_PATH, 'more', 'card')
|
|
3
|
+
|
|
4
|
+
# add a default value
|
|
5
|
+
Card.property :bg_color, :default => '#ccc'
|
|
6
|
+
|
|
7
|
+
class BusinessCard < Card
|
|
8
|
+
property :extension_code
|
|
9
|
+
property :job_title
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
class DesignBusinessCard < BusinessCard
|
|
13
|
+
property :bg_color, :default => '#eee'
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
describe "Subclassing an ExtendedDocument" do
|
|
18
|
+
|
|
19
|
+
before(:each) do
|
|
20
|
+
@card = BusinessCard.new
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it "shouldn't messup the parent's properties" do
|
|
24
|
+
Card.properties.should_not == BusinessCard.properties
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it "should share the same db default" do
|
|
28
|
+
@card.database.uri.should == Card.database.uri
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it "should share the same autovalidation details" do
|
|
32
|
+
@card.auto_validation.should be_true
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it "should have kept the validation details" do
|
|
36
|
+
@card.should_not be_valid
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it "should have added the new validation details" do
|
|
40
|
+
validated_fields = @card.class.validators.contexts[:default].map{|v| v.field_name}
|
|
41
|
+
validated_fields.should include(:extension_code)
|
|
42
|
+
validated_fields.should include(:job_title)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it "should inherit default property values" do
|
|
46
|
+
@card.bg_color.should == '#ccc'
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it "should be able to overwrite a default property" do
|
|
50
|
+
DesignBusinessCard.new.bg_color.should == '#eee'
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
end
|
|
54
|
+
|
|
@@ -190,6 +190,7 @@ describe "ExtendedDocument views" do
|
|
|
190
190
|
|
|
191
191
|
describe "with a lot of designs left around" do
|
|
192
192
|
before(:each) do
|
|
193
|
+
reset_test_db!
|
|
193
194
|
Article.by_date
|
|
194
195
|
Article.view_by :field
|
|
195
196
|
Article.by_field
|
|
@@ -203,4 +204,4 @@ describe "ExtendedDocument views" do
|
|
|
203
204
|
ddocs["rows"].length.should == 1
|
|
204
205
|
end
|
|
205
206
|
end
|
|
206
|
-
end
|
|
207
|
+
end
|
|
@@ -8,6 +8,7 @@ require File.join(FIXTURE_PATH, 'more', 'event')
|
|
|
8
8
|
describe "ExtendedDocument properties" do
|
|
9
9
|
|
|
10
10
|
before(:each) do
|
|
11
|
+
reset_test_db!
|
|
11
12
|
@card = Card.new(:first_name => "matt")
|
|
12
13
|
end
|
|
13
14
|
|
|
@@ -126,4 +127,4 @@ describe "ExtendedDocument properties" do
|
|
|
126
127
|
end
|
|
127
128
|
end
|
|
128
129
|
|
|
129
|
-
end
|
|
130
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: mattetti-couchrest
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: "0.
|
|
4
|
+
version: "0.22"
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- J. Chris Anderson
|
|
@@ -89,6 +89,7 @@ files:
|
|
|
89
89
|
- lib/couchrest/helper
|
|
90
90
|
- lib/couchrest/helper/pager.rb
|
|
91
91
|
- lib/couchrest/helper/streamer.rb
|
|
92
|
+
- lib/couchrest/helper/upgrade.rb
|
|
92
93
|
- lib/couchrest/mixins
|
|
93
94
|
- lib/couchrest/mixins/attachments.rb
|
|
94
95
|
- lib/couchrest/mixins/callbacks.rb
|
|
@@ -140,10 +141,9 @@ files:
|
|
|
140
141
|
- spec/couchrest/more/casted_model_spec.rb
|
|
141
142
|
- spec/couchrest/more/extended_doc_attachment_spec.rb
|
|
142
143
|
- spec/couchrest/more/extended_doc_spec.rb
|
|
144
|
+
- spec/couchrest/more/extended_doc_subclass_spec.rb
|
|
143
145
|
- spec/couchrest/more/extended_doc_view_spec.rb
|
|
144
146
|
- spec/couchrest/more/property_spec.rb
|
|
145
|
-
- spec/couchrest/support
|
|
146
|
-
- spec/couchrest/support/class_spec.rb
|
|
147
147
|
- spec/fixtures
|
|
148
148
|
- spec/fixtures/attachments
|
|
149
149
|
- spec/fixtures/attachments/couchdb.png
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
require File.join(File.dirname(__FILE__), '..', '..', 'spec_helper')
|
|
2
|
-
require File.join(File.dirname(__FILE__), '..', '..', '..', 'lib', 'couchrest', 'support', 'class')
|
|
3
|
-
|
|
4
|
-
describe CouchRest::ClassExtension do
|
|
5
|
-
|
|
6
|
-
before :all do
|
|
7
|
-
class FullyDefinedClassExtensions
|
|
8
|
-
def self.respond_to?(method)
|
|
9
|
-
if CouchRest::ClassExtension::InstanceMethods.instance_methods.include?(method)
|
|
10
|
-
true
|
|
11
|
-
else
|
|
12
|
-
super
|
|
13
|
-
end
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
class PartDefinedClassExtensions
|
|
18
|
-
def self.respond_to?(method)
|
|
19
|
-
methods = CouchRest::ClassExtension::InstanceMethods.instance_methods
|
|
20
|
-
methods.delete('cattr_reader')
|
|
21
|
-
|
|
22
|
-
if methods.include?(method)
|
|
23
|
-
false
|
|
24
|
-
else
|
|
25
|
-
super
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
class NoClassExtensions
|
|
31
|
-
def self.respond_to?(method)
|
|
32
|
-
if CouchRest::ClassExtension::InstanceMethods.instance_methods.include?(method)
|
|
33
|
-
false
|
|
34
|
-
else
|
|
35
|
-
super
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
it "should not include InstanceMethods if the class extensions are already defined" do
|
|
44
|
-
FullyDefinedClassExtensions.send(:include, CouchRest::ClassExtension)
|
|
45
|
-
FullyDefinedClassExtensions.ancestors.should_not include(CouchRest::ClassExtension::InstanceMethods)
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
it "should raise RuntimeError if the class extensions are only partially defined" do
|
|
49
|
-
lambda {
|
|
50
|
-
PartDefinedClassExtensions.send(:include, CouchRest::ClassExtension)
|
|
51
|
-
}.should raise_error(RuntimeError)
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
it "should include class extensions if they are not already defined" do
|
|
55
|
-
NoClassExtensions.send(:include, CouchRest::ClassExtension)
|
|
56
|
-
NoClassExtensions.ancestors.should include(CouchRest::ClassExtension::InstanceMethods)
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
end
|