samlown-couchrest 0.37.2 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. data/README.md +10 -4
  2. data/Rakefile +1 -1
  3. data/history.txt +8 -0
  4. data/lib/couchrest.rb +27 -49
  5. data/lib/couchrest/{core/database.rb → database.rb} +6 -11
  6. data/lib/couchrest/{core/design.rb → design.rb} +2 -2
  7. data/lib/couchrest/{core/document.rb → document.rb} +1 -1
  8. data/lib/couchrest/helper/attachments.rb +29 -0
  9. data/lib/couchrest/middlewares/logger.rb +3 -3
  10. data/lib/couchrest/monkeypatches.rb +1 -71
  11. data/lib/couchrest/{core/response.rb → response.rb} +0 -0
  12. data/lib/couchrest/{core/rest_api.rb → rest_api.rb} +9 -6
  13. data/lib/couchrest/{core/server.rb → server.rb} +0 -0
  14. data/spec/couchrest/{core/couchrest_spec.rb → couchrest_spec.rb} +16 -3
  15. data/spec/couchrest/{core/database_spec.rb → database_spec.rb} +2 -2
  16. data/spec/couchrest/{core/design_spec.rb → design_spec.rb} +2 -2
  17. data/spec/couchrest/{core/document_spec.rb → document_spec.rb} +1 -1
  18. data/spec/couchrest/{core/server_spec.rb → server_spec.rb} +2 -2
  19. data/spec/spec.opts +0 -1
  20. data/spec/spec_helper.rb +0 -4
  21. metadata +24 -113
  22. data/couchrest.gemspec +0 -183
  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 -154
  38. data/lib/couchrest/mixins/validation.rb +0 -246
  39. data/lib/couchrest/mixins/views.rb +0 -173
  40. data/lib/couchrest/more/casted_array.rb +0 -25
  41. data/lib/couchrest/more/casted_model.rb +0 -58
  42. data/lib/couchrest/more/extended_document.rb +0 -310
  43. data/lib/couchrest/more/property.rb +0 -50
  44. data/lib/couchrest/more/typecast.rb +0 -175
  45. data/lib/couchrest/support/blank.rb +0 -42
  46. data/lib/couchrest/support/rails.rb +0 -42
  47. data/lib/couchrest/validation/auto_validate.rb +0 -157
  48. data/lib/couchrest/validation/contextual_validators.rb +0 -78
  49. data/lib/couchrest/validation/validation_errors.rb +0 -125
  50. data/lib/couchrest/validation/validators/absent_field_validator.rb +0 -74
  51. data/lib/couchrest/validation/validators/confirmation_validator.rb +0 -107
  52. data/lib/couchrest/validation/validators/format_validator.rb +0 -122
  53. data/lib/couchrest/validation/validators/formats/email.rb +0 -66
  54. data/lib/couchrest/validation/validators/formats/url.rb +0 -43
  55. data/lib/couchrest/validation/validators/generic_validator.rb +0 -120
  56. data/lib/couchrest/validation/validators/length_validator.rb +0 -139
  57. data/lib/couchrest/validation/validators/method_validator.rb +0 -89
  58. data/lib/couchrest/validation/validators/numeric_validator.rb +0 -109
  59. data/lib/couchrest/validation/validators/required_field_validator.rb +0 -114
  60. data/spec/couchrest/more/attribute_protection_spec.rb +0 -150
  61. data/spec/couchrest/more/casted_extended_doc_spec.rb +0 -79
  62. data/spec/couchrest/more/casted_model_spec.rb +0 -406
  63. data/spec/couchrest/more/extended_doc_attachment_spec.rb +0 -135
  64. data/spec/couchrest/more/extended_doc_inherited_spec.rb +0 -40
  65. data/spec/couchrest/more/extended_doc_spec.rb +0 -808
  66. data/spec/couchrest/more/extended_doc_subclass_spec.rb +0 -98
  67. data/spec/couchrest/more/extended_doc_view_spec.rb +0 -462
  68. data/spec/couchrest/more/property_spec.rb +0 -628
  69. data/spec/fixtures/more/article.rb +0 -35
  70. data/spec/fixtures/more/card.rb +0 -22
  71. data/spec/fixtures/more/cat.rb +0 -20
  72. data/spec/fixtures/more/course.rb +0 -22
  73. data/spec/fixtures/more/event.rb +0 -8
  74. data/spec/fixtures/more/invoice.rb +0 -17
  75. data/spec/fixtures/more/person.rb +0 -9
  76. data/spec/fixtures/more/question.rb +0 -6
  77. data/spec/fixtures/more/service.rb +0 -12
  78. data/spec/fixtures/more/user.rb +0 -22
