couchrest_model 2.0.0.beta2 → 2.0.0

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.
Files changed (41) hide show
  1. data/.travis.yml +8 -0
  2. data/Gemfile +1 -1
  3. data/README.md +1 -1
  4. data/Rakefile +9 -24
  5. data/VERSION +1 -1
  6. data/couchrest_model.gemspec +7 -5
  7. data/history.md +17 -1
  8. data/lib/couchrest/model/associations.rb +16 -11
  9. data/lib/couchrest/model/base.rb +17 -15
  10. data/lib/couchrest/model/casted_array.rb +7 -1
  11. data/lib/couchrest/model/core_extensions/time_parsing.rb +0 -23
  12. data/lib/couchrest/model/design.rb +282 -0
  13. data/lib/couchrest/model/designs/design_mapper.rb +79 -0
  14. data/lib/couchrest/model/designs/view.rb +9 -6
  15. data/lib/couchrest/model/designs.rb +37 -70
  16. data/lib/couchrest/model/persistence.rb +5 -5
  17. data/lib/couchrest/model/properties.rb +5 -16
  18. data/lib/couchrest/model/property.rb +34 -16
  19. data/lib/couchrest/model/translation.rb +22 -0
  20. data/lib/couchrest/model/typecast.rb +54 -43
  21. data/lib/couchrest/model/utils/migrate.rb +106 -0
  22. data/lib/couchrest_model.rb +4 -2
  23. data/lib/tasks/migrations.rake +5 -5
  24. data/spec/fixtures/models/course.rb +1 -0
  25. data/spec/fixtures/models/designs.rb +22 -0
  26. data/spec/spec_helper.rb +1 -0
  27. data/spec/unit/assocations_spec.rb +7 -0
  28. data/spec/unit/base_spec.rb +3 -1
  29. data/spec/unit/{designs/design_spec.rb → design_spec.rb} +6 -6
  30. data/spec/unit/designs/design_mapper_spec.rb +124 -0
  31. data/spec/unit/designs/view_spec.rb +30 -4
  32. data/spec/unit/designs_spec.rb +5 -140
  33. data/spec/unit/dirty_spec.rb +15 -1
  34. data/spec/unit/embeddable_spec.rb +2 -2
  35. data/spec/unit/property_spec.rb +70 -28
  36. data/spec/unit/translations_spec.rb +31 -0
  37. data/spec/unit/typecast_spec.rb +99 -19
  38. data/spec/unit/utils/migrate_spec.rb +25 -0
  39. metadata +43 -19
  40. data/lib/couchrest/model/designs/design.rb +0 -284
  41. data/lib/couchrest/model/migrate.rb +0 -92
@@ -22,18 +22,37 @@ module CouchRest
22
22
 
23
23
  module ClassMethods
24
24
 
25
- # Add views and other design document features
26
- # to the current model.
27
- def design(prefix = nil, &block)
25
+ # Define a Design Document associated with the current model.
26
+ #
27
+ # This class method supports several cool features that make it much
28
+ # easier to define design documents.
29
+ #
30
+ # Adding a prefix allows you to associate multiple design documents with the same
31
+ # model. This is useful if you'd like to split your designs into seperate
32
+ # use cases; one for regular search functions and a second for stats for example.
33
+ #
34
+ # # Create a design doc with id _design/Cats
35
+ # design do
36
+ # view :by_name
37
+ # end
38
+ #
39
+ # # Create a design doc with id _design/Cats_stats
40
+ # design :stats do
41
+ # view :by_age, :reduce => :stats
42
+ # end
43
+ #
44
+ #
45
+ def design(*args, &block)
46
+ opts = prepare_design_options(*args)
28
47
 
29
48
  # Store ourselves a copy of this design spec incase any other model inherits.
30
- (@_design_blocks ||= [ ]) << {:args => [prefix], :block => block}
49
+ (@_design_blocks ||= [ ]) << {:args => args, :block => block}
31
50
 
