couchrest_model 2.0.0.beta2 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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)