@@ -1,50 +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
- base_type = type.is_a?(Array) ? type.first : type
24
- if base_type.is_a?(String)
25
- if base_type.downcase == 'boolean'
26
- base_type = TrueClass
27
- else
28
- begin
29
- base_type = ::CouchRest.constantize(base_type)
30
- rescue # leave base type as a string and convert in more/typecast
31
- end
32
- end
33
- end
34
- @type = type.is_a?(Array) ? [base_type] : base_type
35
- end
36
- end
37
-
38
- def parse_options(options)
39
- return if options.empty?
40
- @validation_format = options.delete(:format) if options[:format]
41
- @read_only = options.delete(:read_only) if options[:read_only]
42
- @alias = options.delete(:alias) if options[:alias]
43
- @default = options.delete(:default) unless options[:default].nil?
44
- @casted = options[:casted] ? true : false
45
- @init_method = options[:init_method] ? options.delete(:init_method) : 'new'
46
- @options = options
47
- end
48
-
49
- end
50
- end
@@ -1,175 +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
- klass = ::CouchRest.constantize(klass) unless klass.is_a?(Class)
32
- if value.instance_of?(klass) || klass == Object
33
- value
34
- elsif [String, TrueClass, Integer, Float, BigDecimal, DateTime, Time, Date, Class].include?(klass)
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
- 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
- if value.kind_of?(Integer)
69
- value.to_s.to_d
70
- else
71
- typecast_to_numeric(value, :to_d)
72
- end
73
- end
74
-
75
- # Typecast a value to a Float
76
- def typecast_to_float(value)
77
- typecast_to_numeric(value, :to_f)
78
- end
79
-
80
- # Match numeric string
81
- def typecast_to_numeric(value, method)
82
- if value.respond_to?(:to_str)
83
- if value.to_str =~ /\A(-?(?:0|[1-9]\d*)(?:\.\d+)?|(?:\.\d+))\z/
84
- $1.send(method)
85
- else
86
- value
87
- end
88
- elsif value.respond_to?(method)
89
- value.send(method)
90
- else
91
- value
92
- end
93
- end
94
-
95
- # Typecasts an arbitrary value to a DateTime.
96
- # Handles both Hashes and DateTime instances.
97
- # This is slow!! Use Time instead.
98
- def typecast_to_datetime(value)
99
- if value.is_a?(Hash)
100
- typecast_hash_to_datetime(value)
101
- else
102
- DateTime.parse(value.to_s)
103
- end
104
- rescue ArgumentError
105
- value
106
- end
107
-
108
- # Typecasts an arbitrary value to a Date
109
- # Handles both Hashes and Date instances.
110
- def typecast_to_date(value)
111
- if value.is_a?(Hash)
112
- typecast_hash_to_date(value)
113
- elsif value.is_a?(Time) # sometimes people think date is time!
114
- value.to_date
115
- elsif value.to_s =~ /(\d{4})[\-|\/](\d{2})[\-|\/](\d{2})/
116
- # Faster than parsing the date
117
- Date.new($1.to_i, $2.to_i, $3.to_i)
118
- else
119
- Date.parse(value)
120
- end
121
- rescue ArgumentError
122
- value
123
- end
124
-
125
- # Typecasts an arbitrary value to a Time
126
- # Handles both Hashes and Time instances.
127
- def typecast_to_time(value)
128
- if value.is_a?(Hash)
129
- typecast_hash_to_time(value)
130
- else
131
- Time.mktime_with_offset(value.to_s)
132
- end
133
- rescue ArgumentError
134
- value
135
- rescue TypeError
136
- value
137
- end
138
-
139
- # Creates a DateTime instance from a Hash with keys :year, :month, :day,
140
- # :hour, :min, :sec
141
- def typecast_hash_to_datetime(value)
142
- DateTime.new(*extract_time(value))
143
- end
144
-
145
- # Creates a Date instance from a Hash with keys :year, :month, :day
146
- def typecast_hash_to_date(value)
147
- Date.new(*extract_time(value)[0, 3])
148
- end
149
-
150
- # Creates a Time instance from a Hash with keys :year, :month, :day,
151
- # :hour, :min, :sec
152
- def typecast_hash_to_time(value)
153
- Time.local(*extract_time(value))
154
- end
155
-
156
- # Extracts the given args from the hash. If a value does not exist, it
157
- # uses the value of Time.now.
158
- def extract_time(value)
159
- now = Time.now
160
- [:year, :month, :day, :hour, :min, :sec].map do |segment|
161
- typecast_to_numeric(value.fetch(segment, now.send(segment)), :to_i)
162
- end
163
- end
164
-
165
- # Typecast a value to a Class
166
- def typecast_to_class(value)
167
- ::CouchRest.constantize(value.to_s)
168
- rescue NameError
169
- value
170
- end
171
-
172
- end
173
- end
174
- end
175
-
@@ -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