32
- mapper = DesignMapper.new(self, prefix)
51
+ mapper = DesignMapper.new(self, opts[:prefix])
33
52
  mapper.instance_eval(&block) if block_given?
34
53
 
35
54
  # Create an 'all' view if no prefix and one has not been defined already
36
- mapper.view(:all) if prefix.nil? and !mapper.design_doc.has_view?(:all)
55
+ mapper.view(:all) if opts[:prefix].nil? and !mapper.design_doc.has_view?(:all)
37
56
  end
38
57
 
39
58
  def inherited(model)
@@ -68,76 +87,24 @@ module CouchRest
68
87
  @_design_docs ||= []
69
88
  end
70
89
 
71
- end
72
-
73
- # Map method calls defined in a design block to actions
74
- # in the Design Document.
75
- class DesignMapper
76
-
77
- # Basic mapper attributes
78
- attr_accessor :model, :method, :prefix
79
-
80
- # Temporary variable storing the design doc
81
- attr_accessor :design_doc
82
-
83
- def initialize(model, prefix = nil)
84
- self.model = model
85
- self.prefix = prefix
86
- self.method = Design.method_name(prefix)
87
-
88
- create_model_design_doc_reader
89
- self.design_doc = model.send(method) || assign_model_design_doc
90
- end
91
-
92
- def disable_auto_update
93
- design_doc.auto_update = false
94
- end
95
-
96
- def enable_auto_update
97
- design_doc.auto_update = true
98
- end
99
-
100
- # Add the specified view to the design doc the definition was made in
101
- # and create quick access methods in the model.
102
- def view(name, opts = {})
103
- design_doc.create_view(name, opts)
104
- end
105
-
106
- # Really simple design function that allows a filter
107
- # to be added. Filters are simple functions used when listening
108
- # to the _changes feed.
109
- #
110
- # No methods are created here, the design is simply updated.
111
- # See the CouchDB API for more information on how to use this.
112
- def filter(name, function)
113
- design_doc.create_filter(name, function)
114
- end
115
-
116
- # Convenience wrapper to access model's type key option.
117
- def model_type_key
118
- model.model_type_key
119
- end
120
-
121
- protected
90
+ private
122
91
 
123
- # Create accessor in model and assign a new design doc.
124
- # New design doc is returned ready to use.
125
- def create_model_design_doc_reader
126
- model.instance_eval "def #{method}; @#{method}; end"
92
+ def prepare_design_options(*args)
93
+ options = {}
94
+ if !args.first.is_a?(Hash)
95
+ options[:prefix] = args.shift
96
+ end
97
+ options.merge(args.last) unless args.empty?
98
+ prepare_source_paths(options)
99
+ options
127
100
  end
128
101
 
129
- def assign_model_design_doc
130
- doc = Design.new(model, prefix)
131
- model.instance_variable_set("@#{method}", doc)
132
- model.design_docs << doc
133
-
134
- # Set defaults
135
- doc.auto_update = model.auto_update_design_doc
136
-
137
- doc
102
+ def prepare_source_paths(options)
103
+
138
104
  end
139
105
 
140
106
  end
107
+
141
108
  end
142
109
  end
143
110
  end
@@ -8,8 +8,8 @@ module CouchRest
8
8
  # be returned.
9
9
  def create(options = {})
10
10
  return false unless perform_validations(options)
11
- _run_create_callbacks do
12
- _run_save_callbacks do
11
+ run_callbacks :create do
12
+ run_callbacks :save do
13
13
  set_unique_id if new? && self.respond_to?(:set_unique_id)
14
14
  result = database.save_doc(self)
15
15
  ret = (result["ok"] == true) ? self : false
@@ -32,8 +32,8 @@ module CouchRest
32
32
  raise "Calling #{self.class.name}#update on document that has not been created!" if new?
33
33
  return false unless perform_validations(options)
34
34
  return true if !self.disable_dirty && !self.changed?
35
- _run_update_callbacks do
36
- _run_save_callbacks do
35
+ run_callbacks :update do
36
+ run_callbacks :save do
37
37
  result = database.save_doc(self)
