Merge remote branch 'refs/remotes/canonical/master' into design-mapper-more-auto-update-design-doc-aware
This commit is contained in:
commit
88bb413ec2
66 changed files with 866 additions and 423 deletions
|
@ -183,19 +183,19 @@ module CouchRest
|
|||
casted_by[casted_by_property.to_s] << obj.id
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def << obj
|
||||
check_obj(obj)
|
||||
casted_by[casted_by_property.to_s] << obj.id
|
||||
super(obj)
|
||||
end
|
||||
|
||||
|
||||
def push(obj)
|
||||
check_obj(obj)
|
||||
casted_by[casted_by_property.to_s].push obj.id
|
||||
super(obj)
|
||||
end
|
||||
|
||||
|
||||
def unshift(obj)
|
||||
check_obj(obj)
|
||||
casted_by[casted_by_property.to_s].unshift obj.id
|
||||
|
@ -212,7 +212,7 @@ module CouchRest
|
|||
casted_by[casted_by_property.to_s].pop
|
||||
super
|
||||
end
|
||||
|
||||
|
||||
def shift
|
||||
casted_by[casted_by_property.to_s].shift
|
||||
super
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
module CouchRest
|
||||
module Model
|
||||
class Base < Document
|
||||
class Base < CouchRest::Document
|
||||
|
||||
extend ActiveModel::Naming
|
||||
|
||||
include CouchRest::Model::Configuration
|
||||
include CouchRest::Model::Connection
|
||||
include CouchRest::Model::Persistence
|
||||
include CouchRest::Model::Callbacks
|
||||
include CouchRest::Model::DocumentQueries
|
||||
include CouchRest::Model::Views
|
||||
include CouchRest::Model::DesignDoc
|
||||
|
@ -18,9 +17,11 @@ module CouchRest
|
|||
include CouchRest::Model::PropertyProtection
|
||||
include CouchRest::Model::Associations
|
||||
include CouchRest::Model::Validations
|
||||
include CouchRest::Model::Callbacks
|
||||
include CouchRest::Model::Designs
|
||||
include CouchRest::Model::CastedBy
|
||||
include CouchRest::Model::Dirty
|
||||
include CouchRest::Model::Callbacks
|
||||
|
||||
def self.subclasses
|
||||
@subclasses ||= []
|
||||
|
@ -46,22 +47,24 @@ module CouchRest
|
|||
#
|
||||
# Options supported:
|
||||
#
|
||||
# * :directly_set_attributes: true when data comes directly from database
|
||||
# * :database: provide an alternative database
|
||||
# * :directly_set_attributes, true when data comes directly from database
|
||||
# * :database, provide an alternative database
|
||||
#
|
||||
# If a block is provided the new model will be passed into the
|
||||
# block so that it can be populated.
|
||||
def initialize(doc = {}, options = {})
|
||||
doc = prepare_all_attributes(doc, options)
|
||||
# set the instances database, if provided
|
||||
def initialize(attributes = {}, options = {})
|
||||
super()
|
||||
prepare_all_attributes(attributes, options)
|
||||
# set the instance's database, if provided
|
||||
self.database = options[:database] unless options[:database].nil?
|
||||
super(doc)
|
||||
unless self['_id'] && self['_rev']
|
||||
self[self.model_type_key] = self.class.to_s
|
||||
end
|
||||
|
||||
yield self if block_given?
|
||||
|
||||
after_initialize if respond_to?(:after_initialize)
|
||||
run_callbacks(:initialize) { self }
|
||||
end
|
||||
|
||||
|
||||
|
@ -79,18 +82,19 @@ module CouchRest
|
|||
super
|
||||
end
|
||||
|
||||
## Compatibility with ActiveSupport and older frameworks
|
||||
|
||||
# Hack so that CouchRest::Document, which descends from Hash,
|
||||
# doesn't appear to Rails routing as a Hash of options
|
||||
def is_a?(klass)
|
||||
return false if klass == Hash
|
||||
super
|
||||
# compatbility for 1.8, it does not use respond_to_missing?
|
||||
# thing is, when using it like this only, doing method(:find_by_view)
|
||||
# will throw an error
|
||||
def self.respond_to?(m, include_private = false)
|
||||
super || respond_to_missing?(m, include_private)
|
||||
end
|
||||
alias :kind_of? :is_a?
|
||||
|
||||
def persisted?
|
||||
!new?
|
||||
# ruby 1.9 feature
|
||||
# this allows ruby to know that the method is defined using
|
||||
# method_missing, and as such, method(:find_by_view) will actually
|
||||
# give a Method back, and not throw an error like in 1.8!
|
||||
def self.respond_to_missing?(m, include_private = false)
|
||||
has_view?(m) || has_view?(m.to_s[/^find_(by_.+)/, 1])
|
||||
end
|
||||
|
||||
def to_key
|
||||
|
@ -100,6 +104,26 @@ module CouchRest
|
|||
alias :to_param :id
|
||||
alias :new_record? :new?
|
||||
alias :new_document? :new?
|
||||
|
||||
# Compare this model with another by confirming to see
|
||||
# if the IDs and their databases match!
|
||||
#
|
||||
# Camparison of the database is required in case the
|
||||
# model has been proxied or loaded elsewhere.
|
||||
#
|
||||
# A Basic CouchRest document will only ever compare using
|
||||
# a Hash comparison on the attributes.
|
||||
def == other
|
||||
return false unless other.is_a?(Base)
|
||||
if id.nil? && other.id.nil?
|
||||
# no ids? assume comparing nested and revert to hash comparison
|
||||
to_hash == other.to_hash
|
||||
else
|
||||
database == other.database && id == other.id
|
||||
end
|
||||
end
|
||||
alias :eql? :==
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -5,21 +5,23 @@ module CouchRest #:nodoc:
|
|||
|
||||
module Callbacks
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
CALLBACKS = [
|
||||
:before_validation, :after_validation,
|
||||
:after_initialize,
|
||||
:before_create, :around_create, :after_create,
|
||||
:before_destroy, :around_destroy, :after_destroy,
|
||||
:before_save, :around_save, :after_save,
|
||||
:before_update, :around_update, :after_update,
|
||||
]
|
||||
|
||||
included do
|
||||
extend ActiveModel::Callbacks
|
||||
include ActiveModel::Validations::Callbacks
|
||||
|
||||
define_model_callbacks \
|
||||
:create,
|
||||
:destroy,
|
||||
:save,
|
||||
:update
|
||||
|
||||
define_model_callbacks :initialize, :only => :after
|
||||
define_model_callbacks :create, :destroy, :save, :update
|
||||
end
|
||||
|
||||
def valid?(*) #nodoc
|
||||
_run_validation_callbacks { super }
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -50,6 +50,16 @@ module CouchRest::Model
|
|||
super
|
||||
end
|
||||
|
||||
def delete(obj)
|
||||
couchrest_parent_will_change! if use_dirty? && self.length > 0
|
||||
super(obj)
|
||||
end
|
||||
|
||||
def delete_at(index)
|
||||
couchrest_parent_will_change! if use_dirty? && self.length > 0
|
||||
super(index)
|
||||
end
|
||||
|
||||
def build(*args)
|
||||
obj = casted_by_property.build(*args)
|
||||
self.push(obj)
|
||||
|
|
|
@ -244,6 +244,7 @@ module CouchRest
|
|||
else
|
||||
options = { :limit => per_page, :skip => per_page * (page - 1) }
|
||||
end
|
||||
options[:include_docs] = true
|
||||
view_options.merge(options)
|
||||
end
|
||||
|
||||
|
|
|
@ -1,13 +1,10 @@
|
|||
module CouchRest
|
||||
module Model
|
||||
module DocumentQueries
|
||||
|
||||
def self.included(base)
|
||||
base.extend(ClassMethods)
|
||||
end
|
||||
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
module ClassMethods
|
||||
|
||||
|
||||
# Load all documents that have the model_type_key's field equal to the
|
||||
# name of the current class. Take the standard set of
|
||||
# CouchRest::Database#view options.
|
||||
|
@ -73,7 +70,7 @@ module CouchRest
|
|||
end
|
||||
end
|
||||
alias :find :get
|
||||
|
||||
|
||||
# Load a document from the database by id
|
||||
# An exception will be raised if the document isn't found
|
||||
#
|
||||
|
|
|
@ -1,37 +1,37 @@
|
|||
module CouchRest::Model
|
||||
module CastedModel
|
||||
|
||||
module Embeddable
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
# Include Attributes early to ensure super() will work
|
||||
include CouchRest::Attributes
|
||||
|
||||
included do
|
||||
include CouchRest::Model::Configuration
|
||||
include CouchRest::Model::Callbacks
|
||||
include CouchRest::Model::Properties
|
||||
include CouchRest::Model::PropertyProtection
|
||||
include CouchRest::Model::Associations
|
||||
include CouchRest::Model::Validations
|
||||
include CouchRest::Model::Callbacks
|
||||
include CouchRest::Model::CastedBy
|
||||
include CouchRest::Model::Dirty
|
||||
include CouchRest::Model::Callbacks
|
||||
|
||||
class_eval do
|
||||
# Override CastedBy's base_doc?
|
||||
def base_doc?
|
||||
false # Can never be base doc!
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
def initialize(keys = {})
|
||||
raise StandardError unless self.is_a? Hash
|
||||
prepare_all_attributes(keys)
|
||||
# Initialize a new Casted Model. Accepts the same
|
||||
# options as CouchRest::Model::Base for preparing and initializing
|
||||
# attributes.
|
||||
def initialize(keys = {}, options = {})
|
||||
super()
|
||||
end
|
||||
|
||||
def []= key, value
|
||||
super(key.to_s, value)
|
||||
end
|
||||
|
||||
def [] key
|
||||
super(key.to_s)
|
||||
prepare_all_attributes(keys, options)
|
||||
run_callbacks(:initialize) { self }
|
||||
end
|
||||
|
||||
# False if the casted model has already
|
||||
|
@ -65,6 +65,14 @@ module CouchRest::Model
|
|||
end
|
||||
alias :attributes= :update_attributes_without_saving
|
||||
|
||||
end # End Embeddable
|
||||
|
||||
# Provide backwards compatability with previous versions (pre 1.1.0)
|
||||
module CastedModel
|
||||
extend ActiveSupport::Concern
|
||||
included do
|
||||
include CouchRest::Model::Embeddable
|
||||
end
|
||||
end
|
||||
|
||||
end
|
|
@ -21,14 +21,15 @@ module CouchRest
|
|||
|
||||
# Creates the document in the db. Raises an exception
|
||||
# if the document is not created properly.
|
||||
def create!
|
||||
self.class.fail_validate!(self) unless self.create
|
||||
def create!(options = {})
|
||||
self.class.fail_validate!(self) unless self.create(options)
|
||||
end
|
||||
|
||||
# Trigger the callbacks (before, after, around)
|
||||
# only if the document isn't new
|
||||
def update(options = {})
|
||||
raise "Calling #{self.class.name}#update on document that has not been created!" if self.new?
|
||||
raise "Cannot save a destroyed document!" if destroyed?
|
||||
raise "Calling #{self.class.name}#update on document that has not been created!" if new?
|
||||
return false unless perform_validations(options)
|
||||
return true if !self.disable_dirty && !self.changed?
|
||||
_run_update_callbacks do
|
||||
|
@ -54,19 +55,25 @@ module CouchRest
|
|||
end
|
||||
|
||||
# Deletes the document from the database. Runs the :destroy callbacks.
|
||||
# Removes the <tt>_id</tt> and <tt>_rev</tt> fields, preparing the
|
||||
# document to be saved to a new <tt>_id</tt> if required.
|
||||
def destroy
|
||||
_run_destroy_callbacks do
|
||||
result = database.delete_doc(self)
|
||||
if result['ok']
|
||||
self.delete('_rev')
|
||||
self.delete('_id')
|
||||
@_destroyed = true
|
||||
self.freeze
|
||||
end
|
||||
result['ok']
|
||||
end
|
||||
end
|
||||
|
||||
def destroyed?
|
||||
!!@_destroyed
|
||||
end
|
||||
|
||||
def persisted?
|
||||
!new? && !destroyed?
|
||||
end
|
||||
|
||||
# Update the document's attributes and save. For example:
|
||||
#
|
||||
# doc.update_attributes :name => "Fred"
|
||||
|
@ -85,7 +92,7 @@ module CouchRest
|
|||
#
|
||||
# Returns self.
|
||||
def reload
|
||||
merge!(self.class.get(id))
|
||||
prepare_all_attributes(database.get(id), :directly_set_attributes => true)
|
||||
self
|
||||
end
|
||||
|
||||
|
@ -104,22 +111,25 @@ module CouchRest
|
|||
|
||||
module ClassMethods
|
||||
|
||||
# Creates a new instance, bypassing attribute protection
|
||||
# Creates a new instance, bypassing attribute protection and
|
||||
# uses the type field to determine which model to use to instanatiate
|
||||
# the new object.
|
||||
#
|
||||
# ==== Returns
|
||||
# a document instance
|
||||
#
|
||||
def build_from_database(doc = {})
|
||||
base = (doc[model_type_key].blank? || doc[model_type_key] == self.to_s) ? self : doc[model_type_key].constantize
|
||||
base.new(doc, :directly_set_attributes => true)
|
||||
def build_from_database(doc = {}, options = {}, &block)
|
||||
src = doc[model_type_key]
|
||||
base = (src.blank? || src == self.to_s) ? self : src.constantize
|
||||
base.new(doc, options.merge(:directly_set_attributes => true), &block)
|
||||
end
|
||||
|
||||
# Defines an instance and save it directly to the database
|
||||
#
|
||||
# ==== Returns
|
||||
# returns the reloaded document
|
||||
def create(attributes = {})
|
||||
instance = new(attributes)
|
||||
def create(attributes = {}, &block)
|
||||
instance = new(attributes, &block)
|
||||
instance.create
|
||||
instance
|
||||
end
|
||||
|
@ -128,8 +138,8 @@ module CouchRest
|
|||
#
|
||||
# ==== Returns
|
||||
# returns the reloaded document or raises an exception
|
||||
def create!(attributes = {})
|
||||
instance = new(attributes)
|
||||
def create!(attributes = {}, &block)
|
||||
instance = new(attributes, &block)
|
||||
instance.create!
|
||||
instance
|
||||
end
|
||||
|
|
|
@ -12,8 +12,10 @@ module CouchRest
|
|||
raise "You can only mixin Properties in a class responding to [] and []=, if you tried to mixin CastedModel, make sure your class inherits from Hash or responds to the proper methods" unless (method_defined?(:[]) && method_defined?(:[]=))
|
||||
end
|
||||
|
||||
def as_json(options = nil)
|
||||
Hash[self].reject{|k,v| v.nil?}.as_json(options)
|
||||
# Provide an attribute hash ready to be sent to CouchDB but with
|
||||
# all the nil attributes removed.
|
||||
def as_couch_json
|
||||
super.delete_if{|k,v| v.nil?}
|
||||
end
|
||||
|
||||
# Returns the Class properties with their values
|
||||
|
@ -80,17 +82,18 @@ module CouchRest
|
|||
self.disable_dirty = dirty
|
||||
end
|
||||
|
||||
def prepare_all_attributes(doc = {}, options = {})
|
||||
def prepare_all_attributes(attrs = {}, options = {})
|
||||
self.disable_dirty = !!options[:directly_set_attributes]
|
||||
apply_all_property_defaults
|
||||
if options[:directly_set_attributes]
|
||||
directly_set_read_only_attributes(doc)
|
||||
directly_set_read_only_attributes(attrs)
|
||||
directly_set_attributes(attrs, true)
|
||||
else
|
||||
doc = remove_protected_attributes(doc)
|
||||
attrs = remove_protected_attributes(attrs)
|
||||
directly_set_attributes(attrs)
|
||||
end
|
||||
res = doc.nil? ? doc : directly_set_attributes(doc)
|
||||
self.disable_dirty = false
|
||||
res
|
||||
self
|
||||
end
|
||||
|
||||
def find_property!(property)
|
||||
|
@ -101,16 +104,13 @@ module CouchRest
|
|||
|
||||
# Set all the attributes and return a hash with the attributes
|
||||
# that have not been accepted.
|
||||
def directly_set_attributes(hash)
|
||||
hash.reject do |attribute_name, attribute_value|
|
||||
if self.respond_to?("#{attribute_name}=")
|
||||
self.send("#{attribute_name}=", attribute_value)
|
||||
true
|
||||
elsif mass_assign_any_attribute # config option
|
||||
self[attribute_name] = attribute_value
|
||||
true
|
||||
else
|
||||
false
|
||||
def directly_set_attributes(hash, mass_assign = false)
|
||||
return if hash.nil?
|
||||
hash.reject do |key, value|
|
||||
if self.respond_to?("#{key}=")
|
||||
self.send("#{key}=", value)
|
||||
elsif mass_assign || mass_assign_any_attribute
|
||||
self[key] = value
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -151,15 +151,13 @@ module CouchRest
|
|||
# These properties are casted as Time objects, so they should always
|
||||
# be set to UTC.
|
||||
def timestamps!
|
||||
class_eval <<-EOS, __FILE__, __LINE__
|
||||
property(:updated_at, Time, :read_only => true, :protected => true, :auto_validation => false)
|
||||
property(:created_at, Time, :read_only => true, :protected => true, :auto_validation => false)
|
||||
property(:updated_at, Time, :read_only => true, :protected => true, :auto_validation => false)
|
||||
property(:created_at, Time, :read_only => true, :protected => true, :auto_validation => false)
|
||||
|
||||
set_callback :save, :before do |object|
|
||||
write_attribute('updated_at', Time.now)
|
||||
write_attribute('created_at', Time.now) if object.new?
|
||||
end
|
||||
EOS
|
||||
set_callback :save, :before do |object|
|
||||
write_attribute('updated_at', Time.now)
|
||||
write_attribute('created_at', Time.now) if object.new?
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
|
@ -170,8 +168,8 @@ module CouchRest
|
|||
# check if this property is going to casted
|
||||
type = options.delete(:type) || options.delete(:cast_as)
|
||||
if block_given?
|
||||
type = Class.new(Hash) do
|
||||
include CastedModel
|
||||
type = Class.new do
|
||||
include Embeddable
|
||||
end
|
||||
if block.arity == 1 # Traditional, with options
|
||||
type.class_eval { yield type }
|
||||
|
@ -193,42 +191,32 @@ module CouchRest
|
|||
|
||||
# defines the getter for the property (and optional aliases)
|
||||
def create_property_getter(property)
|
||||
# meth = property.name
|
||||
class_eval <<-EOS, __FILE__, __LINE__ + 1
|
||||
def #{property.name}
|
||||
read_attribute('#{property.name}')
|
||||
end
|
||||
EOS
|
||||
define_method(property.name) do
|
||||
read_attribute(property.name)
|
||||
end
|
||||
|
||||
if ['boolean', TrueClass.to_s.downcase].include?(property.type.to_s.downcase)
|
||||
class_eval <<-EOS, __FILE__, __LINE__
|
||||
def #{property.name}?
|
||||
value = read_attribute('#{property.name}')
|
||||
!(value.nil? || value == false)
|
||||
end
|
||||
EOS
|
||||
define_method("#{property.name}?") do
|
||||
value = read_attribute(property.name)
|
||||
!(value.nil? || value == false)
|
||||
end
|
||||
end
|
||||
|
||||
if property.alias
|
||||
class_eval <<-EOS, __FILE__, __LINE__ + 1
|
||||
alias #{property.alias.to_sym} #{property.name.to_sym}
|
||||
EOS
|
||||
alias_method(property.alias, property.name.to_sym)
|
||||
end
|
||||
end
|
||||
|
||||
# defines the setter for the property (and optional aliases)
|
||||
def create_property_setter(property)
|
||||
property_name = property.name
|
||||
class_eval <<-EOS
|
||||
def #{property_name}=(value)
|
||||
write_attribute('#{property_name}', value)
|
||||
end
|
||||
EOS
|
||||
name = property.name
|
||||
|
||||
define_method("#{name}=") do |value|
|
||||
write_attribute(name, value)
|
||||
end
|
||||
|
||||
if property.alias
|
||||
class_eval <<-EOS
|
||||
alias #{property.alias.to_sym}= #{property_name.to_sym}=
|
||||
EOS
|
||||
alias_method "#{property.alias}=", "#{name}="
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -27,19 +27,15 @@ module CouchRest::Model
|
|||
if value.nil?
|
||||
value = []
|
||||
elsif [Hash, HashWithIndifferentAccess].include?(value.class)
|
||||
# Assume provided as a Hash where key is index!
|
||||
data = value
|
||||
value = [ ]
|
||||
data.keys.sort.each do |k|
|
||||
value << data[k]
|
||||
end
|
||||
# Assume provided as a params hash where key is index
|
||||
value = parameter_hash_to_array(value)
|
||||
elsif !value.is_a?(Array)
|
||||
raise "Expecting an array or keyed hash for property #{parent.class.name}##{self.name}"
|
||||
end
|
||||
arr = value.collect { |data| cast_value(parent, data) }
|
||||
# allow casted_by calls to be passed up chain by wrapping in CastedArray
|
||||
CastedArray.new(arr, self, parent)
|
||||
elsif (type == Object || type == Hash) && (value.class == Hash)
|
||||
elsif (type == Object || type == Hash) && (value.is_a?(Hash))
|
||||
# allow casted_by calls to be passed up chain by wrapping in CastedHash
|
||||
CastedHash[value, self, parent]
|
||||
elsif !value.nil?
|
||||
|
@ -47,9 +43,8 @@ module CouchRest::Model
|
|||
end
|
||||
end
|
||||
|
||||
# Cast an individual value, not an array
|
||||
# Cast an individual value
|
||||
def cast_value(parent, value)
|
||||
raise "An array inside an array cannot be casted, use CastedModel" if value.is_a?(Array)
|
||||
value = typecast_value(value, self)
|
||||
associate_casted_value_to_parent(parent, value)
|
||||
end
|
||||
|
@ -78,6 +73,14 @@ module CouchRest::Model
|
|||
|
||||
private
|
||||
|
||||
def parameter_hash_to_array(source)
|
||||
value = [ ]
|
||||
source.keys.each do |k|
|
||||
value[k.to_i] = source[k]
|
||||
end
|
||||
value.compact
|
||||
end
|
||||
|
||||
def associate_casted_value_to_parent(parent, value)
|
||||
value.casted_by = parent if value.respond_to?(:casted_by)
|
||||
value.casted_by_property = self if value.respond_to?(:casted_by_property)
|
||||
|
|
|
@ -73,12 +73,12 @@ module CouchRest
|
|||
end
|
||||
|
||||
# Base
|
||||
def new(*args)
|
||||
proxy_update(model.new(*args))
|
||||
def new(attrs = {}, options = {}, &block)
|
||||
proxy_block_update(:new, attrs, options, &block)
|
||||
end
|
||||
|
||||
def build_from_database(doc = {})
|
||||
proxy_update(model.build_from_database(doc))
|
||||
def build_from_database(attrs = {}, options = {}, &block)
|
||||
proxy_block_update(:build_from_database, attrs, options, &block)
|
||||
end
|
||||
|
||||
def method_missing(m, *args, &block)
|
||||
|
@ -170,6 +170,13 @@ module CouchRest
|
|||
end
|
||||
end
|
||||
|
||||
def proxy_block_update(method, *args, &block)
|
||||
model.send(method, *args) do |doc|
|
||||
proxy_update(doc)
|
||||
yield doc if block_given?
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -18,7 +18,7 @@ CouchRest::Design.class_eval do
|
|||
flatten =
|
||||
lambda {|r|
|
||||
(recurse = lambda {|v|
|
||||
if v.is_a?(Hash)
|
||||
if v.is_a?(Hash) || v.is_a?(CouchRest::Document)
|
||||
v.to_a.map{|v| recurse.call(v)}.flatten
|
||||
elsif v.is_a?(Array)
|
||||
v.flatten.map{|v| recurse.call(v)}
|
||||
|
|
|
@ -13,22 +13,33 @@ module CouchRest
|
|||
# Validations may be applied to both Model::Base and Model::CastedModel
|
||||
module Validations
|
||||
extend ActiveSupport::Concern
|
||||
included do
|
||||
include ActiveModel::Validations
|
||||
include ActiveModel::Validations::Callbacks
|
||||
include ActiveModel::Validations
|
||||
|
||||
# Determine if the document is valid.
|
||||
#
|
||||
# @example Is the document valid?
|
||||
# person.valid?
|
||||
#
|
||||
# @example Is the document valid in a context?
|
||||
# person.valid?(:create)
|
||||
#
|
||||
# @param [ Symbol ] context The optional validation context.
|
||||
#
|
||||
# @return [ true, false ] True if valid, false if not.
|
||||
#
|
||||
def valid?(context = nil)
|
||||
super context ? context : (new? ? :create : :update)
|
||||
end
|
||||
|
||||
|
||||
module ClassMethods
|
||||
|
||||
# Validates the associated casted model. This method should not be
|
||||
|
||||
# Validates the associated casted model. This method should not be
|
||||
# used within your code as it is automatically included when a CastedModel
|
||||
# is used inside the model.
|
||||
#
|
||||
def validates_casted_model(*args)
|
||||
validates_with(CastedModelValidator, _merge_attributes(args))
|
||||
end
|
||||
|
||||
|
||||
# Validates if the field is unique for this type of document. Automatically creates
|
||||
# a view if one does not already exist and performs a search for all matching
|
||||
# documents.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue