mark_mapper 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/README.rdoc +39 -0
- data/examples/attr_accessible.rb +24 -0
- data/examples/attr_protected.rb +24 -0
- data/examples/cache_key.rb +26 -0
- data/examples/custom_types.rb +26 -0
- data/examples/identity_map.rb +30 -0
- data/examples/identity_map/automatic.rb +2 -0
- data/examples/keys.rb +42 -0
- data/examples/modifiers/set.rb +27 -0
- data/examples/plugins.rb +40 -0
- data/examples/querying.rb +39 -0
- data/examples/sample_app.rb +43 -0
- data/examples/scopes.rb +56 -0
- data/examples/validating/embedded_docs.rb +31 -0
- data/lib/mark_mapper.rb +125 -0
- data/lib/mark_mapper/config.rb +90 -0
- data/lib/mark_mapper/connection.rb +60 -0
- data/lib/mark_mapper/criteria_hash.rb +194 -0
- data/lib/mark_mapper/document.rb +46 -0
- data/lib/mark_mapper/embedded_document.rb +32 -0
- data/lib/mark_mapper/exceptions.rb +33 -0
- data/lib/mark_mapper/extensions/array.rb +27 -0
- data/lib/mark_mapper/extensions/boolean.rb +45 -0
- data/lib/mark_mapper/extensions/date.rb +29 -0
- data/lib/mark_mapper/extensions/duplicable.rb +86 -0
- data/lib/mark_mapper/extensions/float.rb +18 -0
- data/lib/mark_mapper/extensions/hash.rb +26 -0
- data/lib/mark_mapper/extensions/integer.rb +27 -0
- data/lib/mark_mapper/extensions/kernel.rb +11 -0
- data/lib/mark_mapper/extensions/nil_class.rb +18 -0
- data/lib/mark_mapper/extensions/object.rb +30 -0
- data/lib/mark_mapper/extensions/object_id.rb +18 -0
- data/lib/mark_mapper/extensions/set.rb +20 -0
- data/lib/mark_mapper/extensions/string.rb +31 -0
- data/lib/mark_mapper/extensions/symbol.rb +87 -0
- data/lib/mark_mapper/extensions/time.rb +29 -0
- data/lib/mark_mapper/locale/en.yml +5 -0
- data/lib/mark_mapper/middleware/identity_map.rb +41 -0
- data/lib/mark_mapper/normalizers/criteria_hash_key.rb +17 -0
- data/lib/mark_mapper/normalizers/criteria_hash_value.rb +66 -0
- data/lib/mark_mapper/normalizers/fields_value.rb +26 -0
- data/lib/mark_mapper/normalizers/hash_key.rb +19 -0
- data/lib/mark_mapper/normalizers/integer.rb +19 -0
- data/lib/mark_mapper/normalizers/options_hash_value.rb +83 -0
- data/lib/mark_mapper/normalizers/sort_value.rb +55 -0
- data/lib/mark_mapper/options_hash.rb +103 -0
- data/lib/mark_mapper/pagination.rb +6 -0
- data/lib/mark_mapper/pagination/collection.rb +32 -0
- data/lib/mark_mapper/pagination/paginator.rb +46 -0
- data/lib/mark_mapper/plugins.rb +22 -0
- data/lib/mark_mapper/plugins/accessible.rb +61 -0
- data/lib/mark_mapper/plugins/active_model.rb +18 -0
- data/lib/mark_mapper/plugins/associations.rb +96 -0
- data/lib/mark_mapper/plugins/associations/base.rb +98 -0
- data/lib/mark_mapper/plugins/associations/belongs_to_association.rb +63 -0
- data/lib/mark_mapper/plugins/associations/belongs_to_polymorphic_proxy.rb +35 -0
- data/lib/mark_mapper/plugins/associations/belongs_to_proxy.rb +52 -0
- data/lib/mark_mapper/plugins/associations/collection.rb +29 -0
- data/lib/mark_mapper/plugins/associations/embedded_collection.rb +44 -0
- data/lib/mark_mapper/plugins/associations/in_array_proxy.rb +133 -0
- data/lib/mark_mapper/plugins/associations/many_association.rb +63 -0
- data/lib/mark_mapper/plugins/associations/many_documents_as_proxy.rb +28 -0
- data/lib/mark_mapper/plugins/associations/many_documents_proxy.rb +142 -0
- data/lib/mark_mapper/plugins/associations/many_embedded_polymorphic_proxy.rb +32 -0
- data/lib/mark_mapper/plugins/associations/many_embedded_proxy.rb +24 -0
- data/lib/mark_mapper/plugins/associations/many_polymorphic_proxy.rb +14 -0
- data/lib/mark_mapper/plugins/associations/one_as_proxy.rb +22 -0
- data/lib/mark_mapper/plugins/associations/one_association.rb +48 -0
- data/lib/mark_mapper/plugins/associations/one_embedded_polymorphic_proxy.rb +30 -0
- data/lib/mark_mapper/plugins/associations/one_embedded_proxy.rb +44 -0
- data/lib/mark_mapper/plugins/associations/one_proxy.rb +95 -0
- data/lib/mark_mapper/plugins/associations/proxy.rb +138 -0
- data/lib/mark_mapper/plugins/associations/single_association.rb +46 -0
- data/lib/mark_mapper/plugins/caching.rb +21 -0
- data/lib/mark_mapper/plugins/callbacks.rb +42 -0
- data/lib/mark_mapper/plugins/clone.rb +24 -0
- data/lib/mark_mapper/plugins/counter_cache.rb +97 -0
- data/lib/mark_mapper/plugins/dirty.rb +61 -0
- data/lib/mark_mapper/plugins/document.rb +41 -0
- data/lib/mark_mapper/plugins/dumpable.rb +22 -0
- data/lib/mark_mapper/plugins/dynamic_querying.rb +45 -0
- data/lib/mark_mapper/plugins/dynamic_querying/dynamic_finder.rb +44 -0
- data/lib/mark_mapper/plugins/embedded_callbacks.rb +81 -0
- data/lib/mark_mapper/plugins/embedded_document.rb +53 -0
- data/lib/mark_mapper/plugins/equality.rb +23 -0
- data/lib/mark_mapper/plugins/identity_map.rb +144 -0
- data/lib/mark_mapper/plugins/indexable.rb +86 -0
- data/lib/mark_mapper/plugins/inspect.rb +16 -0
- data/lib/mark_mapper/plugins/keys.rb +470 -0
- data/lib/mark_mapper/plugins/keys/key.rb +134 -0
- data/lib/mark_mapper/plugins/keys/static.rb +45 -0
- data/lib/mark_mapper/plugins/logger.rb +18 -0
- data/lib/mark_mapper/plugins/modifiers.rb +140 -0
- data/lib/mark_mapper/plugins/pagination.rb +16 -0
- data/lib/mark_mapper/plugins/partial_updates.rb +77 -0
- data/lib/mark_mapper/plugins/persistence.rb +79 -0
- data/lib/mark_mapper/plugins/protected.rb +45 -0
- data/lib/mark_mapper/plugins/querying.rb +173 -0
- data/lib/mark_mapper/plugins/querying/decorated_markmapper_query.rb +75 -0
- data/lib/mark_mapper/plugins/rails.rb +79 -0
- data/lib/mark_mapper/plugins/rails/active_record_association_adapter.rb +33 -0
- data/lib/mark_mapper/plugins/sci.rb +82 -0
- data/lib/mark_mapper/plugins/scopes.rb +28 -0
- data/lib/mark_mapper/plugins/serialization.rb +109 -0
- data/lib/mark_mapper/plugins/timestamps.rb +29 -0
- data/lib/mark_mapper/plugins/touch.rb +18 -0
- data/lib/mark_mapper/plugins/userstamps.rb +18 -0
- data/lib/mark_mapper/plugins/validations.rb +96 -0
- data/lib/mark_mapper/query.rb +278 -0
- data/lib/mark_mapper/railtie.rb +52 -0
- data/lib/mark_mapper/railtie/database.rake +65 -0
- data/lib/mark_mapper/translation.rb +10 -0
- data/lib/mark_mapper/version.rb +4 -0
- data/lib/rails/generators/mark_mapper/config/config_generator.rb +37 -0
- data/lib/rails/generators/mark_mapper/config/templates/marklogic.yml +19 -0
- data/lib/rails/generators/mark_mapper/model/model_generator.rb +40 -0
- data/lib/rails/generators/mark_mapper/model/templates/model.rb +17 -0
- data/spec/config/mark_mapper.yml +6 -0
- data/spec/examples_spec.rb +25 -0
- data/spec/functional/accessible_spec.rb +198 -0
- data/spec/functional/associations/belongs_to_polymorphic_proxy_spec.rb +64 -0
- data/spec/functional/associations/belongs_to_proxy_spec.rb +255 -0
- data/spec/functional/associations/in_array_proxy_spec.rb +349 -0
- data/spec/functional/associations/many_documents_as_proxy_spec.rb +230 -0
- data/spec/functional/associations/many_documents_proxy_spec.rb +968 -0
- data/spec/functional/associations/many_embedded_polymorphic_proxy_spec.rb +238 -0
- data/spec/functional/associations/many_embedded_proxy_spec.rb +288 -0
- data/spec/functional/associations/many_polymorphic_proxy_spec.rb +302 -0
- data/spec/functional/associations/one_as_proxy_spec.rb +489 -0
- data/spec/functional/associations/one_embedded_polymorphic_proxy_spec.rb +207 -0
- data/spec/functional/associations/one_embedded_proxy_spec.rb +100 -0
- data/spec/functional/associations/one_proxy_spec.rb +406 -0
- data/spec/functional/associations_spec.rb +48 -0
- data/spec/functional/caching_spec.rb +75 -0
- data/spec/functional/callbacks_spec.rb +330 -0
- data/spec/functional/counter_cache_spec.rb +235 -0
- data/spec/functional/dirty_spec.rb +316 -0
- data/spec/functional/document_spec.rb +310 -0
- data/spec/functional/dumpable_spec.rb +24 -0
- data/spec/functional/dynamic_querying_spec.rb +75 -0
- data/spec/functional/embedded_document_spec.rb +316 -0
- data/spec/functional/equality_spec.rb +20 -0
- data/spec/functional/extensions_spec.rb +16 -0
- data/spec/functional/identity_map_spec.rb +483 -0
- data/spec/functional/keys_spec.rb +339 -0
- data/spec/functional/logger_spec.rb +20 -0
- data/spec/functional/modifiers_spec.rb +446 -0
- data/spec/functional/options_hash_spec.rb +41 -0
- data/spec/functional/pagination_spec.rb +89 -0
- data/spec/functional/partial_updates_spec.rb +530 -0
- data/spec/functional/protected_spec.rb +199 -0
- data/spec/functional/querying_spec.rb +984 -0
- data/spec/functional/rails_spec.rb +55 -0
- data/spec/functional/sci_spec.rb +374 -0
- data/spec/functional/scopes_spec.rb +204 -0
- data/spec/functional/static_keys_spec.rb +153 -0
- data/spec/functional/timestamps_spec.rb +97 -0
- data/spec/functional/touch_spec.rb +125 -0
- data/spec/functional/userstamps_spec.rb +46 -0
- data/spec/functional/validations_spec.rb +416 -0
- data/spec/quality_spec.rb +51 -0
- data/spec/spec_helper.rb +150 -0
- data/spec/support/matchers.rb +15 -0
- data/spec/support/models.rb +256 -0
- data/spec/symbol_operator_spec.rb +70 -0
- data/spec/symbol_spec.rb +9 -0
- data/spec/unit/associations/base_spec.rb +146 -0
- data/spec/unit/associations/belongs_to_association_spec.rb +30 -0
- data/spec/unit/associations/many_association_spec.rb +64 -0
- data/spec/unit/associations/one_association_spec.rb +48 -0
- data/spec/unit/associations/proxy_spec.rb +103 -0
- data/spec/unit/clone_spec.rb +79 -0
- data/spec/unit/config_generator_spec.rb +24 -0
- data/spec/unit/criteria_hash_spec.rb +218 -0
- data/spec/unit/document_spec.rb +251 -0
- data/spec/unit/dynamic_finder_spec.rb +125 -0
- data/spec/unit/embedded_document_spec.rb +676 -0
- data/spec/unit/equality_spec.rb +38 -0
- data/spec/unit/exceptions_spec.rb +12 -0
- data/spec/unit/extensions_spec.rb +368 -0
- data/spec/unit/identity_map_middleware_spec.rb +134 -0
- data/spec/unit/inspect_spec.rb +47 -0
- data/spec/unit/key_spec.rb +276 -0
- data/spec/unit/keys_spec.rb +155 -0
- data/spec/unit/mark_mapper_spec.rb +37 -0
- data/spec/unit/model_generator_spec.rb +45 -0
- data/spec/unit/normalizers/criteria_hash_key_spec.rb +37 -0
- data/spec/unit/normalizers/criteria_hash_value_spec.rb +200 -0
- data/spec/unit/normalizers/fields_value_spec.rb +45 -0
- data/spec/unit/normalizers/hash_key_spec.rb +15 -0
- data/spec/unit/normalizers/integer_spec.rb +24 -0
- data/spec/unit/normalizers/options_hash_value_spec.rb +99 -0
- data/spec/unit/normalizers/sort_value_spec.rb +98 -0
- data/spec/unit/options_hash_spec.rb +64 -0
- data/spec/unit/pagination/collection_spec.rb +30 -0
- data/spec/unit/pagination/paginator_spec.rb +118 -0
- data/spec/unit/pagination_spec.rb +11 -0
- data/spec/unit/plugins_spec.rb +89 -0
- data/spec/unit/query_spec.rb +837 -0
- data/spec/unit/rails_compatibility_spec.rb +40 -0
- data/spec/unit/rails_reflect_on_association_spec.rb +118 -0
- data/spec/unit/rails_spec.rb +188 -0
- data/spec/unit/serialization_spec.rb +169 -0
- data/spec/unit/serializers/json_serializer_spec.rb +218 -0
- data/spec/unit/serializers/xml_serializer_spec.rb +198 -0
- data/spec/unit/time_zones_spec.rb +44 -0
- data/spec/unit/translation_spec.rb +27 -0
- data/spec/unit/validations_spec.rb +588 -0
- metadata +307 -0
@@ -0,0 +1,86 @@
|
|
1
|
+
module MarkMapper
|
2
|
+
module Plugins
|
3
|
+
module Indexable
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
module ClassMethods
|
7
|
+
# Get all the defined indexes for this document
|
8
|
+
#
|
9
|
+
# @example Get the indexes hash
|
10
|
+
# person.index_defs
|
11
|
+
#
|
12
|
+
# @return[ Hash ] A hash containing all the index definitions
|
13
|
+
#
|
14
|
+
# @since 0.0.1
|
15
|
+
def index_defs
|
16
|
+
@index_defs ||= {}
|
17
|
+
end
|
18
|
+
|
19
|
+
# Defines all the MarkLogic indexes for this document
|
20
|
+
#
|
21
|
+
# @example Define an index.
|
22
|
+
# Model.index :first_name, :type => String, :facet => true
|
23
|
+
#
|
24
|
+
# @param [ Symbol ] name The localname of the element to index.
|
25
|
+
# @param [ Hash ] options The options to pass to the index.
|
26
|
+
#
|
27
|
+
# @option options [ String ] :type The atomic type of the element to index.
|
28
|
+
# @option options [ Boolean ] :facet Whether to facet on this element index or not
|
29
|
+
#
|
30
|
+
# @since 0.0.1
|
31
|
+
def index(name, options = {})
|
32
|
+
options[:type] ||= String
|
33
|
+
options[:type] = options[:type].xs_type if options[:type].respond_to?(:xs_type)
|
34
|
+
|
35
|
+
raise InvalidIndexType, "Invalid index type: #{options[:type]}" unless [Boolean.xs_type, Integer.xs_type, String.xs_type, Float.xs_type].include? options[:type]
|
36
|
+
|
37
|
+
new_index =
|
38
|
+
begin
|
39
|
+
case options[:kind]
|
40
|
+
when "field" then MarkLogic::DatabaseSettings::RangeFieldIndex.new(name, options)
|
41
|
+
when "path" then MarkLogic::DatabaseSettings::RangePathIndex.new(name, options)
|
42
|
+
else MarkLogic::DatabaseSettings::RangeElementIndex.new(name, options)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
if !index_defs.has_key?(name.to_s)
|
47
|
+
index_defs[name.to_s] = new_index
|
48
|
+
MarkMapper.application.add_index(new_index)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# Removes the definition for an index
|
53
|
+
# Used for testing
|
54
|
+
#
|
55
|
+
# @example Remove an index
|
56
|
+
# Model.remove_index :name
|
57
|
+
#
|
58
|
+
# @param [ String, Symbol ] name The name of the index to remove
|
59
|
+
#
|
60
|
+
# @since 0.0.1
|
61
|
+
def remove_index(name)
|
62
|
+
index_defs.delete name.to_s
|
63
|
+
end
|
64
|
+
|
65
|
+
# Generates an xml string with bootstrap configuration for the indexes
|
66
|
+
# This is used when generating indexes automagically within MarkLogic
|
67
|
+
#
|
68
|
+
# @return [ String ] XML configuration
|
69
|
+
#
|
70
|
+
# @since 0.0.1
|
71
|
+
# def index_setup_xml
|
72
|
+
# xml = ""
|
73
|
+
# index_defs.values do |index|
|
74
|
+
# xml << index.setup_xml
|
75
|
+
# end
|
76
|
+
# xml
|
77
|
+
# end
|
78
|
+
end
|
79
|
+
|
80
|
+
included do
|
81
|
+
index :_id, :type => String
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
module MarkMapper
|
3
|
+
module Plugins
|
4
|
+
module Inspect
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
def inspect(include_nil = false)
|
8
|
+
keys = include_nil ? key_names : attributes.keys
|
9
|
+
attributes_as_nice_string = keys.sort.collect do |name|
|
10
|
+
"#{name}: #{self.send(:"#{name}").inspect}"
|
11
|
+
end.join(", ")
|
12
|
+
"#<#{self.class} #{attributes_as_nice_string}>"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,470 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'mark_mapper/plugins/keys/key'
|
3
|
+
require 'mark_mapper/plugins/keys/static'
|
4
|
+
|
5
|
+
module MarkMapper
|
6
|
+
module Plugins
|
7
|
+
module Keys
|
8
|
+
extend ActiveSupport::Concern
|
9
|
+
|
10
|
+
IS_RUBY_1_9 = method(:const_defined?).arity == 1
|
11
|
+
|
12
|
+
included do
|
13
|
+
extend ActiveSupport::DescendantsTracker
|
14
|
+
key :_id, ObjectId, :default => lambda { MarkLogic::ObjectId.new }
|
15
|
+
end
|
16
|
+
|
17
|
+
module ClassMethods
|
18
|
+
def inherited(descendant)
|
19
|
+
descendant.instance_variable_set(:@keys, keys.dup)
|
20
|
+
super
|
21
|
+
end
|
22
|
+
|
23
|
+
def keys
|
24
|
+
@keys ||= {}
|
25
|
+
end
|
26
|
+
|
27
|
+
def dynamic_keys
|
28
|
+
@dynamic_keys ||= Hash[*unaliased_keys.select {|k, v| v.dynamic? }.flatten(1)]
|
29
|
+
end
|
30
|
+
|
31
|
+
def defined_keys
|
32
|
+
@defined_keys ||= Hash[*unaliased_keys.select {|k, v| !v.dynamic? }.flatten(1)]
|
33
|
+
end
|
34
|
+
|
35
|
+
def unaliased_keys
|
36
|
+
@unaliased_keys ||= Hash[*keys.select {|k, v| k == v.name }.flatten(1)]
|
37
|
+
end
|
38
|
+
|
39
|
+
def dealias_keys(hash)
|
40
|
+
out = {}
|
41
|
+
hash.each do |k, v|
|
42
|
+
key = keys[k.to_s]
|
43
|
+
name = key && key.abbr || k
|
44
|
+
out[name] = k.to_s.match(/^\$/) && v.is_a?(Hash) ? dealias_keys(v) : v
|
45
|
+
end
|
46
|
+
out
|
47
|
+
end
|
48
|
+
|
49
|
+
def dealias_key(name)
|
50
|
+
key = keys[name.to_s]
|
51
|
+
key && key.abbr || k
|
52
|
+
end
|
53
|
+
|
54
|
+
alias_method :dealias, :dealias_keys
|
55
|
+
alias_method :unalias, :dealias_keys
|
56
|
+
|
57
|
+
def key(*args)
|
58
|
+
Key.new(*args).tap do |key|
|
59
|
+
keys[key.name] = key
|
60
|
+
keys[key.abbr] = key if key.abbr
|
61
|
+
create_accessors_for(key) if key.valid_ruby_name? && !key.reserved_name?
|
62
|
+
create_key_in_descendants(*args)
|
63
|
+
create_indexes_for(key)
|
64
|
+
create_validations_for(key)
|
65
|
+
@dynamic_keys = @defined_keys = @unaliased_keys = @object_id_keys = nil
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def remove_key(name)
|
70
|
+
if key = keys[name.to_s]
|
71
|
+
keys.delete key.name
|
72
|
+
keys.delete key.abbr
|
73
|
+
remove_method key.name if respond_to? "#{key.name}"
|
74
|
+
remove_method "#{key.name}=" if respond_to? "#{key.name}="
|
75
|
+
remove_method "#{key.name}?" if respond_to? "#{key.name}?"
|
76
|
+
remove_method "#{key.name}_before_type_cast" if respond_to? "#{key.name}_before_type_cast"
|
77
|
+
remove_key_in_descendants key.name
|
78
|
+
remove_validations_for key.name
|
79
|
+
@dynamic_keys = @defined_keys = @unaliased_keys = @object_id_keys = nil
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def persisted_name(name)
|
84
|
+
if key = keys[name.to_s]
|
85
|
+
key.persisted_name
|
86
|
+
else
|
87
|
+
name
|
88
|
+
end
|
89
|
+
end
|
90
|
+
alias_method :abbr, :persisted_name
|
91
|
+
|
92
|
+
def key?(key)
|
93
|
+
keys.key? key.to_s
|
94
|
+
end
|
95
|
+
|
96
|
+
def using_object_id?
|
97
|
+
object_id_key?(:_id)
|
98
|
+
end
|
99
|
+
|
100
|
+
def object_id_keys
|
101
|
+
@object_id_keys ||= unaliased_keys.keys.select { |key| keys[key].type == ObjectId }.map(&:to_sym)
|
102
|
+
end
|
103
|
+
|
104
|
+
def object_id_key?(name)
|
105
|
+
object_id_keys.include?(name.to_sym)
|
106
|
+
end
|
107
|
+
|
108
|
+
def to_marklogic(instance)
|
109
|
+
instance && instance.to_marklogic
|
110
|
+
end
|
111
|
+
|
112
|
+
def from_marklogic(value)
|
113
|
+
value && (value.instance_of?(self) ? value : load(value))
|
114
|
+
end
|
115
|
+
|
116
|
+
# load is overridden in identity map to ensure same objects are loaded
|
117
|
+
def load(attrs, with_cast = false)
|
118
|
+
return nil if attrs.nil?
|
119
|
+
begin
|
120
|
+
attrs['_type'] ? attrs['_type'].constantize : self
|
121
|
+
rescue NameError
|
122
|
+
self
|
123
|
+
end.allocate.initialize_from_database(attrs, with_cast)
|
124
|
+
end
|
125
|
+
|
126
|
+
private
|
127
|
+
def key_accessors_module_defined?
|
128
|
+
# :nocov:
|
129
|
+
if IS_RUBY_1_9
|
130
|
+
const_defined?('MarkMapperKeys')
|
131
|
+
else
|
132
|
+
const_defined?('MarkMapperKeys', false)
|
133
|
+
end
|
134
|
+
# :nocov:
|
135
|
+
end
|
136
|
+
|
137
|
+
def accessors_module
|
138
|
+
if key_accessors_module_defined?
|
139
|
+
const_get 'MarkMapperKeys'
|
140
|
+
else
|
141
|
+
const_set 'MarkMapperKeys', Module.new
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def create_accessors_for(key)
|
146
|
+
accessors = ""
|
147
|
+
if key.read_accessor?
|
148
|
+
accessors << <<-end_eval
|
149
|
+
def #{key.name}
|
150
|
+
read_key(:#{key.name})
|
151
|
+
end
|
152
|
+
|
153
|
+
def #{key.name}_before_type_cast
|
154
|
+
read_key_before_type_cast(:#{key.name})
|
155
|
+
end
|
156
|
+
end_eval
|
157
|
+
end
|
158
|
+
|
159
|
+
if key.write_accessor?
|
160
|
+
accessors << <<-end_eval
|
161
|
+
def #{key.name}=(value)
|
162
|
+
write_key(:#{key.name}, value)
|
163
|
+
end
|
164
|
+
end_eval
|
165
|
+
end
|
166
|
+
|
167
|
+
if key.predicate_accessor?
|
168
|
+
accessors << <<-end_eval
|
169
|
+
def #{key.name}?
|
170
|
+
read_key(:#{key.name}).present?
|
171
|
+
end
|
172
|
+
end_eval
|
173
|
+
end
|
174
|
+
|
175
|
+
if block_given?
|
176
|
+
accessors_module.module_eval do
|
177
|
+
yield
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
accessors_module.module_eval accessors
|
182
|
+
include accessors_module
|
183
|
+
end
|
184
|
+
|
185
|
+
def create_key_in_descendants(*args)
|
186
|
+
descendants.each { |descendant| descendant.key(*args) }
|
187
|
+
end
|
188
|
+
|
189
|
+
def remove_key_in_descendants(name)
|
190
|
+
descendants.each { |descendant| descendant.remove_key(name) }
|
191
|
+
end
|
192
|
+
|
193
|
+
def create_indexes_for(key)
|
194
|
+
if key.options[:index] && !key.embeddable?
|
195
|
+
warn "[DEPRECATION] :index option when defining key #{key.name.inspect} is deprecated. Put indexes in `db/indexes.rb`"
|
196
|
+
ensure_index key.name
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
def create_validations_for(key)
|
201
|
+
attribute = key.name.to_sym
|
202
|
+
|
203
|
+
if key.options[:required]
|
204
|
+
if key.type == Boolean
|
205
|
+
validates_inclusion_of attribute, :in => [true, false]
|
206
|
+
else
|
207
|
+
validates_presence_of(attribute)
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
if key.options[:unique]
|
212
|
+
validates_uniqueness_of(attribute)
|
213
|
+
end
|
214
|
+
|
215
|
+
if key.options[:numeric]
|
216
|
+
number_options = key.type == Integer ? {:only_integer => true} : {}
|
217
|
+
validates_numericality_of(attribute, number_options)
|
218
|
+
end
|
219
|
+
|
220
|
+
if key.options[:format]
|
221
|
+
validates_format_of(attribute, :with => key.options[:format])
|
222
|
+
end
|
223
|
+
|
224
|
+
if key.options[:in]
|
225
|
+
validates_inclusion_of(attribute, :in => key.options[:in])
|
226
|
+
end
|
227
|
+
|
228
|
+
if key.options[:not_in]
|
229
|
+
validates_exclusion_of(attribute, :in => key.options[:not_in])
|
230
|
+
end
|
231
|
+
|
232
|
+
if key.options[:length]
|
233
|
+
length_options = case key.options[:length]
|
234
|
+
when Integer
|
235
|
+
{:minimum => 0, :maximum => key.options[:length]}
|
236
|
+
when Range
|
237
|
+
{:within => key.options[:length]}
|
238
|
+
when Hash
|
239
|
+
key.options[:length]
|
240
|
+
end
|
241
|
+
validates_length_of(attribute, length_options)
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
def remove_validations_for(name)
|
246
|
+
name = name.to_sym
|
247
|
+
a_name = [name]
|
248
|
+
|
249
|
+
_validators.reject!{ |key, _| key == name }
|
250
|
+
remove_validate_callbacks a_name
|
251
|
+
end
|
252
|
+
|
253
|
+
def remove_validate_callbacks(a_name)
|
254
|
+
chain = _validate_callbacks.dup.reject do |callback|
|
255
|
+
f = callback.raw_filter
|
256
|
+
f.respond_to?(:attributes) && f.attributes == a_name
|
257
|
+
end
|
258
|
+
reset_callbacks(:validate)
|
259
|
+
chain.each do |callback|
|
260
|
+
set_callback 'validate', callback.raw_filter
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
end
|
265
|
+
|
266
|
+
def initialize(attrs={})
|
267
|
+
@_new = true
|
268
|
+
init_ivars
|
269
|
+
initialize_default_values(attrs)
|
270
|
+
self.attributes = attrs
|
271
|
+
yield self if block_given?
|
272
|
+
end
|
273
|
+
|
274
|
+
def initialize_from_database(attrs={}, with_cast = false)
|
275
|
+
@_new = false
|
276
|
+
init_ivars
|
277
|
+
initialize_default_values(attrs)
|
278
|
+
load_from_database(attrs, with_cast)
|
279
|
+
self
|
280
|
+
end
|
281
|
+
|
282
|
+
def persisted?
|
283
|
+
!new? && !destroyed?
|
284
|
+
end
|
285
|
+
|
286
|
+
def attributes=(attrs)
|
287
|
+
return if attrs == nil || attrs.blank?
|
288
|
+
|
289
|
+
attrs.each_pair do |key, value|
|
290
|
+
if respond_to?(:"#{key}=")
|
291
|
+
self.send(:"#{key}=", value)
|
292
|
+
else
|
293
|
+
self[key] = value
|
294
|
+
end
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
def to_marklogic(include_abbreviatons = true)
|
299
|
+
Hash.new.tap do |attrs|
|
300
|
+
self.class.unaliased_keys.each do |name, key|
|
301
|
+
value = self.read_key(key.name)
|
302
|
+
if key.type == ObjectId || !value.nil?
|
303
|
+
attrs[include_abbreviatons && key.persisted_name || name] = key.set(value)
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
embedded_associations.each do |association|
|
308
|
+
if documents = instance_variable_get(association.ivar)
|
309
|
+
if association.is_a?(Associations::OneAssociation)
|
310
|
+
attrs[association.name] = documents.to_marklogic
|
311
|
+
else
|
312
|
+
attrs[association.name] = documents.map(&:to_marklogic)
|
313
|
+
end
|
314
|
+
end
|
315
|
+
end
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
319
|
+
def attributes
|
320
|
+
to_marklogic(false).with_indifferent_access
|
321
|
+
end
|
322
|
+
|
323
|
+
def assign(attrs={})
|
324
|
+
warn "[DEPRECATION] #assign is deprecated, use #attributes="
|
325
|
+
self.attributes = attrs
|
326
|
+
end
|
327
|
+
|
328
|
+
def update_attributes(attrs={})
|
329
|
+
self.attributes = attrs
|
330
|
+
save
|
331
|
+
end
|
332
|
+
|
333
|
+
def update_attributes!(attrs={})
|
334
|
+
self.attributes = attrs
|
335
|
+
save!
|
336
|
+
end
|
337
|
+
|
338
|
+
def update_attribute(name, value)
|
339
|
+
self.send(:"#{name}=", value)
|
340
|
+
save(:validate => false)
|
341
|
+
end
|
342
|
+
|
343
|
+
def id
|
344
|
+
self[:_id]
|
345
|
+
end
|
346
|
+
|
347
|
+
def id=(value)
|
348
|
+
if self.class.using_object_id?
|
349
|
+
value = ObjectId.to_marklogic(value)
|
350
|
+
end
|
351
|
+
|
352
|
+
self[:_id] = value
|
353
|
+
end
|
354
|
+
|
355
|
+
def keys
|
356
|
+
self.class.keys
|
357
|
+
end
|
358
|
+
|
359
|
+
def read_key(key_name)
|
360
|
+
key_name_sym = key_name.to_sym
|
361
|
+
if @_dynamic_attributes && @_dynamic_attributes.key?(key_name_sym)
|
362
|
+
@_dynamic_attributes[key_name_sym]
|
363
|
+
elsif key = keys[key_name.to_s]
|
364
|
+
if key.ivar && instance_variable_defined?(key.ivar)
|
365
|
+
value = instance_variable_get(key.ivar)
|
366
|
+
else
|
367
|
+
if key.ivar
|
368
|
+
instance_variable_set key.ivar, key.get(nil)
|
369
|
+
else
|
370
|
+
@_dynamic_attributes[key_name_sym] = key.get(nil)
|
371
|
+
end
|
372
|
+
end
|
373
|
+
end
|
374
|
+
end
|
375
|
+
|
376
|
+
def [](key_name); read_key(key_name); end
|
377
|
+
def attribute(key_name); read_key(key_name); end
|
378
|
+
|
379
|
+
def []=(name, value)
|
380
|
+
write_key(name, value)
|
381
|
+
end
|
382
|
+
|
383
|
+
def key_names
|
384
|
+
@key_names ||= keys.keys
|
385
|
+
end
|
386
|
+
|
387
|
+
def non_embedded_keys
|
388
|
+
@non_embedded_keys ||= keys.values.select { |key| !key.embeddable? }
|
389
|
+
end
|
390
|
+
|
391
|
+
def embedded_keys
|
392
|
+
@embedded_keys ||= keys.values.select(&:embeddable?)
|
393
|
+
end
|
394
|
+
|
395
|
+
protected
|
396
|
+
|
397
|
+
def unalias_key(name)
|
398
|
+
name = name.to_s
|
399
|
+
if key = keys[name]
|
400
|
+
key.name
|
401
|
+
else
|
402
|
+
name
|
403
|
+
end
|
404
|
+
end
|
405
|
+
|
406
|
+
private
|
407
|
+
|
408
|
+
def init_ivars
|
409
|
+
@__mm_keys = self.class.keys # Not dumpable
|
410
|
+
@__mm_default_keys = @__mm_keys.values.select(&:default?) # Not dumpable
|
411
|
+
@_dynamic_attributes = {} # Dumpable
|
412
|
+
end
|
413
|
+
|
414
|
+
def load_from_database(attrs, with_cast = false)
|
415
|
+
return if attrs == nil || attrs.blank?
|
416
|
+
|
417
|
+
attrs.each do |key, value|
|
418
|
+
if !@__mm_keys.key?(key) && respond_to?(:"#{key}=")
|
419
|
+
self.send(:"#{key}=", value)
|
420
|
+
else
|
421
|
+
internal_write_key key, value, with_cast
|
422
|
+
end
|
423
|
+
end
|
424
|
+
end
|
425
|
+
|
426
|
+
def set_parent_document(key, value)
|
427
|
+
if key.type and value.instance_of?(key.type) && key.embeddable? && value.respond_to?(:_parent_document)
|
428
|
+
value._parent_document = self
|
429
|
+
end
|
430
|
+
end
|
431
|
+
|
432
|
+
# This exists to be patched over by plugins, while letting us still get to the undecorated
|
433
|
+
# version of the method.
|
434
|
+
def write_key(name, value)
|
435
|
+
init_ivars unless @__mm_keys
|
436
|
+
internal_write_key(name.to_s, value)
|
437
|
+
end
|
438
|
+
|
439
|
+
def internal_write_key(name, value, cast = true)
|
440
|
+
key = @__mm_keys[name] || dynamic_key(name)
|
441
|
+
as_marklogic = cast ? key.set(value) : value
|
442
|
+
as_typecast = key.get(as_marklogic)
|
443
|
+
if key.ivar
|
444
|
+
if key.embeddable?
|
445
|
+
set_parent_document(key, value)
|
446
|
+
set_parent_document(key, as_typecast)
|
447
|
+
end
|
448
|
+
instance_variable_set key.ivar, as_typecast
|
449
|
+
else
|
450
|
+
@_dynamic_attributes[key.name.to_sym] = as_typecast
|
451
|
+
end
|
452
|
+
@attributes = nil
|
453
|
+
value
|
454
|
+
end
|
455
|
+
|
456
|
+
def dynamic_key(name)
|
457
|
+
self.class.key(name, :__dynamic => true)
|
458
|
+
end
|
459
|
+
|
460
|
+
def initialize_default_values(except = {})
|
461
|
+
@__mm_default_keys.each do |key|
|
462
|
+
if !(except && except.key?(key.name))
|
463
|
+
internal_write_key key.name, key.default_value, false
|
464
|
+
end
|
465
|
+
end
|
466
|
+
end
|
467
|
+
#end private
|
468
|
+
end
|
469
|
+
end
|
470
|
+
end
|