38
38
  ret = result["ok"] == true
39
39
  @changed_attributes.clear if ret && @changed_attributes
@@ -56,7 +56,7 @@ module CouchRest
56
56
 
57
57
  # Deletes the document from the database. Runs the :destroy callbacks.
58
58
  def destroy
59
- _run_destroy_callbacks do
59
+ run_callbacks :destroy do
60
60
  result = database.delete_doc(self)
61
61
  if result['ok']
62
62
  @_destroyed = true
@@ -205,26 +205,15 @@ module CouchRest
205
205
 
206
206
  # This is not a thread safe operation, if you have to set new properties at runtime
207
207
  # make sure a mutex is used.
208
- def define_property(name, options={}, &block)
209
- # check if this property is going to casted
210
- type = options.delete(:type) || options.delete(:cast_as)
211
- if block_given?
212
- type = Class.new do
213
- include Embeddable
214
- end
215
- if block.arity == 1 # Traditional, with options
216
- type.class_eval { yield type }
217
- else
218
- type.instance_exec(&block)
219
- end
220
- type = [type] # inject as an array
221
- end
222
- property = Property.new(name, type, options)
208
+ def define_property(name, options = {}, &block)
209
+ property = Property.new(name, options, &block)
223
210
  create_property_getter(property)
224
211
  create_property_setter(property) unless property.read_only == true
225
- if property.type_class.respond_to?(:validates_casted_model)
212
+
213
+ if property.type.respond_to?(:validates_casted_model)
226
214
  validates_casted_model property.name
227
215
  end
216
+
228
217
  properties << property
229
218
  properties_by_name[property.to_s] = property
230
219
  property
@@ -4,26 +4,29 @@ module CouchRest::Model
4
4
 
5
5
  include ::CouchRest::Model::Typecast
6
6
 
7
- attr_reader :name, :type, :type_class, :read_only, :alias, :default, :casted, :init_method, :options, :allow_blank
7
+ attr_reader :name, :type, :array, :read_only, :alias, :default, :casted, :init_method, :options, :allow_blank
8
8
 
9
9
  # Attribute to define.
10
10
  # All Properties are assumed casted unless the type is nil.
11
- def initialize(name, type = nil, options = {})
11
+ def initialize(name, options = {}, &block)
12
12
  @name = name.to_s
13
- @casted = true
14
- parse_type(type)
15
13
  parse_options(options)
14
+ parse_type(options, &block)
16
15
  self
17
16
  end
18
17
 
19
18
  def to_s
20
19
  name
21
20
  end
21
+
22
+ def to_sym
23
+ @_sym_name ||= name.to_sym
24
+ end
22
25
 
23
26
  # Cast the provided value using the properties details.
24
27
  def cast(parent, value)
25
28
  return value unless casted
26
- if type.is_a?(Array)
29
+ if array
27
30
  if value.nil?
28
31
  value = []
29
32
  elsif [Hash, HashWithIndifferentAccess].include?(value.class)
@@ -68,12 +71,12 @@ module CouchRest::Model
68
71
  # used. If a proc is defined for the init method, it will be used instead of
69
72
  # a normal call to the class.
70
73
  def build(*args)
71
- raise StandardError, "Cannot build property without a class" if @type_class.nil?
74
+ raise StandardError, "Cannot build property without a class" if @type.nil?
72
75
 
73
76
  if @init_method.is_a?(Proc)
74
77
  @init_method.call(*args)
75
78
  else
76
- @type_class.send(@init_method, *args)
79
+ @type.send(@init_method, *args)
77
80
  end
78
81
  end
79
82
 
@@ -93,21 +96,23 @@ module CouchRest::Model
93
96
  value
94
97
  end
95
98
 
96
- def parse_type(type)
97
- if type.nil?
99
+ def parse_type(options, &block)
100
+ set_type_from_block(&block) if block_given?
101
+ if @type.nil?
98
102
  @casted = false
