samlown-couchrest_extended_document 1.0.1 → 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -11,7 +11,9 @@ Note: CouchRest only supports CouchDB 0.9.0 or newer.
11
11
 
12
12
  ## Usage
13
13
 
14
- require 'couchrest/extended_document'
14
+ ### General
15
+
16
+ require 'couchrest_extended_document'
15
17
 
16
18
  class Cat < CouchRest::ExtendedDocument
17
19
 
@@ -19,6 +21,16 @@ Note: CouchRest only supports CouchDB 0.9.0 or newer.
19
21
 
20
22
  end
21
23
 
24
+ ### Rails
25
+
26
+ In your environment.rb file require the gem as follows:
27
+
28
+ Rails::Initializer.run do |config|
29
+ ....
30
+ config.gem "couchrest_extended_document"
31
+ ....
32
+ end
33
+
22
34
  ## Testing
23
35
 
24
36
  The most complete documentation is the spec/ directory. To validate your
data/Rakefile CHANGED
@@ -1,6 +1,6 @@
1
1
  require 'rake'
2
2
  require "rake/rdoctask"
3
- require File.join(File.expand_path(File.dirname(__FILE__)),'lib','couchrest','extended_document')
3
+ require File.join(File.expand_path(File.dirname(__FILE__)),'lib','couchrest_extended_document')
4
4
 
5
5
  begin
6
6
  require 'spec/rake/spectask'
data/history.txt CHANGED
@@ -4,11 +4,29 @@
4
4
 
5
5
  * Minor enhancements
6
6
 
7
- == 0.4.0
7
+ == 1.0.3
8
+
9
+ * Minor enhancements
10
+ * Removed Validation by default, requires too many structure changes (FAIL)
11
+ * Added support for instantiation of documents read from database as couchrest-type provided (Sam Lown)
12
+ * Improved attachment handling for detecting file type (Sam Lown)
13
+ * Removing some monkey patches and relying on active_support for constantize and humanize (Sam Lown)
14
+ * Added support for setting type directly on property (Sam Lown)
15
+
16
+
17
+ == 1.0.2
18
+
19
+ * Minor enhancements
20
+ * Enable Validation by default and refactored location (Sam Lown)
21
+
22
+ == 1.0.0
8
23
 
9
24
  * Major enhancements
10
25
  * Separated ExtendedDocument from main CouchRest gem (Sam Lown)
11
26
 
27
+ * Minor enhancements
28
+ * active_support included by default
29
+
12
30
  == 0.37
13
31
 
14
32
  * Minor enhancements
@@ -1,22 +1,14 @@
1
- gem 'samlown-couchrest'
2
- require 'couchrest'
3
- require 'active_support'
4
- require 'mime/types'
5
- require "enumerator"
1
+
6
2
  require File.join(File.dirname(__FILE__), "property")
3
+ require File.join(File.dirname(__FILE__), "validation")
7
4
  require File.join(File.dirname(__FILE__), 'mixins')
8
- require File.join(File.dirname(__FILE__), 'casted_model')
9
-
10
- # Monkey patches
11
- require File.join(File.dirname(__FILE__), 'support', 'couchrest')
12
- require File.join(File.dirname(__FILE__), 'support', 'rails') if defined?(Rails)
13
5
 
14
6
  module CouchRest
15
7
 
16
8
  # Same as CouchRest::Document but with properties and validations
17
9
  class ExtendedDocument < Document
18
10
 
19
- VERSION = "1.0.1"
11
+ VERSION = "1.0.3"
20
12
 
21
13
  include CouchRest::Mixins::Callbacks
22
14
  include CouchRest::Mixins::DocumentQueries
@@ -27,6 +19,9 @@ module CouchRest
27
19
  include CouchRest::Mixins::Collection
28
20
  include CouchRest::Mixins::AttributeProtection
29
21
 
22
+ # Including validation here does not work due to the way inheritance is handled.
23
+ #include CouchRest::Validation
24
+
30
25
  def self.subclasses
