couchrest_model 1.0.0.beta7
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.
- data/LICENSE +176 -0
- data/README.md +320 -0
- data/Rakefile +71 -0
- data/THANKS.md +19 -0
- data/examples/model/example.rb +144 -0
- data/history.txt +180 -0
- data/lib/couchrest/model.rb +10 -0
- data/lib/couchrest/model/associations.rb +207 -0
- data/lib/couchrest/model/attribute_protection.rb +74 -0
- data/lib/couchrest/model/attributes.rb +75 -0
- data/lib/couchrest/model/base.rb +111 -0
- data/lib/couchrest/model/callbacks.rb +27 -0
- data/lib/couchrest/model/casted_array.rb +39 -0
- data/lib/couchrest/model/casted_model.rb +68 -0
- data/lib/couchrest/model/class_proxy.rb +122 -0
- data/lib/couchrest/model/collection.rb +260 -0
- data/lib/couchrest/model/design_doc.rb +126 -0
- data/lib/couchrest/model/document_queries.rb +82 -0
- data/lib/couchrest/model/errors.rb +23 -0
- data/lib/couchrest/model/extended_attachments.rb +73 -0
- data/lib/couchrest/model/persistence.rb +141 -0
- data/lib/couchrest/model/properties.rb +144 -0
- data/lib/couchrest/model/property.rb +96 -0
- data/lib/couchrest/model/support/couchrest.rb +19 -0
- data/lib/couchrest/model/support/hash.rb +9 -0
- data/lib/couchrest/model/typecast.rb +170 -0
- data/lib/couchrest/model/validations.rb +68 -0
- data/lib/couchrest/model/validations/casted_model.rb +14 -0
- data/lib/couchrest/model/validations/locale/en.yml +5 -0
- data/lib/couchrest/model/validations/uniqueness.rb +45 -0
- data/lib/couchrest/model/views.rb +167 -0
- data/lib/couchrest_model.rb +56 -0
- data/spec/couchrest/assocations_spec.rb +213 -0
- data/spec/couchrest/attachment_spec.rb +148 -0
- data/spec/couchrest/attribute_protection_spec.rb +153 -0
- data/spec/couchrest/base_spec.rb +463 -0
- data/spec/couchrest/casted_model_spec.rb +424 -0
- data/spec/couchrest/casted_spec.rb +75 -0
- data/spec/couchrest/class_proxy_spec.rb +132 -0
- data/spec/couchrest/inherited_spec.rb +40 -0
- data/spec/couchrest/persistence_spec.rb +409 -0
- data/spec/couchrest/property_spec.rb +804 -0
- data/spec/couchrest/subclass_spec.rb +99 -0
- data/spec/couchrest/validations.rb +73 -0
- data/spec/couchrest/view_spec.rb +463 -0
- data/spec/fixtures/attachments/README +3 -0
- data/spec/fixtures/attachments/couchdb.png +0 -0
- data/spec/fixtures/attachments/test.html +11 -0
- data/spec/fixtures/base.rb +139 -0
- data/spec/fixtures/more/article.rb +35 -0
- data/spec/fixtures/more/card.rb +17 -0
- data/spec/fixtures/more/cat.rb +19 -0
- data/spec/fixtures/more/course.rb +25 -0
- data/spec/fixtures/more/event.rb +8 -0
- data/spec/fixtures/more/invoice.rb +14 -0
- data/spec/fixtures/more/person.rb +9 -0
- data/spec/fixtures/more/question.rb +7 -0
- data/spec/fixtures/more/service.rb +10 -0
- data/spec/fixtures/more/user.rb +22 -0
- data/spec/fixtures/views/lib.js +3 -0
- data/spec/fixtures/views/test_view/lib.js +3 -0
- data/spec/fixtures/views/test_view/only-map.js +4 -0
- data/spec/fixtures/views/test_view/test-map.js +3 -0
- data/spec/fixtures/views/test_view/test-reduce.js +3 -0
- data/spec/spec.opts +5 -0
- data/spec/spec_helper.rb +48 -0
- data/utils/remap.rb +27 -0
- data/utils/subset.rb +30 -0
- metadata +232 -0
@@ -0,0 +1,23 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module CouchRest
|
3
|
+
module Model
|
4
|
+
module Errors
|
5
|
+
|
6
|
+
class CouchRestModelError < StandardError; end
|
7
|
+
|
8
|
+
# Raised when a persisence method ending in ! fails validation. The message
|
9
|
+
# will contain the full error messages from the +Document+ in question.
|
10
|
+
#
|
11
|
+
# Example:
|
12
|
+
#
|
13
|
+
# <tt>Validations.new(person.errors)</tt>
|
14
|
+
class Validations < CouchRestModelError
|
15
|
+
attr_reader :document
|
16
|
+
def initialize(document)
|
17
|
+
@document = document
|
18
|
+
super("Validation Failed: #{@document.errors.full_messages.join(", ")}")
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module CouchRest
|
2
|
+
module Model
|
3
|
+
module ExtendedAttachments
|
4
|
+
|
5
|
+
# Add a file attachment to the current document. Expects
|
6
|
+
# :file and :name to be included in the arguments.
|
7
|
+
def create_attachment(args={})
|
8
|
+
raise ArgumentError unless args[:file] && args[:name]
|
9
|
+
return if has_attachment?(args[:name])
|
10
|
+
self['_attachments'] ||= {}
|
11
|
+
set_attachment_attr(args)
|
12
|
+
rescue ArgumentError => e
|
13
|
+
raise ArgumentError, 'You must specify :file and :name'
|
14
|
+
end
|
15
|
+
|
16
|
+
# reads the data from an attachment
|
17
|
+
def read_attachment(attachment_name)
|
18
|
+
database.fetch_attachment(self, attachment_name)
|
19
|
+
end
|
20
|
+
|
21
|
+
# modifies a file attachment on the current doc
|
22
|
+
def update_attachment(args={})
|
23
|
+
raise ArgumentError unless args[:file] && args[:name]
|
24
|
+
return unless has_attachment?(args[:name])
|
25
|
+
delete_attachment(args[:name])
|
26
|
+
set_attachment_attr(args)
|
27
|
+
rescue ArgumentError => e
|
28
|
+
raise ArgumentError, 'You must specify :file and :name'
|
29
|
+
end
|
30
|
+
|
31
|
+
# deletes a file attachment from the current doc
|
32
|
+
def delete_attachment(attachment_name)
|
33
|
+
return unless self['_attachments']
|
34
|
+
self['_attachments'].delete attachment_name
|
35
|
+
end
|
36
|
+
|
37
|
+
# returns true if attachment_name exists
|
38
|
+
def has_attachment?(attachment_name)
|
39
|
+
!!(self['_attachments'] && self['_attachments'][attachment_name] && !self['_attachments'][attachment_name].empty?)
|
40
|
+
end
|
41
|
+
|
42
|
+
# returns URL to fetch the attachment from
|
43
|
+
def attachment_url(attachment_name)
|
44
|
+
return unless has_attachment?(attachment_name)
|
45
|
+
"#{database.root}/#{self.id}/#{attachment_name}"
|
46
|
+
end
|
47
|
+
|
48
|
+
# returns URI to fetch the attachment from
|
49
|
+
def attachment_uri(attachment_name)
|
50
|
+
return unless has_attachment?(attachment_name)
|
51
|
+
"#{database.uri}/#{self.id}/#{attachment_name}"
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def get_mime_type(path)
|
57
|
+
return nil if path.nil?
|
58
|
+
type = ::MIME::Types.type_for(path)
|
59
|
+
type.empty? ? nil : type.first.content_type
|
60
|
+
end
|
61
|
+
|
62
|
+
def set_attachment_attr(args)
|
63
|
+
content_type = args[:content_type] ? args[:content_type] : get_mime_type(args[:file].path)
|
64
|
+
content_type ||= (get_mime_type(args[:name]) || 'text/plain')
|
65
|
+
self['_attachments'][args[:name]] = {
|
66
|
+
'content_type' => content_type,
|
67
|
+
'data' => args[:file].read
|
68
|
+
}
|
69
|
+
end
|
70
|
+
|
71
|
+
end # module ExtendedAttachments
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
module CouchRest
|
2
|
+
module Model
|
3
|
+
module Persistence
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
# Create the document. Validation is enabled by default and will return
|
7
|
+
# false if the document is not valid. If all goes well, the document will
|
8
|
+
# be returned.
|
9
|
+
def create(options = {})
|
10
|
+
return false unless perform_validations(options)
|
11
|
+
_run_create_callbacks do
|
12
|
+
_run_save_callbacks do
|
13
|
+
set_unique_id if new? && self.respond_to?(:set_unique_id)
|
14
|
+
result = database.save_doc(self)
|
15
|
+
(result["ok"] == true) ? self : false
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# Creates the document in the db. Raises an exception
|
21
|
+
# if the document is not created properly.
|
22
|
+
def create!
|
23
|
+
self.class.fail_validate!(self) unless self.create
|
24
|
+
end
|
25
|
+
|
26
|
+
# Trigger the callbacks (before, after, around)
|
27
|
+
# only if the document isn't new
|
28
|
+
def update(options = {})
|
29
|
+
raise "Calling #{self.class.name}#update on document that has not been created!" if self.new?
|
30
|
+
return false unless perform_validations(options)
|
31
|
+
_run_update_callbacks do
|
32
|
+
_run_save_callbacks do
|
33
|
+
result = database.save_doc(self)
|
34
|
+
result["ok"] == true
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# Trigger the callbacks (before, after, around) and save the document
|
40
|
+
def save(options = {})
|
41
|
+
self.new? ? create(options) : update(options)
|
42
|
+
end
|
43
|
+
|
44
|
+
# Saves the document to the db using save. Raises an exception
|
45
|
+
# if the document is not saved properly.
|
46
|
+
def save!
|
47
|
+
self.class.fail_validate!(self) unless self.save
|
48
|
+
true
|
49
|
+
end
|
50
|
+
|
51
|
+
# Deletes the document from the database. Runs the :destroy callbacks.
|
52
|
+
# Removes the <tt>_id</tt> and <tt>_rev</tt> fields, preparing the
|
53
|
+
# document to be saved to a new <tt>_id</tt> if required.
|
54
|
+
def destroy
|
55
|
+
_run_destroy_callbacks do
|
56
|
+
result = database.delete_doc(self)
|
57
|
+
if result['ok']
|
58
|
+
self.delete('_rev')
|
59
|
+
self.delete('_id')
|
60
|
+
end
|
61
|
+
result['ok']
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
protected
|
66
|
+
|
67
|
+
def perform_validations(options = {})
|
68
|
+
perform_validation = case options
|
69
|
+
when Hash
|
70
|
+
options[:validate] != false
|
71
|
+
else
|
72
|
+
options
|
73
|
+
end
|
74
|
+
perform_validation ? valid? : true
|
75
|
+
end
|
76
|
+
|
77
|
+
|
78
|
+
module ClassMethods
|
79
|
+
|
80
|
+
# Creates a new instance, bypassing attribute protection
|
81
|
+
#
|
82
|
+
#
|
83
|
+
# ==== Returns
|
84
|
+
# a document instance
|
85
|
+
def create_from_database(doc = {})
|
86
|
+
base = (doc['couchrest-type'].blank? || doc['couchrest-type'] == self.to_s) ? self : doc['couchrest-type'].constantize
|
87
|
+
base.new(doc, :directly_set_attributes => true)
|
88
|
+
end
|
89
|
+
|
90
|
+
# Defines an instance and save it directly to the database
|
91
|
+
#
|
92
|
+
# ==== Returns
|
93
|
+
# returns the reloaded document
|
94
|
+
def create(attributes = {})
|
95
|
+
instance = new(attributes)
|
96
|
+
instance.create
|
97
|
+
instance
|
98
|
+
end
|
99
|
+
|
100
|
+
# Defines an instance and save it directly to the database
|
101
|
+
#
|
102
|
+
# ==== Returns
|
103
|
+
# returns the reloaded document or raises an exception
|
104
|
+
def create!(attributes = {})
|
105
|
+
instance = new(attributes)
|
106
|
+
instance.create!
|
107
|
+
instance
|
108
|
+
end
|
109
|
+
|
110
|
+
# Name a method that will be called before the document is first saved,
|
111
|
+
# which returns a string to be used for the document's <tt>_id</tt>.
|
112
|
+
#
|
113
|
+
# Because CouchDB enforces a constraint that each id must be unique,
|
114
|
+
# this can be used to enforce eg: uniq usernames. Note that this id
|
115
|
+
# must be globally unique across all document types which share a
|
116
|
+
# database, so if you'd like to scope uniqueness to this class, you
|
117
|
+
# should use the class name as part of the unique id.
|
118
|
+
def unique_id method = nil, &block
|
119
|
+
if method
|
120
|
+
define_method :set_unique_id do
|
121
|
+
self['_id'] ||= self.send(method)
|
122
|
+
end
|
123
|
+
elsif block
|
124
|
+
define_method :set_unique_id do
|
125
|
+
uniqid = block.call(self)
|
126
|
+
raise ArgumentError, "unique_id block must not return nil" if uniqid.nil?
|
127
|
+
self['_id'] ||= uniqid
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
# Raise an error if validation failed.
|
133
|
+
def fail_validate!(document)
|
134
|
+
raise Errors::Validations.new(document)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
@@ -0,0 +1,144 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module CouchRest
|
3
|
+
module Model
|
4
|
+
module Properties
|
5
|
+
|
6
|
+
class IncludeError < StandardError; end
|
7
|
+
|
8
|
+
def self.included(base)
|
9
|
+
base.class_eval <<-EOS, __FILE__, __LINE__ + 1
|
10
|
+
extlib_inheritable_accessor(:properties) unless self.respond_to?(:properties)
|
11
|
+
self.properties ||= []
|
12
|
+
EOS
|
13
|
+
base.extend(ClassMethods)
|
14
|
+
raise CouchRest::Mixins::Properties::IncludeError, "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 (base.new.respond_to?(:[]) && base.new.respond_to?(:[]=))
|
15
|
+
end
|
16
|
+
|
17
|
+
# Returns the Class properties
|
18
|
+
#
|
19
|
+
# ==== Returns
|
20
|
+
# Array:: the list of properties for model's class
|
21
|
+
def properties
|
22
|
+
self.class.properties
|
23
|
+
end
|
24
|
+
|
25
|
+
def read_attribute(property)
|
26
|
+
self[property.to_s]
|
27
|
+
end
|
28
|
+
|
29
|
+
def write_attribute(property, value)
|
30
|
+
prop = property.is_a?(Property) ? property : self.class.properties.detect {|p| p.to_s == property.to_s}
|
31
|
+
raise "Missing property definition for #{property.to_s}" unless prop
|
32
|
+
self[prop.to_s] = prop.cast(self, value)
|
33
|
+
end
|
34
|
+
|
35
|
+
def apply_all_property_defaults
|
36
|
+
return if self.respond_to?(:new?) && (new? == false)
|
37
|
+
# TODO: cache the default object
|
38
|
+
self.class.properties.each do |property|
|
39
|
+
write_attribute(property, property.default_value)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
module ClassMethods
|
44
|
+
|
45
|
+
def property(name, *options, &block)
|
46
|
+
opts = { }
|
47
|
+
type = options.shift
|
48
|
+
if type.class != Hash
|
49
|
+
opts[:type] = type
|
50
|
+
opts.merge!(options.shift || {})
|
51
|
+
else
|
52
|
+
opts.update(type)
|
53
|
+
end
|
54
|
+
existing_property = self.properties.find{|p| p.name == name.to_s}
|
55
|
+
if existing_property.nil? || (existing_property.default != opts[:default])
|
56
|
+
define_property(name, opts, &block)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# Automatically set <tt>updated_at</tt> and <tt>created_at</tt> fields
|
61
|
+
# on the document whenever saving occurs. CouchRest uses a pretty
|
62
|
+
# decent time format by default. See Time#to_json
|
63
|
+
def timestamps!
|
64
|
+
class_eval <<-EOS, __FILE__, __LINE__
|
65
|
+
property(:updated_at, Time, :read_only => true, :protected => true, :auto_validation => false)
|
66
|
+
property(:created_at, Time, :read_only => true, :protected => true, :auto_validation => false)
|
67
|
+
|
68
|
+
set_callback :save, :before do |object|
|
69
|
+
write_attribute('updated_at', Time.now)
|
70
|
+
write_attribute('created_at', Time.now) if object.new?
|
71
|
+
end
|
72
|
+
EOS
|
73
|
+
end
|
74
|
+
|
75
|
+
protected
|
76
|
+
|
77
|
+
# This is not a thread safe operation, if you have to set new properties at runtime
|
78
|
+
# make sure a mutex is used.
|
79
|
+
def define_property(name, options={}, &block)
|
80
|
+
# check if this property is going to casted
|
81
|
+
type = options.delete(:type) || options.delete(:cast_as)
|
82
|
+
if block_given?
|
83
|
+
type = Class.new(Hash) do
|
84
|
+
include CastedModel
|
85
|
+
end
|
86
|
+
type.class_eval { yield type }
|
87
|
+
type = [type] # inject as an array
|
88
|
+
end
|
89
|
+
property = Property.new(name, type, options)
|
90
|
+
create_property_getter(property)
|
91
|
+
create_property_setter(property) unless property.read_only == true
|
92
|
+
if property.type_class.respond_to?(:validates_casted_model)
|
93
|
+
validates_casted_model property.name
|
94
|
+
end
|
95
|
+
properties << property
|
96
|
+
property
|
97
|
+
end
|
98
|
+
|
99
|
+
# defines the getter for the property (and optional aliases)
|
100
|
+
def create_property_getter(property)
|
101
|
+
# meth = property.name
|
102
|
+
class_eval <<-EOS, __FILE__, __LINE__ + 1
|
103
|
+
def #{property.name}
|
104
|
+
read_attribute('#{property.name}')
|
105
|
+
end
|
106
|
+
EOS
|
107
|
+
|
108
|
+
if ['boolean', TrueClass.to_s.downcase].include?(property.type.to_s.downcase)
|
109
|
+
class_eval <<-EOS, __FILE__, __LINE__
|
110
|
+
def #{property.name}?
|
111
|
+
value = read_attribute('#{property.name}')
|
112
|
+
!(value.nil? || value == false)
|
113
|
+
end
|
114
|
+
EOS
|
115
|
+
end
|
116
|
+
|
117
|
+
if property.alias
|
118
|
+
class_eval <<-EOS, __FILE__, __LINE__ + 1
|
119
|
+
alias #{property.alias.to_sym} #{property.name.to_sym}
|
120
|
+
EOS
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
# defines the setter for the property (and optional aliases)
|
125
|
+
def create_property_setter(property)
|
126
|
+
property_name = property.name
|
127
|
+
class_eval <<-EOS
|
128
|
+
def #{property_name}=(value)
|
129
|
+
write_attribute('#{property_name}', value)
|
130
|
+
end
|
131
|
+
EOS
|
132
|
+
|
133
|
+
if property.alias
|
134
|
+
class_eval <<-EOS
|
135
|
+
alias #{property.alias.to_sym}= #{property_name.to_sym}=
|
136
|
+
EOS
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
end # module ClassMethods
|
141
|
+
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module CouchRest::Model
|
3
|
+
class Property
|
4
|
+
|
5
|
+
include ::CouchRest::Model::Typecast
|
6
|
+
|
7
|
+
attr_reader :name, :type, :type_class, :read_only, :alias, :default, :casted, :init_method, :options
|
8
|
+
|
9
|
+
# Attribute to define.
|
10
|
+
# All Properties are assumed casted unless the type is nil.
|
11
|
+
def initialize(name, type = nil, options = {})
|
12
|
+
@name = name.to_s
|
13
|
+
@casted = true
|
14
|
+
parse_type(type)
|
15
|
+
parse_options(options)
|
16
|
+
self
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_s
|
20
|
+
name
|
21
|
+
end
|
22
|
+
|
23
|
+
# Cast the provided value using the properties details.
|
24
|
+
def cast(parent, value)
|
25
|
+
return value unless casted
|
26
|
+
if type.is_a?(Array)
|
27
|
+
if value.nil?
|
28
|
+
value = []
|
29
|
+
elsif [Hash, HashWithIndifferentAccess].include?(value.class)
|
30
|
+
# Assume provided as a Hash where key is index!
|
31
|
+
data = value
|
32
|
+
value = [ ]
|
33
|
+
data.keys.sort.each do |k|
|
34
|
+
value << data[k]
|
35
|
+
end
|
36
|
+
elsif value.class != Array
|
37
|
+
raise "Expecting an array or keyed hash for property #{parent.class.name}##{self.name}"
|
38
|
+
end
|
39
|
+
arr = value.collect { |data| cast_value(parent, data) }
|
40
|
+
# allow casted_by calls to be passed up chain by wrapping in CastedArray
|
41
|
+
value = type_class != String ? CastedArray.new(arr, self) : arr
|
42
|
+
value.casted_by = parent if value.respond_to?(:casted_by)
|
43
|
+
elsif !value.nil?
|
44
|
+
value = cast_value(parent, value)
|
45
|
+
end
|
46
|
+
value
|
47
|
+
end
|
48
|
+
|
49
|
+
# Cast an individual value, not an array
|
50
|
+
def cast_value(parent, value)
|
51
|
+
raise "An array inside an array cannot be casted, use CastedModel" if value.is_a?(Array)
|
52
|
+
value = typecast_value(value, self)
|
53
|
+
associate_casted_value_to_parent(parent, value)
|
54
|
+
end
|
55
|
+
|
56
|
+
def default_value
|
57
|
+
return if default.nil?
|
58
|
+
if default.class == Proc
|
59
|
+
default.call
|
60
|
+
else
|
61
|
+
Marshal.load(Marshal.dump(default))
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def associate_casted_value_to_parent(parent, value)
|
68
|
+
value.casted_by = parent if value.respond_to?(:casted_by)
|
69
|
+
value
|
70
|
+
end
|
71
|
+
|
72
|
+
def parse_type(type)
|
73
|
+
if type.nil?
|
74
|
+
@casted = false
|
75
|
+
@type = nil
|
76
|
+
@type_class = nil
|
77
|
+
else
|
78
|
+
base = type.is_a?(Array) ? type.first : type
|
79
|
+
base = Object if base.nil?
|
80
|
+
raise "Defining a property type as a #{type.class.name.humanize} is not supported in CouchRest Model!" if base.class != Class
|
81
|
+
@type_class = base
|
82
|
+
@type = type
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def parse_options(options)
|
87
|
+
@validation_format = options.delete(:format) if options[:format]
|
88
|
+
@read_only = options.delete(:read_only) if options[:read_only]
|
89
|
+
@alias = options.delete(:alias) if options[:alias]
|
90
|
+
@default = options.delete(:default) unless options[:default].nil?
|
91
|
+
@init_method = options[:init_method] ? options.delete(:init_method) : 'new'
|
92
|
+
@options = options
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
end
|