99
- @type = nil
100
- @type_class = nil
101
103
  else
102
- base = type.is_a?(Array) ? type.first : type
103
- base = Object if base.nil?
104
- raise "Defining a property type as a #{type.class.name.humanize} is not supported in CouchRest Model!" if base.class != Class
105
- @type_class = base
106
- @type = type
104
+ @casted = true
105
+ if @type.is_a?(Array)
106
+ @type = @type.first || Object
107
+ @array = true
108
+ end
109
+ raise "Defining a property type as a #{@type.class.name.humanize} is not supported in CouchRest Model!" if @type.class != Class
107
110
  end
108
111
  end
109
112
 
110
113
  def parse_options(options)
114
+ @type = options.delete(:type) || options.delete(:cast_as)
115
+ @array = !!options.delete(:array)
111
116
  @validation_format = options.delete(:format) if options[:format]
112
117
  @read_only = options.delete(:read_only) if options[:read_only]
113
118
  @alias = options.delete(:alias) if options[:alias]
@@ -116,5 +121,18 @@ module CouchRest::Model
116
121
  @allow_blank = options[:allow_blank].nil? ? true : options.delete(:allow_blank)
117
122
  @options = options
118
123
  end
124
+
125
+
126
+ def set_type_from_block(&block)
127
+ @type = Class.new do
128
+ include Embeddable
129
+ end
130
+ if block.arity == 1 # Traditional, with options
131
+ @type.class_eval(&block)
132
+ else
133
+ @type.instance_eval(&block)
134
+ end
135
+ end
136
+
119
137
  end
120
138
  end
@@ -0,0 +1,22 @@
1
+ module CouchRest
2
+ module Model
3
+ module Translation
4
+ include ActiveModel::Translation
5
+
6
+ def lookup_ancestors #:nodoc:
7
+ klass = self
8
+ classes = [klass]
9
+ return classes if klass == CouchRest::Model::Base
10
+
11
+ while klass.superclass != CouchRest::Model::Base
12
+ classes << klass = klass.superclass
13
+ end
14
+ classes
15
+ end
16
+
17
+ def i18n_scope
18
+ :couchrest
19
+ end
20
+ end
21
+ end
22
+ end
@@ -4,17 +4,17 @@ module CouchRest
4
4
 
5
5
  def typecast_value(parent, property, value)
6
6
  return nil if value.nil?
7
- klass = property.type_class
8
- if value.instance_of?(klass) || klass == Object
9
- if klass == Time && !value.utc?
7
+ type = property.type
8
+ if value.instance_of?(type) || type == Object
9
+ if type == Time && !value.utc?
10
10
  value.utc # Ensure Time is always in UTC
11
11
  else
12
12
  value
13
13
  end
14
- elsif klass.respond_to?(:couchrest_typecast)
15
- klass.couchrest_typecast(parent, property, value)
16
- elsif [String, TrueClass, Integer, Float, BigDecimal, DateTime, Time, Date, Class].include?(klass)
17
- send('typecast_to_'+klass.to_s.downcase, value)
14
+ elsif type.respond_to?(:couchrest_typecast)
15
+ type.couchrest_typecast(parent, property, value)
16
+ elsif [String, Symbol, TrueClass, Integer, Float, BigDecimal, DateTime, Time, Date, Class].include?(type)
17
+ send('typecast_to_'+type.to_s.downcase, value)
18
18
  else
19
19
  property.build(value)
20
20
  end
@@ -27,30 +27,9 @@ module CouchRest
27
27
  typecast_to_numeric(value, :to_i)
28
28
  end
29
29
 
30
- # Typecast a value to a String
31
- def typecast_to_string(value)
32
- value.to_s
33
- end
34
-
35
- # Typecast a value to a true or false
36
- def typecast_to_trueclass(value)
37
- if value.kind_of?(Integer)
38
- return true if value == 1
39
- return false if value == 0
40
- elsif value.respond_to?(:to_s)
41
- return true if %w[ true 1 t ].include?(value.to_s.downcase)
42
- return false if %w[ false 0 f ].include?(value.to_s.downcase)
43
- end
44
- value
45
- end
46
-
47
30
  # Typecast a value to a BigDecimal
