mark_mapper 0.0.1
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.
- 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
|