couchrest 0.38 → 1.0.0.beta

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. data/README.md +8 -8
  2. data/Rakefile +3 -4
  3. data/couchrest.gemspec +25 -105
  4. data/history.txt +5 -4
  5. data/lib/couchrest.rb +31 -52
  6. data/lib/couchrest/{core/database.rb → database.rb} +6 -11
  7. data/lib/couchrest/{core/design.rb → design.rb} +2 -2
  8. data/lib/couchrest/{core/document.rb → document.rb} +1 -1
  9. data/lib/couchrest/helper/attachments.rb +29 -0
  10. data/lib/couchrest/middlewares/logger.rb +3 -3
  11. data/lib/couchrest/monkeypatches.rb +1 -71
  12. data/lib/couchrest/{core/response.rb → response.rb} +0 -0
  13. data/lib/couchrest/{core/rest_api.rb → rest_api.rb} +8 -12
  14. data/lib/couchrest/{core/server.rb → server.rb} +0 -2
  15. data/spec/couchrest/{core/couchrest_spec.rb → couchrest_spec.rb} +15 -9
  16. data/spec/couchrest/{core/database_spec.rb → database_spec.rb} +4 -4
  17. data/spec/couchrest/{core/design_spec.rb → design_spec.rb} +2 -2
  18. data/spec/couchrest/{core/document_spec.rb → document_spec.rb} +1 -1
  19. data/spec/couchrest/{core/server_spec.rb → server_spec.rb} +2 -2
  20. data/spec/spec.opts +0 -1
  21. data/spec/spec_helper.rb +0 -4
  22. metadata +32 -133
  23. data/examples/model/example.rb +0 -144
  24. data/lib/couchrest/core/adapters/restclient.rb +0 -35
  25. data/lib/couchrest/core/http_abstraction.rb +0 -48
  26. data/lib/couchrest/core/view.rb +0 -4
  27. data/lib/couchrest/mixins.rb +0 -4
  28. data/lib/couchrest/mixins/attachments.rb +0 -31
  29. data/lib/couchrest/mixins/attribute_protection.rb +0 -74
  30. data/lib/couchrest/mixins/callbacks.rb +0 -532
  31. data/lib/couchrest/mixins/class_proxy.rb +0 -124
  32. data/lib/couchrest/mixins/collection.rb +0 -260
  33. data/lib/couchrest/mixins/design_doc.rb +0 -103
  34. data/lib/couchrest/mixins/document_queries.rb +0 -80
  35. data/lib/couchrest/mixins/extended_attachments.rb +0 -70
  36. data/lib/couchrest/mixins/extended_document_mixins.rb +0 -9
  37. data/lib/couchrest/mixins/properties.rb +0 -158
  38. data/lib/couchrest/mixins/validation.rb +0 -246
  39. data/lib/couchrest/mixins/views.rb +0 -173
  40. data/lib/couchrest/more/casted_model.rb +0 -58
  41. data/lib/couchrest/more/extended_document.rb +0 -310
  42. data/lib/couchrest/more/property.rb +0 -58
  43. data/lib/couchrest/more/typecast.rb +0 -180
  44. data/lib/couchrest/support/blank.rb +0 -42
  45. data/lib/couchrest/support/rails.rb +0 -42
  46. data/lib/couchrest/validation/auto_validate.rb +0 -157
  47. data/lib/couchrest/validation/contextual_validators.rb +0 -78
  48. data/lib/couchrest/validation/validation_errors.rb +0 -125
  49. data/lib/couchrest/validation/validators/absent_field_validator.rb +0 -74
  50. data/lib/couchrest/validation/validators/confirmation_validator.rb +0 -107
  51. data/lib/couchrest/validation/validators/format_validator.rb +0 -122
  52. data/lib/couchrest/validation/validators/formats/email.rb +0 -66
  53. data/lib/couchrest/validation/validators/formats/url.rb +0 -43
  54. data/lib/couchrest/validation/validators/generic_validator.rb +0 -120
  55. data/lib/couchrest/validation/validators/length_validator.rb +0 -139
  56. data/lib/couchrest/validation/validators/method_validator.rb +0 -89
  57. data/lib/couchrest/validation/validators/numeric_validator.rb +0 -109
  58. data/lib/couchrest/validation/validators/required_field_validator.rb +0 -114
  59. data/spec/couchrest/more/attribute_protection_spec.rb +0 -150
  60. data/spec/couchrest/more/casted_extended_doc_spec.rb +0 -73
  61. data/spec/couchrest/more/casted_model_spec.rb +0 -406
  62. data/spec/couchrest/more/extended_doc_attachment_spec.rb +0 -135
  63. data/spec/couchrest/more/extended_doc_inherited_spec.rb +0 -40
  64. data/spec/couchrest/more/extended_doc_spec.rb +0 -807
  65. data/spec/couchrest/more/extended_doc_subclass_spec.rb +0 -98
  66. data/spec/couchrest/more/extended_doc_view_spec.rb +0 -456
  67. data/spec/couchrest/more/property_spec.rb +0 -628
  68. data/spec/fixtures/more/article.rb +0 -35
  69. data/spec/fixtures/more/card.rb +0 -22
  70. data/spec/fixtures/more/cat.rb +0 -20
  71. data/spec/fixtures/more/course.rb +0 -22
  72. data/spec/fixtures/more/event.rb +0 -8
  73. data/spec/fixtures/more/invoice.rb +0 -17
  74. data/spec/fixtures/more/person.rb +0 -9
  75. data/spec/fixtures/more/question.rb +0 -6
  76. data/spec/fixtures/more/service.rb +0 -12
  77. data/spec/fixtures/more/user.rb +0 -22