48
31
  def typecast_to_bigdecimal(value)
49
- if value.kind_of?(Integer)
50
- value.to_s.to_d
51
- else
52
- typecast_to_numeric(value, :to_d)
53
- end
32
+ typecast_to_numeric(value, :to_d)
54
33
  end
55
34
 
56
35
  # Typecast a value to a Float
@@ -58,21 +37,50 @@ module CouchRest
58
37
  typecast_to_numeric(value, :to_f)
59
38
  end
60
39
 
61
- # Match numeric string
40
+ # Convert some kind of object to a number that of the type
41
+ # provided.
42
+ #
43
+ # When a string is provided, It'll attempt to filter out
44
+ # region specific details such as commas instead of points
45
+ # for decimal places, text units, and anything else that is
46
+ # not a number and a human could make out.
47
+ #
48
+ # Esentially, the aim is to provide some kind of sanitary
49
+ # conversion from values in incoming http forms.
50
+ #
51
+ # If what we get makes no sense at all, nil it.
62
52
  def typecast_to_numeric(value, method)
63
- if value.respond_to?(:to_str)
64
- if value.strip.gsub(/,/, '.').gsub(/\.(?!\d*\Z)/, '').to_str =~ /\A(-?(?:0|[1-9]\d*)(?:\.\d+)?|(?:\.\d+))\z/
65
- $1.send(method)
66
- else
67
- value
68
- end
53
+ if value.is_a?(String)
54
+ value = value.strip.gsub(/,/, '.').gsub(/[^\d\-\.]/, '').gsub(/\.(?!\d*\Z)/, '')
55
+ value.empty? ? nil : value.send(method)
69
56
  elsif value.respond_to?(method)
70
57
  value.send(method)
71
58
  else
72
- value
59
+ nil
73
60
  end
74
61
  end
75
62
 
63
+ # Typecast a value to a String
64
+ def typecast_to_string(value)
65
+ value.to_s
66
+ end
67
+
68
+ def typecast_to_symbol(value)
69
+ value.to_sym
70
+ end
71
+
72
+ # Typecast a value to a true or false
73
+ def typecast_to_trueclass(value)
74
+ if value.kind_of?(Integer)
75
+ return true if value == 1
76
+ return false if value == 0
77
+ elsif value.respond_to?(:to_s)
78
+ return true if %w[ true 1 t ].include?(value.to_s.downcase)
79
+ return false if %w[ false 0 f ].include?(value.to_s.downcase)
80
+ end
81
+ nil
82
+ end
83
+
76
84
  # Typecasts an arbitrary value to a DateTime.
77
85
  # Handles both Hashes and DateTime instances.
78
86
  # This is slow!! Use Time instead.
@@ -83,7 +91,7 @@ module CouchRest
83
91
  DateTime.parse(value.to_s)
84
92
  end
85
93
  rescue ArgumentError
86
- value
94
+ nil
87
95
  end
88
96
 
89
97
  # Typecasts an arbitrary value to a Date
@@ -100,21 +108,24 @@ module CouchRest
100
108
  Date.parse(value)
101
109
  end
102
110
  rescue ArgumentError
103
- value
111
+ nil
104
112
  end
105
113
 
106
114
  # Typecasts an arbitrary value to a Time
107
115
  # Handles both Hashes and Time instances.
108
116
  def typecast_to_time(value)
109
- if value.is_a?(Hash)
117
+ case value
118
+ when Float # JSON oj already parses Time, FTW.
119
+ Time.at(value).utc
120
+ when Hash
110
121
  typecast_hash_to_time(value)
111
122
  else
112
123
  Time.parse_iso8601(value.to_s)
113
124
  end
114
125
  rescue ArgumentError
115
- value
126
+ nil
116
127
  rescue TypeError
