2010-06-20 22:01:11 +02:00
|
|
|
module CouchRest
|
|
|
|
module Model
|
2011-06-08 18:22:35 +02:00
|
|
|
class Base < CouchRest::Document
|
2010-06-20 22:01:11 +02:00
|
|
|
|
|
|
|
extend ActiveModel::Naming
|
|
|
|
|
2010-09-17 23:00:55 +02:00
|
|
|
include CouchRest::Model::Configuration
|
2011-04-30 00:34:12 +02:00
|
|
|
include CouchRest::Model::Connection
|
2010-06-20 22:01:11 +02:00
|
|
|
include CouchRest::Model::Persistence
|
2011-04-29 21:40:36 +02:00
|
|
|
include CouchRest::Model::DocumentQueries
|
2010-06-20 22:01:11 +02:00
|
|
|
include CouchRest::Model::Views
|
|
|
|
include CouchRest::Model::DesignDoc
|
|
|
|
include CouchRest::Model::ExtendedAttachments
|
|
|
|
include CouchRest::Model::ClassProxy
|
2011-02-09 21:21:03 +01:00
|
|
|
include CouchRest::Model::Proxyable
|
2010-06-20 22:01:11 +02:00
|
|
|
include CouchRest::Model::Collection
|
2010-10-22 15:39:12 +02:00
|
|
|
include CouchRest::Model::PropertyProtection
|
2010-06-20 22:01:11 +02:00
|
|
|
include CouchRest::Model::Associations
|
|
|
|
include CouchRest::Model::Validations
|
2011-06-09 01:05:22 +02:00
|
|
|
include CouchRest::Model::Callbacks
|
2011-02-06 04:32:23 +01:00
|
|
|
include CouchRest::Model::Designs
|
2011-03-03 08:28:57 +01:00
|
|
|
include CouchRest::Model::CastedBy
|
2011-04-20 16:44:49 +02:00
|
|
|
include CouchRest::Model::Dirty
|
2011-06-08 22:31:57 +02:00
|
|
|
include CouchRest::Model::Callbacks
|
2010-06-20 22:01:11 +02:00
|
|
|
|
|
|
|
def self.subclasses
|
|
|
|
@subclasses ||= []
|
|
|
|
end
|
2011-04-20 10:47:36 +02:00
|
|
|
|
2010-06-20 22:01:11 +02:00
|
|
|
def self.inherited(subklass)
|
|
|
|
super
|
|
|
|
subklass.send(:include, CouchRest::Model::Properties)
|
2011-03-03 08:28:57 +01:00
|
|
|
|
2010-06-20 22:01:11 +02:00
|
|
|
subklass.class_eval <<-EOS, __FILE__, __LINE__ + 1
|
|
|
|
def self.inherited(subklass)
|
|
|
|
super
|
|
|
|
subklass.properties = self.properties.dup
|
|
|
|
# This is nasty:
|
|
|
|
subklass._validators = self._validators.dup
|
|
|
|
end
|
|
|
|
EOS
|
|
|
|
subclasses << subklass
|
|
|
|
end
|
2011-04-20 10:47:36 +02:00
|
|
|
|
2010-08-04 04:09:05 +02:00
|
|
|
# Instantiate a new CouchRest::Model::Base by preparing all properties
|
2010-06-20 22:01:11 +02:00
|
|
|
# using the provided document hash.
|
|
|
|
#
|
|
|
|
# Options supported:
|
2011-04-20 10:47:36 +02:00
|
|
|
#
|
2011-06-25 19:24:43 +02:00
|
|
|
# * :directly_set_attributes, true when data comes directly from database
|
|
|
|
# * :database, provide an alternative database
|
2010-06-20 22:01:11 +02:00
|
|
|
#
|
2011-05-11 21:53:28 +02:00
|
|
|
# If a block is provided the new model will be passed into the
|
|
|
|
# block so that it can be populated.
|
2011-06-08 18:22:35 +02:00
|
|
|
def initialize(attributes = {}, options = {})
|
|
|
|
super()
|
|
|
|
prepare_all_attributes(attributes, options)
|
|
|
|
# set the instance's database, if provided
|
2011-02-09 21:21:03 +01:00
|
|
|
self.database = options[:database] unless options[:database].nil?
|
2010-06-20 22:01:11 +02:00
|
|
|
unless self['_id'] && self['_rev']
|
2010-09-17 23:00:55 +02:00
|
|
|
self[self.model_type_key] = self.class.to_s
|
2010-06-20 22:01:11 +02:00
|
|
|
end
|
2011-06-08 18:22:35 +02:00
|
|
|
|
2011-05-11 21:53:28 +02:00
|
|
|
yield self if block_given?
|
|
|
|
|
2010-06-20 22:01:11 +02:00
|
|
|
after_initialize if respond_to?(:after_initialize)
|
2011-06-25 19:24:43 +02:00
|
|
|
run_callbacks(:initialize) { self }
|
2010-06-20 22:01:11 +02:00
|
|
|
end
|
2011-04-20 10:47:36 +02:00
|
|
|
|
|
|
|
|
2010-06-20 22:01:11 +02:00
|
|
|
# Temp solution to make the view_by methods available
|
|
|
|
def self.method_missing(m, *args, &block)
|
|
|
|
if has_view?(m)
|
|
|
|
query = args.shift || {}
|
|
|
|
return view(m, query, *args, &block)
|
|
|
|
elsif m.to_s =~ /^find_(by_.+)/
|
|
|
|
view_name = $1
|
|
|
|
if has_view?(view_name)
|
|
|
|
return first_from_view(view_name, *args)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
super
|
|
|
|
end
|
2011-04-20 10:47:36 +02:00
|
|
|
|
2011-07-31 04:40:31 +02:00
|
|
|
# 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
|
|
|
|
|
|
|
|
# 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
|
|
|
|
|
2010-06-21 14:13:19 +02:00
|
|
|
def to_key
|
2011-04-20 10:47:36 +02:00
|
|
|
new? ? nil : [id]
|
2010-06-21 14:13:19 +02:00
|
|
|
end
|
2010-06-21 13:58:19 +02:00
|
|
|
|
2010-06-21 14:13:19 +02:00
|
|
|
alias :to_param :id
|
2010-06-20 22:01:11 +02:00
|
|
|
alias :new_record? :new?
|
|
|
|
alias :new_document? :new?
|
2011-06-09 01:49:09 +02:00
|
|
|
|
|
|
|
# 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)
|
2011-06-25 02:30:47 +02:00
|
|
|
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
|
2011-06-09 01:49:09 +02:00
|
|
|
end
|
|
|
|
alias :eql? :==
|
|
|
|
|
2011-04-20 10:47:36 +02:00
|
|
|
end
|
2010-06-20 22:01:11 +02:00
|
|
|
end
|
|
|
|
end
|