@@ -1,58 +0,0 @@
1
- module CouchRest
2
-
3
- # Basic attribute support for adding getter/setter + validation
4
- class Property
5
- attr_reader :name, :type, :read_only, :alias, :default, :casted, :init_method, :options
6
-
7
- # attribute to define
8
- def initialize(name, type = nil, options = {})
9
- @name = name.to_s
10
- parse_type(type)
11
- parse_options(options)
12
- self
13
- end
14
-
15
- private
16
-
17
- def parse_type(type)
18
- if type.nil?
19
- @type = 'String'
20
- elsif type.is_a?(Array) && type.empty?
21
- @type = ['Object']
22
- else
23
- @type = type.is_a?(Array) ? [type.first.to_s] : type.to_s
24
- end
25
- end
26
-
27
- def parse_options(options)
28
- return if options.empty?
29
- @validation_format = options.delete(:format) if options[:format]
30
- @read_only = options.delete(:read_only) if options[:read_only]
31
- @alias = options.delete(:alias) if options[:alias]
32
- @default = options.delete(:default) unless options[:default].nil?
33
- @casted = options[:casted] ? true : false
34
- @init_method = options[:init_method] ? options.delete(:init_method) : 'new'
35
- @options = options
36
- end
37
-
38
- end
39
- end
40
-
41
- class CastedArray < Array
42
- attr_accessor :casted_by
43
-
44
- def << obj
45
- obj.casted_by = self.casted_by if obj.respond_to?(:casted_by)
46
- super(obj)
47
- end
48
-
49
- def push(obj)
50
- obj.casted_by = self.casted_by if obj.respond_to?(:casted_by)
51
- super(obj)
52
- end
53
-
54
- def []= index, obj
55
- obj.casted_by = self.casted_by if obj.respond_to?(:casted_by)
56
- super(index, obj)
57
- end
58
- end
@@ -1,180 +0,0 @@
1
- require 'time'
2
- require 'bigdecimal'
3
- require 'bigdecimal/util'
4
- require File.join(File.dirname(__FILE__), '..', 'more', 'property')
5
-
6
- class Time
7
- # returns a local time value much faster than Time.parse
8
- def self.mktime_with_offset(string)
9
- string =~ /(\d{4})[\-|\/](\d{2})[\-|\/](\d{2})[T|\s](\d{2}):(\d{2}):(\d{2})([\+|\s|\-])*(\d{2}):?(\d{2})/
10
- # $1 = year
11
- # $2 = month
12
- # $3 = day
13
- # $4 = hours
14
- # $5 = minutes
15
- # $6 = seconds
16
- # $7 = time zone direction
17
- # $8 = tz difference
18
- # utc time with wrong TZ info:
19
- time = mktime($1, RFC2822_MONTH_NAME[$2.to_i - 1], $3, $4, $5, $6, $7)
20
- tz_difference = ("#{$7 == '-' ? '+' : '-'}#{$8}".to_i * 3600)
21
- time + tz_difference + zone_offset(time.zone)
22
- end
23
- end
24
-
25
- module CouchRest
26
- module More
27
- module Typecast
28
-
29
- def typecast_value(value, klass, init_method)
30
- return nil if value.nil?
31
-
32
- if value.instance_of?(klass) || klass.to_s == 'Object'
33
- value
34
- elsif ['String', 'TrueClass', 'Integer', 'Float', 'BigDecimal', 'DateTime', 'Time', 'Date', 'Class'].include?(klass.to_s)
35
- send('typecast_to_'+klass.to_s.downcase, value)
36
- else
37
- # Allow the init_method to be defined as a Proc for advanced conversion
38
- init_method.is_a?(Proc) ? init_method.call(value) : klass.send(init_method, value)
39
- end
40
- end
41
-
42
- protected
43
-
44
- # Typecast a value to an Integer
45
- def typecast_to_integer(value)
46
- value.kind_of?(Integer) ? value : typecast_to_numeric(value, :to_i)
47
- end
48
-
49
- # Typecast a value to a String
50
- def typecast_to_string(value)
51
- value.to_s
52
- end
53
-
54
- # Typecast a value to a true or false
55
- def typecast_to_trueclass(value)
56
- if value.kind_of?(Integer)
57
- return true if value == 1
58
- return false if value == 0
59
- elsif value.respond_to?(:to_s)
60
- return true if %w[ true 1 t ].include?(value.to_s.downcase)
61
- return false if %w[ false 0 f ].include?(value.to_s.downcase)
62
- end
63
- value
64
- end
65
-
66
- # Typecast a value to a BigDecimal
67
- def typecast_to_bigdecimal(value)
68
- return value if value.kind_of?(BigDecimal)
69
-
70
- if value.kind_of?(Integer)
71
- value.to_s.to_d
72
- else
73
- typecast_to_numeric(value, :to_d)
74
- end
75
- end
76
-
77
- # Typecast a value to a Float
78
- def typecast_to_float(value)
79
- return value if value.kind_of?(Float)
80
- typecast_to_numeric(value, :to_f)
81
- end
82
-
83
- # Match numeric string
84
- def typecast_to_numeric(value, method)
85
- if value.respond_to?(:to_str)
86
- if value.to_str =~ /\A(-?(?:0|[1-9]\d*)(?:\.\d+)?|(?:\.\d+))\z/
87
- $1.send(method)
88
- else
89
- value
90
- end
91
- elsif value.respond_to?(method)
92
- value.send(method)
93
- else
94
- value
95
- end
96
- end
97
-
98
- # Typecasts an arbitrary value to a DateTime.
99
- # Handles both Hashes and DateTime instances.
100
- def typecast_to_datetime(value)
101
- return value if value.kind_of?(DateTime)
102
-
103
- if value.is_a?(Hash)
104
- typecast_hash_to_datetime(value)
105
- else
106
- DateTime.parse(value.to_s)
107
- end
108
- rescue ArgumentError
109
- value
110
- end
111
-
112
- # Typecasts an arbitrary value to a Date
113
- # Handles both Hashes and Date instances.
114
- def typecast_to_date(value)
115
- return value if value.kind_of?(Date)
116
-
117
- if value.is_a?(Hash)
118
- typecast_hash_to_date(value)
119
- else
120
- Date.parse(value.to_s)
121
- end
122
- rescue ArgumentError
123
- value
124
- end
125
-
126
- # Typecasts an arbitrary value to a Time
127
- # Handles both Hashes and Time instances.
128
- def typecast_to_time(value)
129
- return value if value.kind_of?(Time)
130
-
131
- if value.is_a?(Hash)
132
- typecast_hash_to_time(value)
133
- else
134
- Time.mktime_with_offset(value.to_s)
135
- end
136
- rescue ArgumentError
137
- value
138
- rescue TypeError
139
- value
140
- end
141
-
142
- # Creates a DateTime instance from a Hash with keys :year, :month, :day,
143
- # :hour, :min, :sec
144
- def typecast_hash_to_datetime(value)
145
- DateTime.new(*extract_time(value))
146
- end
147
-
148
- # Creates a Date instance from a Hash with keys :year, :month, :day
149
- def typecast_hash_to_date(value)
150
- Date.new(*extract_time(value)[0, 3])
151
- end
152
-
153
- # Creates a Time instance from a Hash with keys :year, :month, :day,
154
- # :hour, :min, :sec
155
- def typecast_hash_to_time(value)
156
- Time.local(*extract_time(value))
157
- end
158
-
159
- # Extracts the given args from the hash. If a value does not exist, it
160
- # uses the value of Time.now.
161
- def extract_time(value)
162
- now = Time.now
163
-
164
- [:year, :month, :day, :hour, :min, :sec].map do |segment|
165
- typecast_to_numeric(value.fetch(segment, now.send(segment)), :to_i)
166
- end
167
- end
168
-
169
- # Typecast a value to a Class
170
- def typecast_to_class(value)
171
- return value if value.kind_of?(Class)
172
- ::CouchRest.constantize(value.to_s)
173
- rescue NameError
174
- value
175
- end
176
-
177
- end
178
- end
179
- end
180
-
@@ -1,42 +0,0 @@
1
- # blank? methods for several different class types
2
- class Object
3
- # Returns true if the object is nil or empty (if applicable)
4
- def blank?
5
- nil? || (respond_to?(:empty?) && empty?)
6
- end
7
- end # class Object
8
-
9
- class Numeric
10
- # Numerics can't be blank
11
- def blank?
12
- false
13
- end
14
- end # class Numeric
15
-
16
- class NilClass
17
- # Nils are always blank
18
- def blank?
19
- true
20
- end
21
- end # class NilClass
22
-
23
- class TrueClass
24
- # True is not blank.
25
- def blank?
26
- false
27
- end
28
- end # class TrueClass
29
-
30
- class FalseClass
31
- # False is always blank.
32
- def blank?
33
- true
34
- end
35
- end # class FalseClass
36
-
37
- class String
38
- # Strips out whitespace then tests if the string is empty.
39
- def blank?
40
- strip.empty?
41
- end
42
- end # class String
@@ -1,42 +0,0 @@
1
- # This file contains various hacks for Rails compatibility.
2
- class Hash
3
- # Hack so that CouchRest::Document, which descends from Hash,
4
- # doesn't appear to Rails routing as a Hash of options
5
- def self.===(other)
6
- return false if self == Hash && other.is_a?(CouchRest::Document)
7
- super
8
- end
9
- end
10
-
11
- CouchRest::Document.class_eval do
12
- # Need this when passing doc to a resourceful route
13
- alias_method :to_param, :id
14
-
15
- # Hack so that CouchRest::Document, which descends from Hash,
16
- # doesn't appear to Rails routing as a Hash of options
17
- def is_a?(o)
18
- return false if o == Hash
19
- super
20
- end
21
- alias_method :kind_of?, :is_a?
22
- end
23
-
24
- CouchRest::CastedModel.class_eval do
25
- # The to_param method is needed for rails to generate resourceful routes.
26
- # In your controller, remember that it's actually the id of the document.
27
- def id
28
- return nil if base_doc.nil?
29
- base_doc.id
30
- end
31
- alias_method :to_param, :id
32
- end
33
-
34
- require Pathname.new(File.dirname(__FILE__)).join('..', 'validation', 'validation_errors')
35
-
36
- CouchRest::Validation::ValidationErrors.class_eval do
37
- # Returns the total number of errors added. Two errors added to the same attribute will be counted as such.
38
- # This method is called by error_messages_for
39
- def count
40
- errors.values.inject(0) { |error_count, errors_for_attribute| error_count + errors_for_attribute.size }
41
- end
42
- end
@@ -1,157 +0,0 @@
1
- # Ported from dm-migrations
2
- require File.join(File.dirname(__FILE__), '..', 'support', 'class')
3
-
4
- module CouchRest
5
-
6
- class Property
7
- # flag letting us know if we already checked the autovalidation settings
8
- attr_accessor :autovalidation_check
9
- @autovalidation_check = false
10
- end
11
-
12
- module Validation
13
- module AutoValidate
14
-
15
- # # Force the auto validation for the class properties
16
- # # This feature is still not fully ported over,
17
- # # test are lacking, so please use with caution
18
- # def auto_validate!
19
- # auto_validation = true
20
- # end
21
-
22
- # adds message for validator
23
- def options_with_message(base_options, property, validator_name)
24
- options = base_options.clone
25
- opts = property.options
26
- options[:message] = if opts[:messages]
27
- if opts[:messages].is_a?(Hash) and msg = opts[:messages][validator_name]
28
- msg
29
- else
30
- nil
31
- end
32
- elsif opts[:message]
33
- opts[:message]
34
- else
35
- nil
36
- end
37
- options
38
- end
39
-
40
-
41
- ##
42
- # Auto-generate validations for a given property. This will only occur
43
- # if the option :auto_validation is either true or left undefined.
44
- #
45
- # @details [Triggers]
46
- # Triggers that generate validator creation
47
- #
48
- # :nullable => false
49
- # Setting the option :nullable to false causes a
50
- # validates_presence_of validator to be automatically created on
51
- # the property
52
- #
53
- # :size => 20 or :length => 20
54
- # Setting the option :size or :length causes a validates_length_of
55
- # validator to be automatically created on the property. If the
56
- # value is a Integer the validation will set :maximum => value if
57
- # the value is a Range the validation will set :within => value
58
- #
59
- # :format => :predefined / lambda / Proc
60
- # Setting the :format option causes a validates_format_of
61
- # validator to be automatically created on the property
62
- #
63
- # :set => ["foo", "bar", "baz"]
64
- # Setting the :set option causes a validates_within
65
- # validator to be automatically created on the property
66
- #
67
- # Integer type
68
- # Using a Integer type causes a validates_numericality_of
69
- # validator to be created for the property. integer_only
70
- # is set to true
71
- #
72
- # Float type
73
- # Using a Integer type causes a validates_is_number
74
- # validator to be created for the property. integer_only
75
- # is set to false, and precision/scale match the property
76
- #
77
- #
78
- # Messages
79
- #
80
- # :messages => {..}
81
- # Setting :messages hash replaces standard error messages
82
- # with custom ones. For instance:
83
- # :messages => {:presence => "Field is required",
84
- # :format => "Field has invalid format"}
85
- # Hash keys are: :presence, :format, :length, :is_unique,
86
- # :is_number, :is_primitive
87
- #
88
- # :message => "Some message"
89
- # It is just shortcut if only one validation option is set
90
- #
91
- def auto_generate_validations(property)
92
- return unless ((property.autovalidation_check != true) && self.auto_validation)
93
- return if (property.options && (property.options.has_key?(:auto_validation) && !property.options[:auto_validation]) || property.read_only)
94
- # value is set by the storage system
95
- opts = {}
96
- opts[:context] = property.options[:validates] if property.options.has_key?(:validates)
97
-
98
- # presence
99
- if opts[:allow_nil] == false
100
- validates_presence_of property.name, options_with_message(opts, property, :presence)
101
- end
102
-
103
- # length
104
- if property.type == "String"
105
- # XXX: maybe length should always return a Range, with the min defaulting to 1
106
- # 52 being the max set
107
- len = property.options.fetch(:length, property.options.fetch(:size, 52))
108
- if len.is_a?(Range)
109
- opts[:within] = len
110
- else
111
- opts[:maximum] = len
112
- end
113
- validates_length_of property.name, options_with_message(opts, property, :length)
114
- end
115
-
116
- # format
117
- if property.options.has_key?(:format)
118
- opts[:with] = property.options[:format]
119
- # validates_format property.name, opts
120
- validates_format property.name, options_with_message(opts, property, :format)
121
- end
122
-
123
- # uniqueness validator
124
- if property.options.has_key?(:unique)
125
- value = property.options[:unique]
126
- if value.is_a?(Array) || value.is_a?(Symbol)
127
- # validates_is_unique property.name, :scope => Array(value)
128
- validates_is_unique property.name, options_with_message({:scope => Array(value)}, property, :is_unique)
129
- elsif value.is_a?(TrueClass)
130
- # validates_is_unique property.name
131
- validates_is_unique property.name, options_with_message({}, property, :is_unique)
132
- end
133
- end
134
-
135
- # within validator
136
- if property.options.has_key?(:set)
137
- validates_within property.name, options_with_message({:set => property.options[:set]}, property, :within)
138
- end
139
-
140
- # numeric validator
141
- if "Integer" == property.type
142
- opts[:integer_only] = true
143
- validates_numericality_of property.name, options_with_message(opts, property, :is_number)
144
- elsif Float == property.type
145
- opts[:precision] = property.precision
146
- opts[:scale] = property.scale
147
- validates_numericality_of property.name, options_with_message(opts, property, :is_number)
148
- end
149
-
150
- # marked the property has checked
151
- property.autovalidation_check = true
152
-
153
- end
154
-
155
- end # module AutoValidate
156
- end # module Validation
157
- end # module CouchRest