117
- value
128
+ nil
118
129
  end
119
130
 
120
131
  # Creates a DateTime instance from a Hash with keys :year, :month, :day,
@@ -147,7 +158,7 @@ module CouchRest
147
158
  def typecast_to_class(value)
148
159
  value.to_s.constantize
149
160
  rescue NameError
150
- value
161
+ nil
151
162
  end
152
163
 
153
164
  end
@@ -0,0 +1,106 @@
1
+ module CouchRest
2
+ module Model
3
+ module Utils
4
+
5
+ # Handle CouchDB Design Document migrations.
6
+ #
7
+ # Actual migrations are handled by the Design document, this serves as a utility
8
+ # to find all the CouchRest Model submodels and perform the migration on them.
9
+ #
10
+ # Also contains some more advanced support for handling proxied models.
11
+ #
12
+ # Examples of usage:
13
+ #
14
+ # # Ensure all models have been loaded (only Rails)
15
+ # CouchRest::Model::Utils::Migrate.load_all_models
16
+ #
17
+ # # Migrate all regular models (not proxied)
18
+ # CouchRest::Model::Utils::Migrate.all_models
19
+ #
20
+ # # Migrate all models and submodels of proxies
21
+ # CouchRest::Model::Utils::Migrate.all_models_and_proxies
22
+ #
23
+ # Typically however you'd want to run these methods from the rake tasks:
24
+ #
25
+ # $ rake couchrest:migrate_with_proxies
26
+ #
27
+ # NOTE: This is an experimental feature that is not yet properly tested.
28
+ #
29
+ module Migrate
30
+ extend self
31
+
32
+ # Make an attempt at loading all the files in this Rails application's
33
+ # models directory.
34
+ def load_all_models
35
+ # Make a reasonable effort to load all models
36
+ return unless defined?(Rails)
37
+ Dir[Rails.root + 'app/models/**/*.rb'].each do |path|
38
+ require path
39
+ end
40
+ end
41
+
42
+ # Go through each class that inherits from CouchRest::Model::Base and
43
+ # attempt to migrate the design documents.
44
+ def all_models
45
+ callbacks = migrate_each_model(find_models)
46
+ cleanup(callbacks)
47
+ end
48
+
49
+ def all_models_and_proxies
50
+ callbacks = migrate_each_model(find_models)
51
+ callbacks += migrate_each_proxying_model(find_proxying_models)
52
+ cleanup(callbacks)
53
+ end
54
+
55
+ protected
56
+
57
+ def find_models
58
+ CouchRest::Model::Base.subclasses.reject{|m| m.proxy_owner_method.present?}
59
+ end
60
+
61
+ def find_proxying_models
62
+ CouchRest::Model::Base.subclasses.reject{|m| m.proxy_database_method.blank?}
63
+ end
64
+
65
+ def migrate_each_model(models, db = nil)
66
+ callbacks = [ ]
67
+ models.each do |model|
68
+ model.design_docs.each do |design|
69
+ callbacks << migrate_design(model, design, db)
70
+ end
71
+ end
72
+ callbacks
73
+ end
74
+
75
+ def migrate_each_proxying_model(models)
76
+ callbacks = [ ]
77
+ models.each do |model|
78
+ submodels = model.proxied_model_names.map{|n| n.constantize}
79
+ model.all.each do |base|
80
+ puts "Finding proxied models for #{model}: \"#{base.send(model.proxy_database_method)}\""
81
+ callbacks += migrate_each_model(submodels, base.proxy_database)
82
+ end
83
+ end
84
+ callbacks
85
+ end
86
+
87
+ def migrate_design(model, design, db = nil)
88
+ print "Migrating #{model.to_s}##{design.method_name}... "
89
+ callback = design.migrate(db) do |result|
90
+ puts "#{result.to_s.gsub(/_/, ' ')}"
91
+ end
92
+ # Return the callback hash if there is one
93
+ callback ? {:design => design, :proc => callback, :db => db || model.database} : nil
94
+ end
95
+
96
+ def cleanup(methods)
97
+ methods.compact.each do |cb|
98
+ name = "/#{cb[:db].name}/#{cb[:design]['_id']}"
99
+ puts "Activating new design: #{name}"
100
+ cb[:proc].call
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end
@@ -24,6 +24,7 @@ require 'couchrest'
24
24
 
