mack-data_mapper 0.8.1 → 0.8.2
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/lib/gems/addressable-2.0.0/lib/addressable/idna.rb +4867 -0
- data/lib/gems/addressable-2.0.0/lib/addressable/uri.rb +2469 -0
- data/lib/gems/addressable-2.0.0/lib/addressable/version.rb +35 -0
- data/lib/gems/dm-aggregates-0.9.7/lib/dm-aggregates/adapters/data_objects_adapter.rb +85 -0
- data/lib/gems/dm-aggregates-0.9.7/lib/dm-aggregates/aggregate_functions.rb +201 -0
- data/lib/gems/dm-aggregates-0.9.7/lib/dm-aggregates/collection.rb +11 -0
- data/lib/gems/dm-aggregates-0.9.7/lib/dm-aggregates/model.rb +11 -0
- data/lib/gems/dm-aggregates-0.9.7/lib/dm-aggregates/repository.rb +7 -0
- data/lib/gems/dm-aggregates-0.9.7/lib/dm-aggregates/support/symbol.rb +21 -0
- data/lib/gems/dm-aggregates-0.9.7/lib/dm-aggregates/version.rb +7 -0
- data/lib/gems/dm-aggregates-0.9.7/lib/dm-aggregates.rb +15 -0
- data/lib/gems/dm-core-0.9.7/lib/dm-core/adapters/abstract_adapter.rb +209 -0
- data/lib/gems/dm-core-0.9.7/lib/dm-core/adapters/data_objects_adapter.rb +709 -0
- data/lib/gems/dm-core-0.9.7/lib/dm-core/adapters/in_memory_adapter.rb +87 -0
- data/lib/gems/dm-core-0.9.7/lib/dm-core/adapters/mysql_adapter.rb +136 -0
- data/lib/gems/dm-core-0.9.7/lib/dm-core/adapters/postgres_adapter.rb +188 -0
- data/lib/gems/dm-core-0.9.7/lib/dm-core/adapters/sqlite3_adapter.rb +105 -0
- data/lib/gems/dm-core-0.9.7/lib/dm-core/adapters.rb +22 -0
- data/lib/gems/dm-core-0.9.7/lib/dm-core/associations/many_to_many.rb +147 -0
- data/lib/gems/dm-core-0.9.7/lib/dm-core/associations/many_to_one.rb +107 -0
- data/lib/gems/dm-core-0.9.7/lib/dm-core/associations/one_to_many.rb +318 -0
- data/lib/gems/dm-core-0.9.7/lib/dm-core/associations/one_to_one.rb +61 -0
- data/lib/gems/dm-core-0.9.7/lib/dm-core/associations/relationship.rb +223 -0
- data/lib/gems/dm-core-0.9.7/lib/dm-core/associations/relationship_chain.rb +81 -0
- data/lib/gems/dm-core-0.9.7/lib/dm-core/associations.rb +200 -0
- data/lib/gems/dm-core-0.9.7/lib/dm-core/auto_migrations.rb +105 -0
- data/lib/gems/dm-core-0.9.7/lib/dm-core/collection.rb +642 -0
- data/lib/gems/dm-core-0.9.7/lib/dm-core/dependency_queue.rb +32 -0
- data/lib/gems/dm-core-0.9.7/lib/dm-core/hook.rb +11 -0
- data/lib/gems/dm-core-0.9.7/lib/dm-core/identity_map.rb +42 -0
- data/lib/gems/dm-core-0.9.7/lib/dm-core/is.rb +16 -0
- data/lib/gems/dm-core-0.9.7/lib/dm-core/logger.rb +232 -0
- data/lib/gems/dm-core-0.9.7/lib/dm-core/migrations/destructive_migrations.rb +17 -0
- data/lib/gems/dm-core-0.9.7/lib/dm-core/migrator.rb +29 -0
- data/lib/gems/dm-core-0.9.7/lib/dm-core/model.rb +488 -0
- data/lib/gems/dm-core-0.9.7/lib/dm-core/naming_conventions.rb +84 -0
- data/lib/gems/dm-core-0.9.7/lib/dm-core/property.rb +663 -0
- data/lib/gems/dm-core-0.9.7/lib/dm-core/property_set.rb +169 -0
- data/lib/gems/dm-core-0.9.7/lib/dm-core/query.rb +628 -0
- data/lib/gems/dm-core-0.9.7/lib/dm-core/repository.rb +159 -0
- data/lib/gems/dm-core-0.9.7/lib/dm-core/resource.rb +637 -0
- data/lib/gems/dm-core-0.9.7/lib/dm-core/scope.rb +58 -0
- data/lib/gems/dm-core-0.9.7/lib/dm-core/support/array.rb +13 -0
- data/lib/gems/dm-core-0.9.7/lib/dm-core/support/assertions.rb +8 -0
- data/lib/gems/dm-core-0.9.7/lib/dm-core/support/errors.rb +23 -0
- data/lib/gems/dm-core-0.9.7/lib/dm-core/support/kernel.rb +11 -0
- data/lib/gems/dm-core-0.9.7/lib/dm-core/support/symbol.rb +41 -0
- data/lib/gems/dm-core-0.9.7/lib/dm-core/support.rb +7 -0
- data/lib/gems/dm-core-0.9.7/lib/dm-core/transaction.rb +267 -0
- data/lib/gems/dm-core-0.9.7/lib/dm-core/type.rb +160 -0
- data/lib/gems/dm-core-0.9.7/lib/dm-core/type_map.rb +80 -0
- data/lib/gems/dm-core-0.9.7/lib/dm-core/types/boolean.rb +7 -0
- data/lib/gems/dm-core-0.9.7/lib/dm-core/types/discriminator.rb +34 -0
- data/lib/gems/dm-core-0.9.7/lib/dm-core/types/object.rb +24 -0
- data/lib/gems/dm-core-0.9.7/lib/dm-core/types/paranoid_boolean.rb +34 -0
- data/lib/gems/dm-core-0.9.7/lib/dm-core/types/paranoid_datetime.rb +33 -0
- data/lib/gems/dm-core-0.9.7/lib/dm-core/types/serial.rb +9 -0
- data/lib/gems/dm-core-0.9.7/lib/dm-core/types/text.rb +10 -0
- data/lib/gems/dm-core-0.9.7/lib/dm-core/types.rb +19 -0
- data/lib/gems/dm-core-0.9.7/lib/dm-core/version.rb +3 -0
- data/lib/gems/dm-core-0.9.7/lib/dm-core.rb +217 -0
- data/lib/gems/dm-core-0.9.7/script/all +5 -0
- data/lib/gems/dm-core-0.9.7/script/performance.rb +284 -0
- data/lib/gems/dm-core-0.9.7/script/profile.rb +87 -0
- data/lib/gems/dm-migrations-0.9.7/lib/dm-migrations/version.rb +5 -0
- data/lib/gems/dm-migrations-0.9.7/lib/dm-migrations.rb +1 -0
- data/lib/gems/dm-migrations-0.9.7/lib/migration.rb +215 -0
- data/lib/gems/dm-migrations-0.9.7/lib/migration_runner.rb +88 -0
- data/lib/gems/dm-migrations-0.9.7/lib/spec/example/migration_example_group.rb +73 -0
- data/lib/gems/dm-migrations-0.9.7/lib/spec/matchers/migration_matchers.rb +107 -0
- data/lib/gems/dm-migrations-0.9.7/lib/sql/column.rb +9 -0
- data/lib/gems/dm-migrations-0.9.7/lib/sql/mysql.rb +52 -0
- data/lib/gems/dm-migrations-0.9.7/lib/sql/postgresql.rb +78 -0
- data/lib/gems/dm-migrations-0.9.7/lib/sql/sqlite3.rb +43 -0
- data/lib/gems/dm-migrations-0.9.7/lib/sql/table.rb +19 -0
- data/lib/gems/dm-migrations-0.9.7/lib/sql/table_creator.rb +81 -0
- data/lib/gems/dm-migrations-0.9.7/lib/sql/table_modifier.rb +53 -0
- data/lib/gems/dm-migrations-0.9.7/lib/sql.rb +10 -0
- data/lib/gems/dm-observer-0.9.7/lib/dm-observer/version.rb +5 -0
- data/lib/gems/dm-observer-0.9.7/lib/dm-observer.rb +91 -0
- data/lib/gems/dm-serializer-0.9.7/lib/dm-serializer/version.rb +5 -0
- data/lib/gems/dm-serializer-0.9.7/lib/dm-serializer.rb +183 -0
- data/lib/gems/dm-timestamps-0.9.7/lib/dm-timestamps/version.rb +5 -0
- data/lib/gems/dm-timestamps-0.9.7/lib/dm-timestamps.rb +57 -0
- data/lib/gems/dm-types-0.9.7/lib/dm-types/bcrypt_hash.rb +31 -0
- data/lib/gems/dm-types-0.9.7/lib/dm-types/csv.rb +28 -0
- data/lib/gems/dm-types-0.9.7/lib/dm-types/enum.rb +70 -0
- data/lib/gems/dm-types-0.9.7/lib/dm-types/epoch_time.rb +27 -0
- data/lib/gems/dm-types-0.9.7/lib/dm-types/file_path.rb +27 -0
- data/lib/gems/dm-types-0.9.7/lib/dm-types/flag.rb +61 -0
- data/lib/gems/dm-types-0.9.7/lib/dm-types/ip_address.rb +30 -0
- data/lib/gems/dm-types-0.9.7/lib/dm-types/json.rb +40 -0
- data/lib/gems/dm-types-0.9.7/lib/dm-types/regexp.rb +20 -0
- data/lib/gems/dm-types-0.9.7/lib/dm-types/serial.rb +8 -0
- data/lib/gems/dm-types-0.9.7/lib/dm-types/slug.rb +37 -0
- data/lib/gems/dm-types-0.9.7/lib/dm-types/uri.rb +29 -0
- data/lib/gems/dm-types-0.9.7/lib/dm-types/uuid.rb +64 -0
- data/lib/gems/dm-types-0.9.7/lib/dm-types/version.rb +5 -0
- data/lib/gems/dm-types-0.9.7/lib/dm-types/yaml.rb +36 -0
- data/lib/gems/dm-types-0.9.7/lib/dm-types.rb +28 -0
- data/lib/gems/dm-validations-0.9.7/lib/dm-validations/absent_field_validator.rb +60 -0
- data/lib/gems/dm-validations-0.9.7/lib/dm-validations/acceptance_validator.rb +76 -0
- data/lib/gems/dm-validations-0.9.7/lib/dm-validations/auto_validate.rb +153 -0
- data/lib/gems/dm-validations-0.9.7/lib/dm-validations/block_validator.rb +60 -0
- data/lib/gems/dm-validations-0.9.7/lib/dm-validations/confirmation_validator.rb +80 -0
- data/lib/gems/dm-validations-0.9.7/lib/dm-validations/contextual_validators.rb +56 -0
- data/lib/gems/dm-validations-0.9.7/lib/dm-validations/custom_validator.rb +72 -0
- data/lib/gems/dm-validations-0.9.7/lib/dm-validations/format_validator.rb +97 -0
- data/lib/gems/dm-validations-0.9.7/lib/dm-validations/formats/email.rb +40 -0
- data/lib/gems/dm-validations-0.9.7/lib/dm-validations/formats/url.rb +20 -0
- data/lib/gems/dm-validations-0.9.7/lib/dm-validations/generic_validator.rb +100 -0
- data/lib/gems/dm-validations-0.9.7/lib/dm-validations/length_validator.rb +113 -0
- data/lib/gems/dm-validations-0.9.7/lib/dm-validations/method_validator.rb +68 -0
- data/lib/gems/dm-validations-0.9.7/lib/dm-validations/numeric_validator.rb +83 -0
- data/lib/gems/dm-validations-0.9.7/lib/dm-validations/primitive_validator.rb +60 -0
- data/lib/gems/dm-validations-0.9.7/lib/dm-validations/required_field_validator.rb +88 -0
- data/lib/gems/dm-validations-0.9.7/lib/dm-validations/support/object.rb +5 -0
- data/lib/gems/dm-validations-0.9.7/lib/dm-validations/uniqueness_validator.rb +64 -0
- data/lib/gems/dm-validations-0.9.7/lib/dm-validations/validation_errors.rb +63 -0
- data/lib/gems/dm-validations-0.9.7/lib/dm-validations/version.rb +5 -0
- data/lib/gems/dm-validations-0.9.7/lib/dm-validations/within_validator.rb +53 -0
- data/lib/gems/dm-validations-0.9.7/lib/dm-validations.rb +234 -0
- data/lib/gems/json_pure-1.1.3/GPL +340 -0
- data/lib/gems/json_pure-1.1.3/VERSION +1 -0
- data/lib/gems/json_pure-1.1.3/bin/edit_json.rb +10 -0
- data/lib/gems/json_pure-1.1.3/bin/prettify_json.rb +76 -0
- data/lib/gems/json_pure-1.1.3/lib/json/Array.xpm +21 -0
- data/lib/gems/json_pure-1.1.3/lib/json/FalseClass.xpm +21 -0
- data/lib/gems/json_pure-1.1.3/lib/json/Hash.xpm +21 -0
- data/lib/gems/json_pure-1.1.3/lib/json/Key.xpm +73 -0
- data/lib/gems/json_pure-1.1.3/lib/json/NilClass.xpm +21 -0
- data/lib/gems/json_pure-1.1.3/lib/json/Numeric.xpm +28 -0
- data/lib/gems/json_pure-1.1.3/lib/json/String.xpm +96 -0
- data/lib/gems/json_pure-1.1.3/lib/json/TrueClass.xpm +21 -0
- data/lib/gems/json_pure-1.1.3/lib/json/add/core.rb +135 -0
- data/lib/gems/json_pure-1.1.3/lib/json/add/rails.rb +58 -0
- data/lib/gems/json_pure-1.1.3/lib/json/common.rb +354 -0
- data/lib/gems/json_pure-1.1.3/lib/json/editor.rb +1362 -0
- data/lib/gems/json_pure-1.1.3/lib/json/ext.rb +13 -0
- data/lib/gems/json_pure-1.1.3/lib/json/json.xpm +1499 -0
- data/lib/gems/json_pure-1.1.3/lib/json/pure/generator.rb +394 -0
- data/lib/gems/json_pure-1.1.3/lib/json/pure/parser.rb +259 -0
- data/lib/gems/json_pure-1.1.3/lib/json/pure.rb +75 -0
- data/lib/gems/json_pure-1.1.3/lib/json/version.rb +9 -0
- data/lib/gems/json_pure-1.1.3/lib/json.rb +235 -0
- data/lib/gems/launchy-0.3.2/bin/launchy +12 -0
- data/lib/gems/launchy-0.3.2/lib/launchy/application.rb +163 -0
- data/lib/gems/launchy-0.3.2/lib/launchy/browser.rb +85 -0
- data/lib/gems/launchy-0.3.2/lib/launchy/command_line.rb +48 -0
- data/lib/gems/launchy-0.3.2/lib/launchy/gemspec.rb +53 -0
- data/lib/gems/launchy-0.3.2/lib/launchy/specification.rb +133 -0
- data/lib/gems/launchy-0.3.2/lib/launchy/version.rb +18 -0
- data/lib/gems/launchy-0.3.2/lib/launchy.rb +58 -0
- data/lib/gems/uuidtools-1.0.3/lib/uuidtools/version.rb +32 -0
- data/lib/gems/uuidtools-1.0.3/lib/uuidtools.rb +648 -0
- data/lib/gems.rb +13 -0
- data/lib/mack-data_mapper/migration_generator/migration_generator.rb +5 -0
- data/lib/mack-data_mapper/migration_generator/templates/db/migrations/%=@migration_name%.rb.template +1 -1
- data/lib/mack-data_mapper/model_generator/manifest.yml +3 -3
- data/lib/mack-data_mapper/model_generator/model_generator.rb +8 -1
- data/lib/mack-data_mapper/model_generator/templates/model.rb.template +1 -1
- data/lib/mack-data_mapper/model_generator/templates/rspec.rb.template +1 -1
- data/lib/mack-data_mapper/model_generator/templates/test_case.rb.template +1 -1
- data/lib/mack-data_mapper.rb +3 -2
- data/lib/mack-data_mapper_tasks.rb +7 -0
- metadata +235 -86
|
@@ -0,0 +1,488 @@
|
|
|
1
|
+
require 'set'
|
|
2
|
+
|
|
3
|
+
module DataMapper
|
|
4
|
+
module Model
|
|
5
|
+
##
|
|
6
|
+
#
|
|
7
|
+
# Extends the model with this module after DataMapper::Resource has been
|
|
8
|
+
# included.
|
|
9
|
+
#
|
|
10
|
+
# This is a useful way to extend DataMapper::Model while
|
|
11
|
+
# still retaining a self.extended method.
|
|
12
|
+
#
|
|
13
|
+
# @param [Module] extensions the module that is to be extend the model after
|
|
14
|
+
# after DataMapper::Model
|
|
15
|
+
#
|
|
16
|
+
# @return [TrueClass, FalseClass] whether or not the inclusions have been
|
|
17
|
+
# successfully appended to the list
|
|
18
|
+
#-
|
|
19
|
+
# @api public
|
|
20
|
+
#
|
|
21
|
+
# TODO: Move this do DataMapper::Model when DataMapper::Model is created
|
|
22
|
+
def self.append_extensions(*extensions)
|
|
23
|
+
extra_extensions.concat extensions
|
|
24
|
+
true
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def self.extra_extensions
|
|
28
|
+
@extra_extensions ||= []
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def self.extended(model)
|
|
32
|
+
model.instance_variable_set(:@storage_names, {})
|
|
33
|
+
model.instance_variable_set(:@properties, {})
|
|
34
|
+
model.instance_variable_set(:@field_naming_conventions, {})
|
|
35
|
+
extra_extensions.each { |extension| model.extend(extension) }
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def inherited(target)
|
|
39
|
+
target.instance_variable_set(:@storage_names, @storage_names.dup)
|
|
40
|
+
target.instance_variable_set(:@properties, {})
|
|
41
|
+
target.instance_variable_set(:@base_model, self.base_model)
|
|
42
|
+
target.instance_variable_set(:@paranoid_properties, @paranoid_properties)
|
|
43
|
+
target.instance_variable_set(:@field_naming_conventions, @field_naming_conventions.dup)
|
|
44
|
+
|
|
45
|
+
if self.respond_to?(:validators)
|
|
46
|
+
@validations.contexts.each do |context, validators|
|
|
47
|
+
validators.each { |validator| target.validators.context(context) << validator }
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
@properties.each do |repository_name,properties|
|
|
52
|
+
repository(repository_name) do
|
|
53
|
+
properties.each do |property|
|
|
54
|
+
next if target.properties(repository_name).has_property?(property.name)
|
|
55
|
+
target.property(property.name, property.type, property.options.dup)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
if @relationships
|
|
61
|
+
duped_relationships = {}
|
|
62
|
+
@relationships.each do |repository_name,relationships|
|
|
63
|
+
relationships.each do |name, relationship|
|
|
64
|
+
dup = relationship.dup
|
|
65
|
+
dup.instance_variable_set(:@child_model, target) if dup.instance_variable_get(:@child_model) == self
|
|
66
|
+
dup.instance_variable_set(:@parent_model, target) if dup.instance_variable_get(:@parent_model) == self
|
|
67
|
+
duped_relationships[repository_name] ||= {}
|
|
68
|
+
duped_relationships[repository_name][name] = dup
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
target.instance_variable_set(:@relationships, duped_relationships)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def self.new(storage_name, &block)
|
|
76
|
+
model = Class.new
|
|
77
|
+
model.send(:include, Resource)
|
|
78
|
+
model.class_eval <<-EOS, __FILE__, __LINE__
|
|
79
|
+
def self.default_storage_name
|
|
80
|
+
#{Extlib::Inflection.classify(storage_name).inspect}
|
|
81
|
+
end
|
|
82
|
+
EOS
|
|
83
|
+
model.instance_eval(&block) if block_given?
|
|
84
|
+
model
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def base_model
|
|
88
|
+
@base_model ||= self
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def repository_name
|
|
92
|
+
Repository.context.any? ? Repository.context.last.name : default_repository_name
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
##
|
|
96
|
+
# Get the repository with a given name, or the default one for the current
|
|
97
|
+
# context, or the default one for this class.
|
|
98
|
+
#
|
|
99
|
+
# @param name<Symbol> the name of the repository wanted
|
|
100
|
+
# @param block<Block> block to execute with the fetched repository as parameter
|
|
101
|
+
#
|
|
102
|
+
# @return <Object, DataMapper::Respository> whatever the block returns,
|
|
103
|
+
# if given a block, otherwise the requested repository.
|
|
104
|
+
#-
|
|
105
|
+
# @api public
|
|
106
|
+
def repository(name = nil)
|
|
107
|
+
#
|
|
108
|
+
# There has been a couple of different strategies here, but me (zond) and dkubb are at least
|
|
109
|
+
# united in the concept of explicitness over implicitness. That is - the explicit wish of the
|
|
110
|
+
# caller (+name+) should be given more priority than the implicit wish of the caller (Repository.context.last).
|
|
111
|
+
#
|
|
112
|
+
if block_given?
|
|
113
|
+
DataMapper.repository(name || repository_name) { |*block_args| yield(*block_args) }
|
|
114
|
+
else
|
|
115
|
+
DataMapper.repository(name || repository_name)
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
##
|
|
120
|
+
# the name of the storage recepticle for this resource. IE. table name, for database stores
|
|
121
|
+
#
|
|
122
|
+
# @return <String> the storage name (IE table name, for database stores) associated with this resource in the given repository
|
|
123
|
+
def storage_name(repository_name = default_repository_name)
|
|
124
|
+
@storage_names[repository_name] ||= repository(repository_name).adapter.resource_naming_convention.call(base_model.send(:default_storage_name))
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
##
|
|
128
|
+
# the names of the storage recepticles for this resource across all repositories
|
|
129
|
+
#
|
|
130
|
+
# @return <Hash(Symbol => String)> All available names of storage recepticles
|
|
131
|
+
def storage_names
|
|
132
|
+
@storage_names
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
##
|
|
136
|
+
# The field naming conventions for this resource across all repositories.
|
|
137
|
+
#
|
|
138
|
+
# @return <String> The naming convention for the given repository
|
|
139
|
+
def field_naming_convention(repository_name = default_storage_name)
|
|
140
|
+
@field_naming_conventions[repository_name] ||= repository(repository_name).adapter.field_naming_convention
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
##
|
|
144
|
+
# defines a property on the resource
|
|
145
|
+
#
|
|
146
|
+
# @param <Symbol> name the name for which to call this property
|
|
147
|
+
# @param <Type> type the type to define this property ass
|
|
148
|
+
# @param <Hash(Symbol => String)> options a hash of available options
|
|
149
|
+
# @see DataMapper::Property
|
|
150
|
+
def property(name, type, options = {})
|
|
151
|
+
property = Property.new(self, name, type, options)
|
|
152
|
+
|
|
153
|
+
create_property_getter(property)
|
|
154
|
+
create_property_setter(property)
|
|
155
|
+
|
|
156
|
+
properties(repository_name)[property.name] = property
|
|
157
|
+
@_valid_relations = false
|
|
158
|
+
|
|
159
|
+
# Add property to the other mappings as well if this is for the default
|
|
160
|
+
# repository.
|
|
161
|
+
if repository_name == default_repository_name
|
|
162
|
+
@properties.each_pair do |repository_name, properties|
|
|
163
|
+
next if repository_name == default_repository_name
|
|
164
|
+
properties << property unless properties.has_property?(property.name)
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
# Add the property to the lazy_loads set for this resources repository
|
|
169
|
+
# only.
|
|
170
|
+
# TODO Is this right or should we add the lazy contexts to all
|
|
171
|
+
# repositories?
|
|
172
|
+
if property.lazy?
|
|
173
|
+
context = options.fetch(:lazy, :default)
|
|
174
|
+
context = :default if context == true
|
|
175
|
+
|
|
176
|
+
Array(context).each do |item|
|
|
177
|
+
properties(repository_name).lazy_context(item) << name
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
# add the property to the child classes only if the property was
|
|
182
|
+
# added after the child classes' properties have been copied from
|
|
183
|
+
# the parent
|
|
184
|
+
if respond_to?(:descendants)
|
|
185
|
+
descendants.each do |model|
|
|
186
|
+
next if model.properties(repository_name).has_property?(name)
|
|
187
|
+
model.property(name, type, options)
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
property
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
def repositories
|
|
195
|
+
[ repository ].to_set + @properties.keys.collect { |repository_name| DataMapper.repository(repository_name) }
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
def properties(repository_name = default_repository_name)
|
|
199
|
+
# We need to check whether all relations are already set up.
|
|
200
|
+
# If this isn't the case, we try to reload them here
|
|
201
|
+
if !@_valid_relations && respond_to?(:many_to_one_relationships)
|
|
202
|
+
@_valid_relations = true
|
|
203
|
+
begin
|
|
204
|
+
many_to_one_relationships.each do |r|
|
|
205
|
+
r.child_key
|
|
206
|
+
end
|
|
207
|
+
rescue NameError
|
|
208
|
+
# Apparently not all relations are loaded,
|
|
209
|
+
# so we will try again later on
|
|
210
|
+
@_valid_relations = false
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
@properties[repository_name] ||= repository_name == Repository.default_name ? PropertySet.new : properties(Repository.default_name).dup
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
def eager_properties(repository_name = default_repository_name)
|
|
217
|
+
properties(repository_name).defaults
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
# @api private
|
|
221
|
+
def properties_with_subclasses(repository_name = default_repository_name)
|
|
222
|
+
properties = PropertySet.new
|
|
223
|
+
([ self ].to_set + (respond_to?(:descendants) ? descendants : [])).each do |model|
|
|
224
|
+
model.relationships(repository_name).each_value { |relationship| relationship.child_key }
|
|
225
|
+
model.many_to_one_relationships.each do |relationship| relationship.child_key end
|
|
226
|
+
model.properties(repository_name).each do |property|
|
|
227
|
+
properties << property unless properties.has_property?(property.name)
|
|
228
|
+
end
|
|
229
|
+
end
|
|
230
|
+
properties
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
def key(repository_name = default_repository_name)
|
|
234
|
+
properties(repository_name).key
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
def default_order(repository_name = default_repository_name)
|
|
238
|
+
@default_order ||= {}
|
|
239
|
+
@default_order[repository_name] ||= key(repository_name).map { |property| Query::Direction.new(property) }
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
def get(*key)
|
|
243
|
+
key = typecast_key(key)
|
|
244
|
+
repository.identity_map(self).get(key) || first(to_query(repository, key))
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
def get!(*key)
|
|
248
|
+
get(*key) || raise(ObjectNotFoundError, "Could not find #{self.name} with key #{key.inspect}")
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
def all(query = {})
|
|
252
|
+
query = scoped_query(query)
|
|
253
|
+
query.repository.read_many(query)
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
def first(*args)
|
|
257
|
+
query = args.last.respond_to?(:merge) ? args.pop : {}
|
|
258
|
+
query = scoped_query(query.merge(:limit => args.first || 1))
|
|
259
|
+
|
|
260
|
+
if args.any?
|
|
261
|
+
query.repository.read_many(query)
|
|
262
|
+
else
|
|
263
|
+
query.repository.read_one(query)
|
|
264
|
+
end
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
def [](*key)
|
|
268
|
+
warn("#{name}[] is deprecated. Use #{name}.get! instead.")
|
|
269
|
+
get!(*key)
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
def first_or_create(query, attributes = {})
|
|
273
|
+
first(query) || begin
|
|
274
|
+
resource = allocate
|
|
275
|
+
query = query.dup
|
|
276
|
+
|
|
277
|
+
properties(repository_name).key.each do |property|
|
|
278
|
+
if value = query.delete(property.name)
|
|
279
|
+
resource.send("#{property.name}=", value)
|
|
280
|
+
end
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
resource.attributes = query.merge(attributes)
|
|
284
|
+
resource.save
|
|
285
|
+
resource
|
|
286
|
+
end
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
##
|
|
290
|
+
# Create an instance of Resource with the given attributes
|
|
291
|
+
#
|
|
292
|
+
# @param <Hash(Symbol => Object)> attributes hash of attributes to set
|
|
293
|
+
def create(attributes = {})
|
|
294
|
+
resource = new(attributes)
|
|
295
|
+
resource.save
|
|
296
|
+
resource
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
##
|
|
300
|
+
# This method is deprecated, and will be removed from dm-core.
|
|
301
|
+
#
|
|
302
|
+
def create!(attributes = {})
|
|
303
|
+
warn("Model#create! is deprecated. It is moving to dm-validations, and will be used to create a record without validations")
|
|
304
|
+
resource = create(attributes)
|
|
305
|
+
raise PersistenceError, "Resource not saved: :new_record => #{resource.new_record?}, :dirty_attributes => #{resource.dirty_attributes.inspect}" if resource.new_record?
|
|
306
|
+
resource
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
# TODO SPEC
|
|
310
|
+
def copy(source, destination, query = {})
|
|
311
|
+
repository(destination) do
|
|
312
|
+
repository(source).read_many(scoped_query(query)).each do |resource|
|
|
313
|
+
self.create(resource.attributes)
|
|
314
|
+
end
|
|
315
|
+
end
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
# @api private
|
|
319
|
+
# TODO: spec this
|
|
320
|
+
def load(values, query)
|
|
321
|
+
repository = query.repository
|
|
322
|
+
model = self
|
|
323
|
+
|
|
324
|
+
if inheritance_property_index = query.inheritance_property_index
|
|
325
|
+
model = values.at(inheritance_property_index) || model
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
if key_property_indexes = query.key_property_indexes(repository)
|
|
329
|
+
key_values = values.values_at(*key_property_indexes)
|
|
330
|
+
identity_map = repository.identity_map(model)
|
|
331
|
+
|
|
332
|
+
if resource = identity_map.get(key_values)
|
|
333
|
+
return resource unless query.reload?
|
|
334
|
+
else
|
|
335
|
+
resource = model.allocate
|
|
336
|
+
resource.instance_variable_set(:@repository, repository)
|
|
337
|
+
identity_map.set(key_values, resource)
|
|
338
|
+
end
|
|
339
|
+
else
|
|
340
|
+
resource = model.allocate
|
|
341
|
+
resource.readonly!
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
resource.instance_variable_set(:@new_record, false)
|
|
345
|
+
|
|
346
|
+
query.fields.zip(values) do |property,value|
|
|
347
|
+
value = property.custom? ? property.type.load(value, property) : property.typecast(value)
|
|
348
|
+
property.set!(resource, value)
|
|
349
|
+
|
|
350
|
+
if track = property.track
|
|
351
|
+
case track
|
|
352
|
+
when :hash
|
|
353
|
+
resource.original_values[property.name] = value.dup.hash unless resource.original_values.has_key?(property.name) rescue value.hash
|
|
354
|
+
when :load
|
|
355
|
+
resource.original_values[property.name] = value unless resource.original_values.has_key?(property.name)
|
|
356
|
+
end
|
|
357
|
+
end
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
resource
|
|
361
|
+
end
|
|
362
|
+
|
|
363
|
+
# TODO: spec this
|
|
364
|
+
def to_query(repository, key, query = {})
|
|
365
|
+
conditions = Hash[ *self.key(repository.name).zip(key).flatten ]
|
|
366
|
+
Query.new(repository, self, query.merge(conditions))
|
|
367
|
+
end
|
|
368
|
+
|
|
369
|
+
def typecast_key(key)
|
|
370
|
+
self.key(repository_name).zip(key).map { |k, v| k.typecast(v) }
|
|
371
|
+
end
|
|
372
|
+
|
|
373
|
+
def default_repository_name
|
|
374
|
+
Repository.default_name
|
|
375
|
+
end
|
|
376
|
+
|
|
377
|
+
def paranoid_properties
|
|
378
|
+
@paranoid_properties ||= {}
|
|
379
|
+
@paranoid_properties
|
|
380
|
+
end
|
|
381
|
+
|
|
382
|
+
private
|
|
383
|
+
|
|
384
|
+
def default_storage_name
|
|
385
|
+
self.name
|
|
386
|
+
end
|
|
387
|
+
|
|
388
|
+
def scoped_query(query = self.query)
|
|
389
|
+
assert_kind_of 'query', query, Query, Hash
|
|
390
|
+
|
|
391
|
+
return self.query if query == self.query
|
|
392
|
+
|
|
393
|
+
query = if query.kind_of?(Hash)
|
|
394
|
+
Query.new(query.has_key?(:repository) ? query.delete(:repository) : self.repository, self, query)
|
|
395
|
+
else
|
|
396
|
+
query
|
|
397
|
+
end
|
|
398
|
+
|
|
399
|
+
if self.query
|
|
400
|
+
self.query.merge(query)
|
|
401
|
+
else
|
|
402
|
+
merge_with_default_scope(query)
|
|
403
|
+
end
|
|
404
|
+
end
|
|
405
|
+
|
|
406
|
+
def set_paranoid_property(name, &block)
|
|
407
|
+
self.paranoid_properties[name] = block
|
|
408
|
+
end
|
|
409
|
+
|
|
410
|
+
# defines the getter for the property
|
|
411
|
+
def create_property_getter(property)
|
|
412
|
+
class_eval <<-EOS, __FILE__, __LINE__
|
|
413
|
+
#{property.reader_visibility}
|
|
414
|
+
def #{property.getter}
|
|
415
|
+
attribute_get(#{property.name.inspect})
|
|
416
|
+
end
|
|
417
|
+
EOS
|
|
418
|
+
|
|
419
|
+
if property.primitive == TrueClass && !instance_methods.include?(property.name.to_s)
|
|
420
|
+
class_eval <<-EOS, __FILE__, __LINE__
|
|
421
|
+
#{property.reader_visibility}
|
|
422
|
+
alias #{property.name} #{property.getter}
|
|
423
|
+
EOS
|
|
424
|
+
end
|
|
425
|
+
end
|
|
426
|
+
|
|
427
|
+
# defines the setter for the property
|
|
428
|
+
def create_property_setter(property)
|
|
429
|
+
unless instance_methods.include?("#{property.name}=")
|
|
430
|
+
class_eval <<-EOS, __FILE__, __LINE__
|
|
431
|
+
#{property.writer_visibility}
|
|
432
|
+
def #{property.name}=(value)
|
|
433
|
+
attribute_set(#{property.name.inspect}, value)
|
|
434
|
+
end
|
|
435
|
+
EOS
|
|
436
|
+
end
|
|
437
|
+
end
|
|
438
|
+
|
|
439
|
+
def relationships(*args)
|
|
440
|
+
# DO NOT REMOVE!
|
|
441
|
+
# method_missing depends on these existing. Without this stub,
|
|
442
|
+
# a missing module can cause misleading recursive errors.
|
|
443
|
+
raise NotImplementedError.new
|
|
444
|
+
end
|
|
445
|
+
|
|
446
|
+
def method_missing(method, *args, &block)
|
|
447
|
+
if relationship = self.relationships(repository_name)[method]
|
|
448
|
+
klass = self == relationship.child_model ? relationship.parent_model : relationship.child_model
|
|
449
|
+
return DataMapper::Query::Path.new(repository, [ relationship ], klass)
|
|
450
|
+
end
|
|
451
|
+
|
|
452
|
+
if property = properties(repository_name)[method]
|
|
453
|
+
return property
|
|
454
|
+
end
|
|
455
|
+
|
|
456
|
+
super
|
|
457
|
+
end
|
|
458
|
+
|
|
459
|
+
# TODO: move to dm-more/dm-transactions
|
|
460
|
+
module Transaction
|
|
461
|
+
#
|
|
462
|
+
# Produce a new Transaction for this Resource class
|
|
463
|
+
#
|
|
464
|
+
# @return <DataMapper::Adapters::Transaction
|
|
465
|
+
# a new DataMapper::Adapters::Transaction with all DataMapper::Repositories
|
|
466
|
+
# of the class of this DataMapper::Resource added.
|
|
467
|
+
#-
|
|
468
|
+
# @api public
|
|
469
|
+
#
|
|
470
|
+
# TODO: move to dm-more/dm-transactions
|
|
471
|
+
def transaction
|
|
472
|
+
DataMapper::Transaction.new(self) { |block_args| yield(*block_args) }
|
|
473
|
+
end
|
|
474
|
+
end # module Transaction
|
|
475
|
+
|
|
476
|
+
include Transaction
|
|
477
|
+
|
|
478
|
+
# TODO: move to dm-more/dm-migrations
|
|
479
|
+
module Migration
|
|
480
|
+
# TODO: move to dm-more/dm-migrations
|
|
481
|
+
def storage_exists?(repository_name = default_repository_name)
|
|
482
|
+
repository(repository_name).storage_exists?(storage_name(repository_name))
|
|
483
|
+
end
|
|
484
|
+
end # module Migration
|
|
485
|
+
|
|
486
|
+
include Migration
|
|
487
|
+
end # module Model
|
|
488
|
+
end # module DataMapper
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
module DataMapper
|
|
2
|
+
|
|
3
|
+
# Use these modules to establish naming conventions.
|
|
4
|
+
# The default is UnderscoredAndPluralized.
|
|
5
|
+
# You assign a naming convention like so:
|
|
6
|
+
#
|
|
7
|
+
# repository(:default).adapter.resource_naming_convention = NamingConventions::Resource::Underscored
|
|
8
|
+
#
|
|
9
|
+
# You can also easily assign a custom convention with a Proc:
|
|
10
|
+
#
|
|
11
|
+
# repository(:default).adapter.resource_naming_convention = lambda do |value|
|
|
12
|
+
# 'tbl' + value.camelize(true)
|
|
13
|
+
# end
|
|
14
|
+
#
|
|
15
|
+
# Or by simply defining your own module in NamingConventions that responds to
|
|
16
|
+
# ::call.
|
|
17
|
+
#
|
|
18
|
+
# NOTE: It's important to set the convention before accessing your models
|
|
19
|
+
# since the resource_names are cached after first accessed.
|
|
20
|
+
# DataMapper.setup(name, uri) returns the Adapter for convenience, so you can
|
|
21
|
+
# use code like this:
|
|
22
|
+
#
|
|
23
|
+
# adapter = DataMapper.setup(:default, "mock://localhost/mock")
|
|
24
|
+
# adapter.resource_naming_convention = DataMapper::NamingConventions::Resource::Underscored
|
|
25
|
+
module NamingConventions
|
|
26
|
+
|
|
27
|
+
module Resource
|
|
28
|
+
|
|
29
|
+
module UnderscoredAndPluralized
|
|
30
|
+
def self.call(name)
|
|
31
|
+
Extlib::Inflection.pluralize(Extlib::Inflection.underscore(name)).gsub('/','_')
|
|
32
|
+
end
|
|
33
|
+
end # module UnderscoredAndPluralized
|
|
34
|
+
|
|
35
|
+
module UnderscoredAndPluralizedWithoutModule
|
|
36
|
+
def self.call(name)
|
|
37
|
+
Extlib::Inflection.pluralize(Extlib::Inflection.underscore(Extlib::Inflection.demodulize(name)))
|
|
38
|
+
end
|
|
39
|
+
end # module UnderscoredAndPluralizedWithoutModule
|
|
40
|
+
|
|
41
|
+
module Underscored
|
|
42
|
+
def self.call(name)
|
|
43
|
+
Extlib::Inflection.underscore(name)
|
|
44
|
+
end
|
|
45
|
+
end # module Underscored
|
|
46
|
+
|
|
47
|
+
module Yaml
|
|
48
|
+
def self.call(name)
|
|
49
|
+
Extlib::Inflection.pluralize(Extlib::Inflection.underscore(name)) + ".yaml"
|
|
50
|
+
end
|
|
51
|
+
end # module Yaml
|
|
52
|
+
|
|
53
|
+
end # module Resource
|
|
54
|
+
|
|
55
|
+
module Field
|
|
56
|
+
|
|
57
|
+
module UnderscoredAndPluralized
|
|
58
|
+
def self.call(property)
|
|
59
|
+
Extlib::Inflection.pluralize(Extlib::Inflection.underscore(property.name.to_s)).gsub('/','_')
|
|
60
|
+
end
|
|
61
|
+
end # module UnderscoredAndPluralized
|
|
62
|
+
|
|
63
|
+
module UnderscoredAndPluralizedWithoutModule
|
|
64
|
+
def self.call(property)
|
|
65
|
+
Extlib::Inflection.pluralize(Extlib::Inflection.underscore(Extlib::Inflection.demodulize(property.name.to_s)))
|
|
66
|
+
end
|
|
67
|
+
end # module UnderscoredAndPluralizedWithoutModule
|
|
68
|
+
|
|
69
|
+
module Underscored
|
|
70
|
+
def self.call(property)
|
|
71
|
+
Extlib::Inflection.underscore(property.name.to_s)
|
|
72
|
+
end
|
|
73
|
+
end # module Underscored
|
|
74
|
+
|
|
75
|
+
module Yaml
|
|
76
|
+
def self.call(property)
|
|
77
|
+
Extlib::Inflection.pluralize(Extlib::Inflection.underscore(property.name.to_s)) + ".yaml"
|
|
78
|
+
end
|
|
79
|
+
end # module Yaml
|
|
80
|
+
|
|
81
|
+
end # module Field
|
|
82
|
+
|
|
83
|
+
end # module NamingConventions
|
|
84
|
+
end # module DataMapper
|