31
26
  @subclasses ||= []
32
27
  end
@@ -54,17 +49,19 @@ module CouchRest
54
49
 
55
50
  # Creates a new instance, bypassing attribute protection
56
51
  #
52
+ #
57
53
  # ==== Returns
58
54
  # a document instance
59
- def self.create_from_database(passed_keys={})
60
- new(passed_keys, :directly_set_attributes => true)
55
+ def self.create_from_database(doc = {})
56
+ base = (doc['couchrest-type'].blank? || doc['couchrest-type'] == self.to_s) ? self : doc['couchrest-type'].constantize
57
+ base.new(doc, :directly_set_attributes => true)
61
58
  end
62
59
 
63
- def initialize(passed_keys={}, options={})
60
+ def initialize(doc = {}, options = {})
64
61
  apply_defaults # defined in CouchRest::Mixins::Properties
65
- remove_protected_attributes(passed_keys) unless options[:directly_set_attributes]
66
- directly_set_attributes(passed_keys) unless passed_keys.nil?
67
- super(passed_keys)
62
+ remove_protected_attributes(doc) unless options[:directly_set_attributes]
63
+ directly_set_attributes(doc) unless doc.nil?
64
+ super(doc)
68
65
  cast_keys # defined in CouchRest::Mixins::Properties
69
66
  unless self['_id'] && self['_rev']
70
67
  self['couchrest-type'] = self.class.to_s
@@ -5,7 +5,6 @@ require File.join(mixins_dir, 'properties')
5
5
  require File.join(mixins_dir, 'document_queries')
6
6
  require File.join(mixins_dir, 'views')
7
7
  require File.join(mixins_dir, 'design_doc')
8
- require File.join(mixins_dir, 'validation')
9
8
  require File.join(mixins_dir, 'extended_attachments')
10
9
  require File.join(mixins_dir, 'class_proxy')
11
10
  require File.join(mixins_dir, 'collection')
@@ -2,7 +2,8 @@ module CouchRest
2
2
  module Mixins
3
3
  module ExtendedAttachments
4
4
 
5
- # creates a file attachment to the current doc
5
+ # Add a file attachment to the current document. Expects
6
+ # :file and :name to be included in the arguments.
6
7
  def create_attachment(args={})
7
8
  raise ArgumentError unless args[:file] && args[:name]
8
9
  return if has_attachment?(args[:name])
@@ -52,13 +53,14 @@ module CouchRest
52
53
 
53
54
  private
54
55
 