25
25
  require 'couchrest/model'
26
26
  require 'couchrest/model/errors'
27
+ require 'couchrest/model/translation'
27
28
  require "couchrest/model/persistence"
28
29
  require "couchrest/model/typecast"
29
30
  require "couchrest/model/casted_by"
@@ -41,8 +42,9 @@ require "couchrest/model/proxyable"
41
42
  require "couchrest/model/associations"
42
43
  require "couchrest/model/configuration"
43
44
  require "couchrest/model/connection"
45
+ require "couchrest/model/design"
44
46
  require "couchrest/model/designs"
45
- require "couchrest/model/designs/design"
47
+ require "couchrest/model/designs/design_mapper"
46
48
  require "couchrest/model/designs/view"
47
49
 
48
50
  # Monkey patches applied to couchrest
@@ -57,7 +59,7 @@ require "couchrest/model/embeddable"
57
59
  require "couchrest/model/base"
58
60
 
59
61
  # Design Migration support
60
- require "couchrest/model/migrate.rb"
62
+ require "couchrest/model/utils/migrate.rb"
61
63
 
62
64
  # Add rails support *after* everything has loaded
63
65
  if defined?(Rails)
@@ -1,20 +1,20 @@
1
1
  #
2
2
  # CouchRest Migration Rake Tasks
3
3
  #
4
- # Use at own risk! These are not tested yet!
4
+ # See the CouchRest::Model::Utils::Migrate class for more details.
5
5
  #
6
6
  namespace :couchrest do
7
7
 
8
8
  desc "Migrate all the design docs found in each model"
9
9
  task :migrate => :environment do
10
- CouchRest::Model::Migrate.load_all_models
11
- CouchRest::Model::Migrate.all_models
10
+ CouchRest::Model::Utils::Migrate.load_all_models
11
+ CouchRest::Model::Utils::Migrate.all_models
12
12
  end
13
13
 
14
14
  desc "Migrate all the design docs "
15
15
  task :migrate_with_proxies => :environment do
16
- CouchRest::Model::Migrate.load_all_models
17
- CouchRest::Model::Migrate.all_models_and_proxies
16
+ CouchRest::Model::Utils::Migrate.load_all_models
17
+ CouchRest::Model::Utils::Migrate.all_models_and_proxies
18
18
  end
19
19
 
20
20
 
@@ -21,6 +21,7 @@ class Course < CouchRest::Model::Base
21
21
  property :klass, :type => Class
22
22
  property :currency, String, :default => 'EUR'
23
23
  property :price, Money
24
+ property :symbol, Symbol
24
25
 
25
26
  design do
26
27
  view :by_title
@@ -0,0 +1,22 @@
1
+
2
+ class DesignModel < CouchRest::Model::Base
3
+ use_database DB
4
+ property :name
5
+ end
6
+
7
+ class DesignsModel < CouchRest::Model::Base
8
+ use_database DB
9
+ property :name
10
+ end
11
+
12
+
13
+ class DesignsNoAutoUpdate < CouchRest::Model::Base
14
+ use_database DB
15
+ property :title, String
16
+ design do
17
+ disable_auto_update
18
+ view :by_title_fail, :by => ['title']
19
+ view :by_title, :reduce => true
20
+ end
21
+ end
22
+
data/spec/spec_helper.rb CHANGED
@@ -5,6 +5,7 @@ require "bundler/setup"
5
5
  require "rubygems"
6
6
  require "rspec"
7
7
 
8
+ #require 'oj'
8
9
  require 'couchrest_model'
9
10
 
10
11
  unless defined?(FIXTURE_PATH)