datamapper 0.3.2 → 0.9.3
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/History.txt +0 -0
- data/Manifest.txt +5 -0
- data/README.txt +11 -0
- data/Rakefile +70 -0
- data/lib/datamapper.rb +8 -0
- metadata +152 -319
- data/CHANGELOG +0 -145
- data/FAQ +0 -96
- data/MIT-LICENSE +0 -22
- data/QUICKLINKS +0 -12
- data/README +0 -105
- data/environment.rb +0 -62
- data/example.rb +0 -156
- data/lib/data_mapper.rb +0 -88
- data/lib/data_mapper/adapters/abstract_adapter.rb +0 -43
- data/lib/data_mapper/adapters/data_object_adapter.rb +0 -480
- data/lib/data_mapper/adapters/mysql_adapter.rb +0 -72
- data/lib/data_mapper/adapters/postgresql_adapter.rb +0 -258
- data/lib/data_mapper/adapters/sql/coersion.rb +0 -134
- data/lib/data_mapper/adapters/sql/commands/load_command.rb +0 -545
- data/lib/data_mapper/adapters/sql/mappings/associations_set.rb +0 -34
- data/lib/data_mapper/adapters/sql/mappings/column.rb +0 -279
- data/lib/data_mapper/adapters/sql/mappings/conditions.rb +0 -172
- data/lib/data_mapper/adapters/sql/mappings/schema.rb +0 -60
- data/lib/data_mapper/adapters/sql/mappings/table.rb +0 -459
- data/lib/data_mapper/adapters/sql/quoting.rb +0 -24
- data/lib/data_mapper/adapters/sqlite3_adapter.rb +0 -159
- data/lib/data_mapper/associations.rb +0 -106
- data/lib/data_mapper/associations/belongs_to_association.rb +0 -160
- data/lib/data_mapper/associations/has_and_belongs_to_many_association.rb +0 -437
- data/lib/data_mapper/associations/has_many_association.rb +0 -283
- data/lib/data_mapper/associations/has_n_association.rb +0 -143
- data/lib/data_mapper/associations/reference.rb +0 -47
- data/lib/data_mapper/attributes.rb +0 -73
- data/lib/data_mapper/auto_migrations.rb +0 -36
- data/lib/data_mapper/base.rb +0 -17
- data/lib/data_mapper/callbacks.rb +0 -107
- data/lib/data_mapper/context.rb +0 -112
- data/lib/data_mapper/database.rb +0 -234
- data/lib/data_mapper/dependency_queue.rb +0 -28
- data/lib/data_mapper/embedded_value.rb +0 -145
- data/lib/data_mapper/identity_map.rb +0 -47
- data/lib/data_mapper/is/tree.rb +0 -121
- data/lib/data_mapper/migration.rb +0 -155
- data/lib/data_mapper/persistence.rb +0 -852
- data/lib/data_mapper/property.rb +0 -310
- data/lib/data_mapper/query.rb +0 -164
- data/lib/data_mapper/support/blank.rb +0 -35
- data/lib/data_mapper/support/connection_pool.rb +0 -117
- data/lib/data_mapper/support/enumerable.rb +0 -35
- data/lib/data_mapper/support/errors.rb +0 -16
- data/lib/data_mapper/support/inflector.rb +0 -265
- data/lib/data_mapper/support/object.rb +0 -54
- data/lib/data_mapper/support/serialization.rb +0 -96
- data/lib/data_mapper/support/silence.rb +0 -10
- data/lib/data_mapper/support/string.rb +0 -72
- data/lib/data_mapper/support/struct.rb +0 -7
- data/lib/data_mapper/support/symbol.rb +0 -82
- data/lib/data_mapper/support/typed_set.rb +0 -65
- data/lib/data_mapper/types/base.rb +0 -44
- data/lib/data_mapper/types/string.rb +0 -34
- data/lib/data_mapper/validatable_extensions/errors.rb +0 -12
- data/lib/data_mapper/validatable_extensions/macros.rb +0 -7
- data/lib/data_mapper/validatable_extensions/validatable_instance_methods.rb +0 -62
- data/lib/data_mapper/validatable_extensions/validation_base.rb +0 -18
- data/lib/data_mapper/validatable_extensions/validations/formats/email.rb +0 -43
- data/lib/data_mapper/validatable_extensions/validations/validates_acceptance_of.rb +0 -7
- data/lib/data_mapper/validatable_extensions/validations/validates_confirmation_of.rb +0 -7
- data/lib/data_mapper/validatable_extensions/validations/validates_each.rb +0 -7
- data/lib/data_mapper/validatable_extensions/validations/validates_format_of.rb +0 -28
- data/lib/data_mapper/validatable_extensions/validations/validates_length_of.rb +0 -15
- data/lib/data_mapper/validatable_extensions/validations/validates_numericality_of.rb +0 -7
- data/lib/data_mapper/validatable_extensions/validations/validates_presence_of.rb +0 -7
- data/lib/data_mapper/validatable_extensions/validations/validates_true_for.rb +0 -7
- data/lib/data_mapper/validatable_extensions/validations/validates_uniqueness_of.rb +0 -40
- data/lib/data_mapper/validations.rb +0 -20
- data/lib/data_mapper/validations/number_validator.rb +0 -40
- data/lib/data_mapper/validations/string_validator.rb +0 -20
- data/lib/data_mapper/validations/validator.rb +0 -13
- data/performance.rb +0 -307
- data/plugins/can_has_sphinx/LICENSE +0 -23
- data/plugins/can_has_sphinx/README +0 -4
- data/plugins/can_has_sphinx/REVISION +0 -1
- data/plugins/can_has_sphinx/Rakefile +0 -22
- data/plugins/can_has_sphinx/init.rb +0 -1
- data/plugins/can_has_sphinx/install.rb +0 -1
- data/plugins/can_has_sphinx/lib/acts_as_sphinx.rb +0 -123
- data/plugins/can_has_sphinx/lib/sphinx.rb +0 -460
- data/plugins/can_has_sphinx/scripts/sphinx.sh +0 -47
- data/plugins/can_has_sphinx/tasks/acts_as_sphinx_tasks.rake +0 -41
- data/profile_data_mapper.rb +0 -40
- data/rakefile.rb +0 -159
- data/spec/acts_as_tree_spec.rb +0 -67
- data/spec/adapters/data_object_adapter_spec.rb +0 -31
- data/spec/associations/belongs_to_association_spec.rb +0 -98
- data/spec/associations/has_and_belongs_to_many_association_spec.rb +0 -377
- data/spec/associations/has_many_association_spec.rb +0 -337
- data/spec/attributes_spec.rb +0 -52
- data/spec/auto_migrations_spec.rb +0 -101
- data/spec/callbacks_spec.rb +0 -186
- data/spec/can_has_sphinx.rb +0 -5
- data/spec/coersion_spec.rb +0 -41
- data/spec/column_spec.rb +0 -114
- data/spec/count_command_spec.rb +0 -45
- data/spec/database_spec.rb +0 -18
- data/spec/dataobjects_spec.rb +0 -27
- data/spec/delete_command_spec.rb +0 -11
- data/spec/dependency_spec.rb +0 -29
- data/spec/embedded_value_spec.rb +0 -161
- data/spec/fixtures/animals.yaml +0 -33
- data/spec/fixtures/animals_exhibits.yaml +0 -2
- data/spec/fixtures/careers.yaml +0 -5
- data/spec/fixtures/comments.yaml +0 -1
- data/spec/fixtures/exhibits.yaml +0 -90
- data/spec/fixtures/fruit.yaml +0 -6
- data/spec/fixtures/people.yaml +0 -37
- data/spec/fixtures/posts.yaml +0 -3
- data/spec/fixtures/projects.yaml +0 -13
- data/spec/fixtures/sections.yaml +0 -5
- data/spec/fixtures/serializers.yaml +0 -6
- data/spec/fixtures/tasks.yaml +0 -6
- data/spec/fixtures/tasks_tasks.yaml +0 -2
- data/spec/fixtures/tomatoes.yaml +0 -1
- data/spec/fixtures/users.yaml +0 -1
- data/spec/fixtures/zoos.yaml +0 -24
- data/spec/is_a_tree_spec.rb +0 -149
- data/spec/legacy_spec.rb +0 -16
- data/spec/load_command_spec.rb +0 -322
- data/spec/magic_columns_spec.rb +0 -26
- data/spec/migration_spec.rb +0 -267
- data/spec/mock_adapter.rb +0 -20
- data/spec/models/animal.rb +0 -12
- data/spec/models/candidate.rb +0 -8
- data/spec/models/career.rb +0 -7
- data/spec/models/chain.rb +0 -8
- data/spec/models/comment.rb +0 -6
- data/spec/models/exhibit.rb +0 -14
- data/spec/models/fence.rb +0 -7
- data/spec/models/fruit.rb +0 -8
- data/spec/models/job.rb +0 -8
- data/spec/models/person.rb +0 -30
- data/spec/models/post.rb +0 -14
- data/spec/models/project.rb +0 -41
- data/spec/models/sales_person.rb +0 -5
- data/spec/models/section.rb +0 -8
- data/spec/models/serializer.rb +0 -5
- data/spec/models/task.rb +0 -9
- data/spec/models/tomato.rb +0 -27
- data/spec/models/user.rb +0 -12
- data/spec/models/zoo.rb +0 -13
- data/spec/natural_key_spec.rb +0 -36
- data/spec/paranoia_spec.rb +0 -38
- data/spec/persistence_spec.rb +0 -479
- data/spec/postgres_spec.rb +0 -96
- data/spec/property_spec.rb +0 -151
- data/spec/query_spec.rb +0 -77
- data/spec/save_command_spec.rb +0 -94
- data/spec/schema_spec.rb +0 -8
- data/spec/serialize_spec.rb +0 -19
- data/spec/single_table_inheritance_spec.rb +0 -43
- data/spec/spec_helper.rb +0 -45
- data/spec/support/blank_spec.rb +0 -8
- data/spec/support/inflector_spec.rb +0 -41
- data/spec/support/object_spec.rb +0 -9
- data/spec/support/serialization_spec.rb +0 -61
- data/spec/support/silence_spec.rb +0 -15
- data/spec/support/string_spec.rb +0 -7
- data/spec/support/struct_spec.rb +0 -12
- data/spec/support/typed_set_spec.rb +0 -66
- data/spec/symbolic_operators_spec.rb +0 -27
- data/spec/table_spec.rb +0 -79
- data/spec/types/string.rb +0 -81
- data/spec/validates_confirmation_of_spec.rb +0 -55
- data/spec/validates_format_of_spec.rb +0 -78
- data/spec/validates_length_of_spec.rb +0 -117
- data/spec/validates_uniqueness_of_spec.rb +0 -92
- data/spec/validations/number_validator.rb +0 -59
- data/spec/validations/string_validator.rb +0 -14
- data/spec/validations_spec.rb +0 -141
- data/tasks/fixtures.rb +0 -53
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
module DataMapper
|
|
2
|
-
module Adapters
|
|
3
|
-
module Sql
|
|
4
|
-
|
|
5
|
-
# Quoting is a mixin that extends your DataMapper::Database singleton-class
|
|
6
|
-
# to allow for object-name and value quoting to be exposed to the queries.
|
|
7
|
-
#
|
|
8
|
-
# DESIGN: Is there any need for this outside of the query objects? Should
|
|
9
|
-
# we just include it in our query object subclasses and not rely on a Quoting
|
|
10
|
-
# mixin being part of the "standard" Adapter interface?
|
|
11
|
-
module Quoting
|
|
12
|
-
|
|
13
|
-
def quote_table_name(name)
|
|
14
|
-
name.ensure_wrapped_with(self.class::TABLE_QUOTING_CHARACTER)
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
def quote_column_name(name)
|
|
18
|
-
name.ensure_wrapped_with(self.class::COLUMN_QUOTING_CHARACTER)
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
end # module Quoting
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
end
|
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
require 'data_mapper/adapters/data_object_adapter'
|
|
2
|
-
begin
|
|
3
|
-
gem 'do_sqlite3', '<= 0.2.5'
|
|
4
|
-
require 'do_sqlite3'
|
|
5
|
-
rescue LoadError
|
|
6
|
-
STDERR.puts <<-EOS
|
|
7
|
-
You must install the DataObjects::SQLite3 driver.
|
|
8
|
-
gem install do_sqlite3
|
|
9
|
-
EOS
|
|
10
|
-
exit
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
module DataMapper
|
|
14
|
-
module Adapters
|
|
15
|
-
|
|
16
|
-
class Sqlite3Adapter < DataObjectAdapter
|
|
17
|
-
|
|
18
|
-
TYPES.merge!({
|
|
19
|
-
:integer => 'INTEGER'.freeze,
|
|
20
|
-
:string => 'TEXT'.freeze,
|
|
21
|
-
:text => 'TEXT'.freeze,
|
|
22
|
-
:class => 'TEXT'.freeze,
|
|
23
|
-
:boolean => 'INTEGER'.freeze
|
|
24
|
-
})
|
|
25
|
-
|
|
26
|
-
TABLE_QUOTING_CHARACTER = '"'.freeze
|
|
27
|
-
COLUMN_QUOTING_CHARACTER = '"'.freeze
|
|
28
|
-
TRUE_ALIASES << 't'.freeze
|
|
29
|
-
FALSE_ALIASES << 'f'.freeze
|
|
30
|
-
|
|
31
|
-
def create_connection
|
|
32
|
-
conn = DataObject::Sqlite3::Connection.new("dbname=#{@configuration.database}")
|
|
33
|
-
conn.logger = self.logger
|
|
34
|
-
conn.open if conn.respond_to?(:open)
|
|
35
|
-
return conn
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
def batch_insertable?
|
|
39
|
-
false
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
module Mappings
|
|
43
|
-
|
|
44
|
-
class Schema
|
|
45
|
-
def to_tables_sql
|
|
46
|
-
@to_tables_sql || @to_tables_sql = <<-EOS.compress_lines
|
|
47
|
-
SELECT "name"
|
|
48
|
-
FROM sqlite_master
|
|
49
|
-
where "type"= "table"
|
|
50
|
-
and "name" <> "sqlite_sequence"
|
|
51
|
-
EOS
|
|
52
|
-
end
|
|
53
|
-
alias_method :database_tables, :get_database_tables
|
|
54
|
-
end # class Schema
|
|
55
|
-
|
|
56
|
-
class Table
|
|
57
|
-
def to_exists_sql
|
|
58
|
-
@to_exists_sql || @to_exists_sql = <<-EOS.compress_lines
|
|
59
|
-
SELECT "name"
|
|
60
|
-
FROM "#{temporary? ? 'sqlite_temp_master' : 'sqlite_master'}"
|
|
61
|
-
WHERE "type" = "table"
|
|
62
|
-
AND "name" = ?
|
|
63
|
-
EOS
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
def to_column_exists_sql
|
|
67
|
-
@to_column_exists_sql || @to_column_exists_sql = <<-EOS.compress_lines
|
|
68
|
-
PRAGMA TABLE_INFO(?)
|
|
69
|
-
EOS
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
def to_truncate_sql
|
|
73
|
-
"DELETE FROM #{to_sql}"
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
alias_method :to_columns_sql, :to_column_exists_sql
|
|
77
|
-
|
|
78
|
-
def unquote_default(default)
|
|
79
|
-
default.gsub(/(^'|'$)/, "") rescue default
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
end # class Table
|
|
83
|
-
|
|
84
|
-
class Column
|
|
85
|
-
def serial_declaration
|
|
86
|
-
"AUTOINCREMENT"
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
def size
|
|
90
|
-
nil
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
def alter!
|
|
94
|
-
@adapter.connection do |db|
|
|
95
|
-
flush_sql_caches!
|
|
96
|
-
backup_table = @adapter.table("#{@table.name}_backup")
|
|
97
|
-
|
|
98
|
-
@table.columns.each do |column|
|
|
99
|
-
backup_table.add_column(column.name, column.type, column.options)
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
backup_table.temporary = true
|
|
103
|
-
|
|
104
|
-
backup_table.create!
|
|
105
|
-
|
|
106
|
-
sql = <<-EOS.compress_lines
|
|
107
|
-
INSERT INTO #{backup_table.to_sql} SELECT #{@table.columns.map { |c| c.to_sql }.join(', ')} FROM #{@table.to_sql};
|
|
108
|
-
DROP TABLE #{@table.to_sql};
|
|
109
|
-
#{@table.to_create_sql};
|
|
110
|
-
INSERT INTO #{@table.to_sql} SELECT #{backup_table.columns.map { |c| c.to_sql }.join(', ')} FROM #{backup_table.to_sql};
|
|
111
|
-
EOS
|
|
112
|
-
|
|
113
|
-
sql.split(';').each do |part|
|
|
114
|
-
db.create_command(part).execute_non_query
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
backup_table.drop!
|
|
118
|
-
flush_sql_caches!
|
|
119
|
-
end
|
|
120
|
-
end
|
|
121
|
-
|
|
122
|
-
def drop!
|
|
123
|
-
@adapter.connection do |db|
|
|
124
|
-
@table.columns.delete(self)
|
|
125
|
-
flush_sql_caches!
|
|
126
|
-
|
|
127
|
-
backup_table = @adapter.table("#{@table.name}_backup")
|
|
128
|
-
|
|
129
|
-
@table.columns.each do |column|
|
|
130
|
-
backup_table.add_column(column.name, column.type, column.options)
|
|
131
|
-
end
|
|
132
|
-
|
|
133
|
-
backup_table.temporary = true
|
|
134
|
-
|
|
135
|
-
backup_table.create!
|
|
136
|
-
|
|
137
|
-
sql = <<-EOS.compress_lines
|
|
138
|
-
INSERT INTO #{backup_table.to_sql} SELECT #{@table.columns.map { |c| c.to_sql }.join(', ')} FROM #{@table.to_sql};
|
|
139
|
-
DROP TABLE #{@table.to_sql};
|
|
140
|
-
#{@table.to_create_sql};
|
|
141
|
-
INSERT INTO #{@table.to_sql} SELECT #{backup_table.columns.map { |c| c.to_sql }.join(', ')} FROM #{backup_table.to_sql};
|
|
142
|
-
EOS
|
|
143
|
-
|
|
144
|
-
sql.split(';').each do |part|
|
|
145
|
-
db.create_command(part).execute_non_query
|
|
146
|
-
end
|
|
147
|
-
|
|
148
|
-
backup_table.drop!
|
|
149
|
-
flush_sql_caches!
|
|
150
|
-
end
|
|
151
|
-
end
|
|
152
|
-
|
|
153
|
-
end # class Column
|
|
154
|
-
end # module Mappings
|
|
155
|
-
|
|
156
|
-
end # class Sqlite3Adapter
|
|
157
|
-
|
|
158
|
-
end # module Adapters
|
|
159
|
-
end # module DataMapper
|
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
require 'data_mapper/associations/reference'
|
|
2
|
-
require 'data_mapper/associations/has_many_association'
|
|
3
|
-
require 'data_mapper/associations/belongs_to_association'
|
|
4
|
-
require 'data_mapper/associations/has_and_belongs_to_many_association'
|
|
5
|
-
|
|
6
|
-
module DataMapper
|
|
7
|
-
module Associations
|
|
8
|
-
|
|
9
|
-
# Extends +base+ with methods for setting up associations between different models.
|
|
10
|
-
def self.included(base)
|
|
11
|
-
base.extend(ClassMethods)
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
module ClassMethods
|
|
15
|
-
# Adds the following methods for query of a single associated object:
|
|
16
|
-
# * <tt>collection(</tt> - returns a set containing the associated objects. Returns
|
|
17
|
-
# an empty set if no objects are found.
|
|
18
|
-
# * <tt>collection << object</tt> - adds an object to the collection.
|
|
19
|
-
# * <tt>collection = [objects]</tt> - replaces the collections content by deleting and
|
|
20
|
-
# adding objects as appropriate.
|
|
21
|
-
# * <tt>collection.empty?</tt> - returns +true+ if there is no associated objects.
|
|
22
|
-
# * <tt>collection.size</tt> - returns the number of associated objects.
|
|
23
|
-
#
|
|
24
|
-
# Options are:
|
|
25
|
-
# * <tt>:class</tt> - specify the class name of the association. So has_many :animals will by
|
|
26
|
-
# default be linked to the Animal class, but if you want the association to use a
|
|
27
|
-
# different class, you'll have to specify it with this option. DM also lets you specify
|
|
28
|
-
# this with <tt>:class_name</tt>, for AR compability.
|
|
29
|
-
# * <tt>:foreign_key</tt> - specify the foreign key used for the association. By default
|
|
30
|
-
# this is guessed to be the name of this class in lower-case and _id suffixed.
|
|
31
|
-
# * <tt>:dependent</tt> - if set to :destroy, the associated objects have their destroy! methods
|
|
32
|
-
# called in a chain meaning all callbacks are also called for each object.
|
|
33
|
-
# if set to :delete, the associated objects are deleted from the database
|
|
34
|
-
# without their callbacks being triggered.
|
|
35
|
-
# if set to :protect and the collection is not empty an AssociatedProtectedError will be raised.
|
|
36
|
-
# if set to :nullify, the associated objects foreign key is set to NULL.
|
|
37
|
-
# default is :nullify
|
|
38
|
-
#
|
|
39
|
-
# Option examples:
|
|
40
|
-
# has_many :favourite_fruits, :class => 'Fruit', :dependent => :destroy
|
|
41
|
-
def has_many(association_name, options = {})
|
|
42
|
-
database.schema[self].associations << HasManyAssociation.new(self, association_name, options)
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
# Adds the following methods for query of a single associated object:
|
|
46
|
-
# * <tt>association(</tt> - returns the associated object. Returns an empty set if no
|
|
47
|
-
# object is found.
|
|
48
|
-
# * <tt>association=(associate)</tt> - assigns the associate object, extracts the
|
|
49
|
-
# primary key, and sets it as the foreign key.
|
|
50
|
-
# * <tt>association.nil?</tt> - returns +true+ if there is no associated object.
|
|
51
|
-
#
|
|
52
|
-
# The declaration can also include an options hash to specialize the behavior of the
|
|
53
|
-
# association.
|
|
54
|
-
#
|
|
55
|
-
# Options are:
|
|
56
|
-
# * <tt>:class</tt> - specify the class name of the association. So has_one :animal will by
|
|
57
|
-
# default be linked to the Animal class, but if you want the association to use a
|
|
58
|
-
# different class, you'll have to specify it with this option. DM also lets you specify
|
|
59
|
-
# this with <tt>:class_name</tt>, for AR compability.
|
|
60
|
-
# * <tt>:foreign_key</tt> - specify the foreign key used for the association. By default
|
|
61
|
-
# this is guessed to be the name of this class in lower-case and _id suffixed.
|
|
62
|
-
# * <tt>:dependent</tt> - has_one is secretly a has_many so this option performs the same
|
|
63
|
-
# as the has_many
|
|
64
|
-
#
|
|
65
|
-
# Option examples:
|
|
66
|
-
# has_one :favourite_fruit, :class => 'Fruit', :foreign_key => 'devourer_id'
|
|
67
|
-
def has_one(association_name, options = {})
|
|
68
|
-
database.schema[self].associations << HasManyAssociation.new(self, association_name, options)
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
# Adds the following methods for query of a single associated object:
|
|
72
|
-
# * <tt>association(</tt> - returns the associated object. Returns an empty set if no
|
|
73
|
-
# object is found.
|
|
74
|
-
# * <tt>association=(associate)</tt> - assigns the associate object, extracts the
|
|
75
|
-
# primary key, and sets it as the foreign key.
|
|
76
|
-
# * <tt>association.nil?</tt> - returns +true+ if there is no associated object.
|
|
77
|
-
# * <tt>build_association</tt> - builds a new object of the associated type, without
|
|
78
|
-
# saving it to the database.
|
|
79
|
-
# * <tt>create_association</tt> - creates and saves a new object of the associated type.
|
|
80
|
-
def belongs_to(association_name, options = {})
|
|
81
|
-
database.schema[self].associations << BelongsToAssociation.new(self, association_name, options)
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
# Associates two classes via an intermediate join table.
|
|
85
|
-
#
|
|
86
|
-
# Options are:
|
|
87
|
-
# * <tt>:dependent</tt> - if set to :destroy, the associated objects have their destroy! methods
|
|
88
|
-
# called in a chain meaning all callbacks are also called for each object. Beware that this
|
|
89
|
-
# is a cascading delete and will affect all records that have a remote relationship with the
|
|
90
|
-
# record being destroyed!
|
|
91
|
-
# if set to :delete, the associated objects are deleted from the database without their
|
|
92
|
-
# callbacks being triggered. This does NOT cascade the deletes. All associated objects will
|
|
93
|
-
# have their relationships removed from other records before being deleted. The record calling
|
|
94
|
-
# destroy will only delete those records directly associated to it.
|
|
95
|
-
# if set to :protect and the collection is not empty an AssociatedProtectedError will be raised.
|
|
96
|
-
# if set to :nullify, the join table will have the relationship records removed which is
|
|
97
|
-
# effectively nullifying the foreign key.
|
|
98
|
-
# default is :nullify
|
|
99
|
-
def has_and_belongs_to_many(association_name, options = {})
|
|
100
|
-
database.schema[self].associations << HasAndBelongsToManyAssociation.new(self, association_name, options)
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
end
|
|
106
|
-
end
|
|
@@ -1,160 +0,0 @@
|
|
|
1
|
-
require 'data_mapper/associations/has_n_association'
|
|
2
|
-
|
|
3
|
-
module DataMapper
|
|
4
|
-
module Associations
|
|
5
|
-
|
|
6
|
-
class BelongsToAssociation < HasNAssociation
|
|
7
|
-
|
|
8
|
-
def define_accessor(klass)
|
|
9
|
-
klass.class_eval <<-EOS
|
|
10
|
-
|
|
11
|
-
def create_#{@association_name}(options = {})
|
|
12
|
-
#{@association_name}_association.create(options)
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def build_#{@association_name}(options = {})
|
|
16
|
-
#{@association_name}_association.build(options)
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def #{@association_name}
|
|
20
|
-
#{@association_name}_association.instance
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def #{@association_name}=(value)
|
|
24
|
-
#{@association_name}_association.set(value)
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
private
|
|
28
|
-
def #{@association_name}_association
|
|
29
|
-
@#{@association_name} || (@#{@association_name} = DataMapper::Associations::BelongsToAssociation::Instance.new(self, #{@association_name.inspect}))
|
|
30
|
-
end
|
|
31
|
-
EOS
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
# Reverse the natural order for BelongsToAssociations
|
|
35
|
-
alias constant associated_constant
|
|
36
|
-
def associated_constant
|
|
37
|
-
@constant
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
def foreign_key_name
|
|
41
|
-
@foreign_key_name || @foreign_key_name = (@options[:foreign_key] || "#{name}_#{key_table.key.name}".to_sym)
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
def complementary_association
|
|
45
|
-
@complementary_association || begin
|
|
46
|
-
@complementary_association = key_table.associations.find do |mapping|
|
|
47
|
-
mapping.is_a?(HasManyAssociation) &&
|
|
48
|
-
mapping.foreign_key_column.name == foreign_key_column.name &&
|
|
49
|
-
mapping.associated_table.name == associated_table.name
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
if @complementary_association
|
|
53
|
-
class << self
|
|
54
|
-
attr_accessor :complementary_association
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
return @complementary_association
|
|
59
|
-
end
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
def to_sql # :nodoc:
|
|
63
|
-
"JOIN #{key_table.to_sql} ON #{foreign_key_column.to_sql(true)} = #{primary_key_column.to_sql(true)}"
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
class Instance < Associations::Reference
|
|
67
|
-
|
|
68
|
-
def dirty?(cleared = ::Set.new)
|
|
69
|
-
@associated && (@new_member || @key_not_set)
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
def validate_recursively(event, cleared)
|
|
73
|
-
@associated.nil? || cleared.include?(@associated) || @associated.validate_recursively(event, cleared)
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
def save_without_validation(database_context, cleared)
|
|
77
|
-
@new_member = false
|
|
78
|
-
unless @associated.nil?
|
|
79
|
-
@instance.instance_variable_set(
|
|
80
|
-
association.foreign_key_column.instance_variable_name,
|
|
81
|
-
@associated.key
|
|
82
|
-
)
|
|
83
|
-
@instance.database_context.adapter.save_without_validation(database_context, @instance, cleared)
|
|
84
|
-
end
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
def reload!
|
|
88
|
-
@new_member = false
|
|
89
|
-
@associated = nil
|
|
90
|
-
instance
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
def instance
|
|
94
|
-
@associated || @associated = begin
|
|
95
|
-
if @instance.loaded_set.nil?
|
|
96
|
-
nil
|
|
97
|
-
else
|
|
98
|
-
|
|
99
|
-
# Temp variable for the instance variable name.
|
|
100
|
-
fk = association.foreign_key_column.to_sym
|
|
101
|
-
|
|
102
|
-
set = @instance.loaded_set.group_by { |instance| instance.send(fk) }
|
|
103
|
-
|
|
104
|
-
@instance.database_context.all(association.constant, association.associated_table.key.to_sym => set.keys).each do |assoc|
|
|
105
|
-
set[assoc.key].each do |primary_instance|
|
|
106
|
-
primary_instance.send("#{@association_name}_association").shallow_append(assoc)
|
|
107
|
-
end
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
@associated
|
|
111
|
-
end
|
|
112
|
-
end
|
|
113
|
-
end
|
|
114
|
-
|
|
115
|
-
def create(options)
|
|
116
|
-
@associated = association.associated_constant.create(options)
|
|
117
|
-
end
|
|
118
|
-
|
|
119
|
-
def build(options)
|
|
120
|
-
@associated = association.associated_constant.new(options)
|
|
121
|
-
end
|
|
122
|
-
|
|
123
|
-
def setter_method
|
|
124
|
-
"#{@association_name}=".to_sym
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
def set(member)
|
|
128
|
-
shallow_append(member)
|
|
129
|
-
|
|
130
|
-
if complement = association.complementary_association
|
|
131
|
-
member.send(complement.name).shallow_append(@instance)
|
|
132
|
-
end
|
|
133
|
-
|
|
134
|
-
return self
|
|
135
|
-
end
|
|
136
|
-
|
|
137
|
-
def shallow_append(val)
|
|
138
|
-
raise RecursionError.new if val == @instance
|
|
139
|
-
@instance.instance_variable_set(association.foreign_key_column.instance_variable_name, val.key)
|
|
140
|
-
@associated = val
|
|
141
|
-
@key_not_set = true if val.key.nil?
|
|
142
|
-
return self
|
|
143
|
-
end
|
|
144
|
-
|
|
145
|
-
def deactivate
|
|
146
|
-
end
|
|
147
|
-
|
|
148
|
-
private
|
|
149
|
-
|
|
150
|
-
def ensure_foreign_key!
|
|
151
|
-
if @associated
|
|
152
|
-
@instance.instance_variable_set(association.foreign_key.instance_variable_name, @associated.key)
|
|
153
|
-
end
|
|
154
|
-
end
|
|
155
|
-
|
|
156
|
-
end # class Instance
|
|
157
|
-
end
|
|
158
|
-
|
|
159
|
-
end
|
|
160
|
-
end
|