55
- def get_mime_type(file)
56
- ::MIME::Types.type_for(file.path).empty? ?
57
- 'text\/plain' : MIME::Types.type_for(file.path).first.content_type.gsub(/\//,'\/')
56
+ def get_mime_type(path)
57
+ type = ::MIME::Types.type_for(path)
58
+ type.empty? ? nil : type.first.content_type
58
59
  end
59
60
 
60
61
  def set_attachment_attr(args)
61
- content_type = args[:content_type] ? args[:content_type] : get_mime_type(args[:file])
62
+ content_type = args[:content_type] ? args[:content_type] : get_mime_type(args[:file].path)
63
+ content_type ||= (get_mime_type(args[:name]) || 'text/plain')
62
64
  self['_attachments'][args[:name]] = {
63
65
  'content_type' => content_type,
64
66
  'data' => args[:file].read
@@ -82,10 +82,18 @@ module CouchRest
82
82
 
83
83
  module ClassMethods
84
84
 
85
- def property(name, options={})
85
+ def property(name, *options)
86
+ opts = { }
87
+ type = options.shift
88
+ if type.class != Hash
89
+ opts[:type] = type
90
+ opts.merge!(options.shift || {})
91
+ else
92
+ opts.update(type)
93
+ end
86
94
  existing_property = self.properties.find{|p| p.name == name.to_s}
87
- if existing_property.nil? || (existing_property.default != options[:default])
88
- define_property(name, options)
95
+ if existing_property.nil? || (existing_property.default != opts[:default])
96
+ define_property(name, opts)
89
97
  end
90
98
  end
91
99
 
@@ -26,7 +26,7 @@ module CouchRest
26
26
  base_type = TrueClass
27
27
  else
28
28
  begin
29
- base_type = ::CouchRest.constantize(base_type)
29
+ base_type = base_type.constantize
30
30
  rescue # leave base type as a string and convert in more/typecast
31
31
  end
32
32
  end
@@ -1,43 +1,6 @@
1
1
 
2
2
  module CouchRest
3
3
 
4
-
5
- # The CouchRest module methods handle the basic JSON serialization
6
- # and deserialization, as well as query parameters. The module also includes
7
- # some helpers for tasks like instantiating a new Database or Server instance.
8
- class << self
9
-
10
- # extracted from Extlib
11
- #
12
- # Constantize tries to find a declared constant with the name specified
13
- # in the string. It raises a NameError when the name is not in CamelCase
14
- # or is not initialized.
15
- #
16
- # @example
17
- # "Module".constantize #=> Module
18
- # "Class".constantize #=> Class
19
- def constantize(camel_cased_word)
20
- unless /\A(?:::)?([A-Z]\w*(?:::[A-Z]\w*)*)\z/ =~ camel_cased_word
21
- raise NameError, "#{camel_cased_word.inspect} is not a valid constant name!"
22
- end
23
-
24
- Object.module_eval("::#{$1}", __FILE__, __LINE__)
25
- end
26
-
27
- # extracted from Extlib
28
- #
29
- # Capitalizes the first word and turns underscores into spaces and strips _id.
30
- # Like titleize, this is meant for creating pretty output.
31
- #
32
- # @example
33
- # "employee_salary" #=> "Employee salary"
34
- # "author_id" #=> "Author"
35
- def humanize(lower_case_and_underscored_word)
36
- lower_case_and_underscored_word.to_s.gsub(/_id$/, "").gsub(/_/, " ").capitalize
37
- end
38
-
39
- end
40
-
41
4
  class Database
42
5
 
43
6
  alias :delete_old! :delete!
@@ -28,7 +28,7 @@ module CouchRest
28
28
 
29
29
  def typecast_value(value, klass, init_method)
30
30
  return nil if value.nil?
31
- klass = ::CouchRest.constantize(klass) unless klass.is_a?(Class)
31
+ klass = klass.constantize unless klass.is_a?(Class)
32
32
  if value.instance_of?(klass) || klass == Object
33
33
  value
34
34
  elsif [String, TrueClass, Integer, Float, BigDecimal, DateTime, Time, Date, Class].include?(klass)
@@ -164,7 +164,7 @@ module CouchRest
164
164
 
165
165
  # Typecast a value to a Class
166
166
  def typecast_to_class(value)
167
- ::CouchRest.constantize(value.to_s)
167
+ value.to_s.constantize
168
168
  rescue NameError
169
169
  value
170
170
  end
@@ -0,0 +1,245 @@
1
+ # Extracted from dm-validations 0.9.10
2
+ #
3
+ # Copyright (c) 2007 Guy van den Berg
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining
6
+ # a copy of this software and associated documentation files (the
7
+ # "Software"), to deal in the Software without restriction, including
8
+ # without limitation the rights to use, copy, modify, merge, publish,
9
+ # distribute, sublicense, and/or sell copies of the Software, and to
10
+ # permit persons to whom the Software is furnished to do so, subject to
11
+ # the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be
14
+ # included in all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+
24
+ class Object
25
+ def validatable?
26
+ false
27
+ end
28
+ end
29
+
30
+ require 'pathname'
31
+
32
+ dir = File.join(Pathname(__FILE__).dirname.expand_path, 'validation')
33
+
34
+ require File.join(dir, 'validation_errors')
35
+ require File.join(dir, 'contextual_validators')
36
+ require File.join(dir, 'auto_validate')
37
+
38
+ require File.join(dir, 'validators', 'generic_validator')
39
+ require File.join(dir, 'validators', 'required_field_validator')
40
+ require File.join(dir, 'validators', 'absent_field_validator')
41
+ require File.join(dir, 'validators', 'format_validator')
42
+ require File.join(dir, 'validators', 'length_validator')
43
+ require File.join(dir, 'validators', 'numeric_validator')
44
+ require File.join(dir, 'validators', 'method_validator')
45
+ require File.join(dir, 'validators', 'confirmation_validator')
46
+
47
+ module CouchRest
48
+ module Validation
49
+
50
+ def self.included(base)
51
+ base.extlib_inheritable_accessor(:auto_validation)
52
+ base.class_eval <<-EOS, __FILE__, __LINE__ + 1
53
+ # Callbacks
54
+ define_callbacks :validate
55
+
56
+ # Turn off auto validation by default
57
+ self.auto_validation ||= false
58
+
59
+ # Force the auto validation for the class properties
60
+ # This feature is still not fully ported over,
61
+ # test are lacking, so please use with caution
62
+ def self.auto_validate!
63
+ self.auto_validation = true
64
+ end
65
+
66
+ # share the validations with subclasses
67
+ def self.inherited(subklass)
68
+ self.validators.contexts.each do |k, v|
69
+ subklass.validators.contexts[k] = v.dup
70
+ end
71
+ super
72
+ end
73
+ EOS
74
+
75
+ base.extend(ClassMethods)
76
+ base.class_eval <<-EOS, __FILE__, __LINE__ + 1
77
+ define_callbacks :validate
78
+ if method_defined?(:_run_save_callbacks)
79
+ set_callback :save, :before, :check_validations
80
+ end
81
+ EOS
82
+ base.class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
83
+ def self.define_property(name, options={})
84
+ super
85
+ auto_generate_validations(properties.last) if properties && properties.size > 0
86
+ autovalidation_check = true
87
+ end
88
+ RUBY_EVAL
89
+ end
90
+
91
+ # Ensures the object is valid for the context provided, and otherwise
92
+ # throws :halt and returns false.
93
+ #
94
+ def check_validations(context = :default)
95
+ throw(:halt, false) unless context.nil? || valid?(context)
96
+ end
97
+
98
+ # Return the ValidationErrors
99
+ #
100
+ def errors
101
+ @errors ||= ValidationErrors.new
102
+ end
103
+
104
+ # Mark this resource as validatable. When we validate associations of a
105
+ # resource we can check if they respond to validatable? before trying to
106
+ # recursivly validate them
107
+ #
108
+ def validatable?
109
+ true
110
+ end
111
+
112
+ # Alias for valid?(:default)
113
+ #
114
+ def valid_for_default?
115
+ valid?(:default)
116
+ end
117
+
118
+ # Check if a resource is valid in a given context
119
+ #
120
+ def valid?(context = :default)
121
+ recursive_valid?(self, context, true)
122
+ end
123
+
124
+ # checking on casted objects
125
+ def validate_casted_arrays
126
+ result = true
127
+ array_casted_properties = self.class.properties.select { |property| property.casted && property.type.instance_of?(Array) }
128
+ array_casted_properties.each do |property|
129
+ casted_values = self.send(property.name)
130
+ next unless casted_values.is_a?(Array) && casted_values.first.respond_to?(:valid?)
131
+ casted_values.each do |value|
132
+ result = (result && value.valid?) if value.respond_to?(:valid?)
133
+ end
134
+ end
135
+ result
136
+ end
137
+
138
+ # Do recursive validity checking
139
+ #
140
+ def recursive_valid?(target, context, state)
141
+ valid = state
142
+ target.each do |key, prop|
143
+ if prop.is_a?(Array)
144
+ prop.each do |item|
145
+ if item.validatable?
146
+ valid = recursive_valid?(item, context, valid) && valid
147
+ end
148
+ end
149
+ elsif prop.validatable?
150
+ valid = recursive_valid?(prop, context, valid) && valid
151
+ end
152
+ end
153
+ target._run_validate_callbacks do
154
+ target.class.validators.execute(context, target) && valid
155
+ end
156
+ end
157
+
158
+
159
+ def validation_property_value(name)
160
+ self.respond_to?(name, true) ? self.send(name) : nil
161
+ end
162
+
163
+ # Get the corresponding Object property, if it exists.
164
+ def validation_property(field_name)
165
+ properties.find{|p| p.name == field_name}
166
+ end
167
+
168
+ module ClassMethods
169
+ include CouchRest::Validation::ValidatesPresent
170
+ include CouchRest::Validation::ValidatesAbsent
171
+ include CouchRest::Validation::ValidatesIsConfirmed
172
+ # include CouchRest::Validation::ValidatesIsPrimitive
173
+ # include CouchRest::Validation::ValidatesIsAccepted
174
+ include CouchRest::Validation::ValidatesFormat
175
+ include CouchRest::Validation::ValidatesLength
176
+ # include CouchRest::Validation::ValidatesWithin
177
+ include CouchRest::Validation::ValidatesIsNumber
178
+ include CouchRest::Validation::ValidatesWithMethod
179
+ # include CouchRest::Validation::ValidatesWithBlock
180
+ # include CouchRest::Validation::ValidatesIsUnique
181
+ include CouchRest::Validation::AutoValidate
182
+
183
+ # Return the set of contextual validators or create a new one
184
+ #
185
+ def validators
186
+ @validations ||= ContextualValidators.new
187
+ end
188
+
189
+ # Clean up the argument list and return a opts hash, including the
190
+ # merging of any default opts. Set the context to default if none is
191
+ # provided. Also allow :context to be aliased to :on, :when & group
192
+ #
193
+ def opts_from_validator_args(args, defaults = nil)
194
+ opts = args.last.kind_of?(Hash) ? args.pop : {}
195
+ context = :default
196
+ context = opts[:context] if opts.has_key?(:context)
197
+ context = opts.delete(:on) if opts.has_key?(:on)
198
+ context = opts.delete(:when) if opts.has_key?(:when)
199
+ context = opts.delete(:group) if opts.has_key?(:group)
200
+ opts[:context] = context
201
+ opts.merge!(defaults) unless defaults.nil?
202
+ opts
203
+ end
204
+
205
+ # Given a new context create an instance method of
206
+ # valid_for_<context>? which simply calls valid?(context)
207
+ # if it does not already exist
208
+ #
209
+ def create_context_instance_methods(context)
210
+ name = "valid_for_#{context.to_s}?" # valid_for_signup?
211
+ if !self.instance_methods.include?(name)
212
+ class_eval <<-EOS, __FILE__, __LINE__ + 1
213
+ def #{name} # def valid_for_signup?
214
+ valid?('#{context.to_s}'.to_sym) # valid?('signup'.to_sym)
215
+ end # end
216
+ EOS
217
+ end
218
+ end
219
+
220
+ # Create a new validator of the given klazz and push it onto the
221
+ # requested context for each of the attributes in the fields list
222
+ #
223
+ def add_validator_to_context(opts, fields, klazz)
224
+ fields.each do |field|
225
+ validator = klazz.new(field.to_sym, opts)
226
+ if opts[:context].is_a?(Symbol)
227
+ unless validators.context(opts[:context]).include?(validator)
228
+ validators.context(opts[:context]) << validator
229
+ create_context_instance_methods(opts[:context])
230
+ end
231
+ elsif opts[:context].is_a?(Array)
232
+ opts[:context].each do |c|
233
+ unless validators.context(c).include?(validator)
234
+ validators.context(c) << validator
235
+ create_context_instance_methods(c)
236
+ end
237
+ end
238
+ end
239
+ end
240
+ end
241
+
242
+ end # module ClassMethods
243
+ end # module Validation
244
+
245
+ end # module CouchRest
@@ -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 = CouchRest.humanize(field)
63
+ field = field.to_s.humanize
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 = CouchRest.humanize(field_name)
67
+ field = field_name.to_s.humanize
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 = CouchRest.humanize(field_name)
57
+ field = field_name.to_s.humanize
58
58
  min = @range ? @range.min : @min
59
59
  max = @range ? @range.max : @max
60
60
  equal = @equal
@@ -0,0 +1,21 @@
1
+
2
+ # require File.join(File.dirname(__FILE__), "couchrest", "extended_document")
3
+
4
+ gem 'samlown-couchrest'
5
+
6
+ require 'couchrest'
7
+
8
+ require 'active_support'
9
+ require 'mime/types'
10
+ require "enumerator"
11
+
12
+ # Monkey patches applied to couchrest
13
+ require File.join(File.dirname(__FILE__), 'couchrest', 'support', 'couchrest')
14
+
15
+ # Base libraries
16
+ require File.join(File.dirname(__FILE__), 'couchrest', 'extended_document')
17
+ require File.join(File.dirname(__FILE__), 'couchrest', 'casted_model')
18
+
19
+ # Add rails support *after* everything has loaded
20
+ require File.join(File.dirname(__FILE__), 'couchrest', 'support', 'rails') if defined?(Rails)
21
+
@@ -68,6 +68,19 @@ describe "ExtendedDocument attachments" do
68
68
  @obj.create_attachment(:file => @file_ext, :name => @attachment_name, :content_type => @content_type)
69
69
  @obj['_attachments'][@attachment_name]['content_type'].should == @content_type
70
70
  end
71
+
72
+ it "should detect the content-type automatically" do
73
+ @obj.create_attachment(:file => File.open(FIXTURE_PATH + '/attachments/couchdb.png'), :name => "couchdb.png")
74
+ @obj['_attachments']['couchdb.png']['content_type'].should == "image/png"
75
+ end
76
+
77
+ it "should use name to detect the content-type automatically if no file" do
78
+ file = File.open(FIXTURE_PATH + '/attachments/couchdb.png')
79
+ file.stub!(:path).and_return("badfilname")
80
+ @obj.create_attachment(:file => File.open(FIXTURE_PATH + '/attachments/couchdb.png'), :name => "couchdb.png")
81
+ @obj['_attachments']['couchdb.png']['content_type'].should == "image/png"
82
+ end
83
+
71
84
  end
72
85
 
73
86
  describe 'reading, updating, and deleting an attachment' do
@@ -96,7 +109,7 @@ describe "ExtendedDocument attachments" do
96
109
  reloaded_obj.read_attachment(@attachment_name).should == file.read
97
110
  end
98
111
 
99
- it 'should se the content-type if passed' do
112
+ it 'should set the content-type if passed' do
100
113
  file = File.open(FIXTURE_PATH + '/attachments/README')
101
114
  @file.should_not == file
102
115
  @obj.update_attachment(:file => file, :name => @attachment_name, :content_type => @content_type)
@@ -18,6 +18,14 @@ describe "ExtendedDocument" do
18
18
  property :name
19
19
  timestamps!
20
20
  end
21
+
22
+ class WithSimplePropertyType < CouchRest::ExtendedDocument
23
+ use_database TEST_SERVER.default_database
24
+ property :name, String
25
+ property :preset, String, :default => 'none'
26
+ property :tags, [String]
27
+ timestamps!
28
+ end
21
29
 
22
30
  class WithCallBacks < CouchRest::ExtendedDocument
23
31
  include ::CouchRest::Validation
@@ -164,6 +172,25 @@ describe "ExtendedDocument" do
164
172
  doc.run_after_save.should be_true
165
173
  end
166
174
  end
175
+
176
+ describe "creating a new document from database" do
177
+
178
+ it "should instantialize" do
179
+ doc = Article.create_from_database({'_id' => 'testitem1', '_rev' => 123, 'couchrest-type' => 'Article', 'name' => 'my test'})
180
+ doc.class.should eql(Article)
181
+ end
182
+
183
+ it "should instantialize of same class if no couchrest-type included from DB" do
184
+ doc = Article.create_from_database({'_id' => 'testitem1', '_rev' => 123, 'name' => 'my test'})
185
+ doc.class.should eql(Article)
186
+ end
187
+
188
+ it "should instantialize document of different type" do
189
+ doc = Article.create_from_database({'_id' => 'testitem2', '_rev' => 123, 'couchrest-type' => 'WithCallBacks', 'name' => 'my test'})
190
+ doc.class.should eql(WithCallBacks)
191
+ end
192
+
193
+ end
167
194
 
168
195
  describe "update attributes without saving" do
169
196
  before(:each) do
@@ -258,6 +285,18 @@ describe "ExtendedDocument" do
258
285
  obj.read_only_with_default.should == 'generic'
259
286
  end
260
287
  end
288
+
289
+ describe "simplified way of setting property types" do
290
+ it "should set defaults" do
291
+ obj = WithSimplePropertyType.new
292
+ obj.preset.should eql('none')
293
+ end
294
+
295
+ it "should handle arrays" do
296
+ obj = WithSimplePropertyType.new(:tags => ['spec'])
297
+ obj.tags.should == ['spec']
298
+ end
299
+ end
261
300
 
262
301
  describe "a doc with template values (CR::Model spec)" do
263
302
  before(:all) do
@@ -15,8 +15,8 @@ class Cat < CouchRest::ExtendedDocument
15
15
  use_database DB
16
16
 
17
17
  property :name, :accessible => true
18
- property :toys, :cast_as => [CatToy], :default => [], :accessible => true
19
- property :favorite_toy, :cast_as => CatToy, :accessible => true
18
+ property :toys, [CatToy], :default => [], :accessible => true
19
+ property :favorite_toy, CatToy, :accessible => true
20
20
  property :number
21
21
  end
22
22
 
data/spec/spec_helper.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  require "rubygems"
2
2
  require "spec" # Satisfies Autotest and anyone else not using the Rake tasks
3
3
 
4
- require File.join(File.dirname(__FILE__), '..','lib','couchrest','extended_document')
4
+ require File.join(File.dirname(__FILE__), '..','lib','couchrest_extended_document')
5
5
  # check the following file to see how to use the spec'd features.
6
6
 
7
7
  unless defined?(FIXTURE_PATH)
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 1
7
7
  - 0
8
- - 1
9
- version: 1.0.1
8
+ - 3
9
+ version: 1.0.3
10
10
  platform: ruby
11
11
  authors:
12
12
  - J. Chris Anderson
@@ -17,7 +17,7 @@ autorequire:
17
17
  bindir: bin
18
18
  cert_chain: []
19
19
 
20
- date: 2010-05-10 00:00:00 +02:00
20
+ date: 2010-05-13 00:00:00 +02:00
21
21
  default_executable:
22
22
  dependencies:
23
23
  - !ruby/object:Gem::Dependency
@@ -96,6 +96,7 @@ files:
96
96
  - lib/couchrest/support/couchrest.rb
97
97
  - lib/couchrest/support/rails.rb
98
98
  - lib/couchrest/typecast.rb
99
+ - lib/couchrest/validation.rb
99
100
  - lib/couchrest/validation/auto_validate.rb
100
101
  - lib/couchrest/validation/contextual_validators.rb
101
102
  - lib/couchrest/validation/validation_errors.rb
@@ -109,6 +110,7 @@ files:
109
110
  - lib/couchrest/validation/validators/method_validator.rb
110
111
  - lib/couchrest/validation/validators/numeric_validator.rb
111
112
  - lib/couchrest/validation/validators/required_field_validator.rb
113
+ - lib/couchrest_extended_document.rb
112
114
  - spec/couchrest/attribute_protection_spec.rb
113
115
  - spec/couchrest/casted_extended_doc_spec.rb
114
116
  - spec/couchrest/casted_model_spec.rb