datamapper 0.2.5 → 0.3.0
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/CHANGELOG +5 -1
- data/FAQ +96 -0
- data/QUICKLINKS +12 -0
- data/README +57 -155
- data/environment.rb +61 -43
- data/example.rb +30 -12
- data/lib/data_mapper.rb +6 -1
- data/lib/data_mapper/adapters/abstract_adapter.rb +0 -57
- data/lib/data_mapper/adapters/data_object_adapter.rb +203 -97
- data/lib/data_mapper/adapters/mysql_adapter.rb +4 -0
- data/lib/data_mapper/adapters/postgresql_adapter.rb +7 -1
- data/lib/data_mapper/adapters/sql/coersion.rb +3 -2
- data/lib/data_mapper/adapters/sql/commands/load_command.rb +29 -10
- data/lib/data_mapper/adapters/sql/mappings/associations_set.rb +4 -0
- data/lib/data_mapper/adapters/sql/mappings/column.rb +13 -9
- data/lib/data_mapper/adapters/sql/mappings/conditions.rb +172 -0
- data/lib/data_mapper/adapters/sql/mappings/table.rb +43 -17
- data/lib/data_mapper/adapters/sqlite3_adapter.rb +9 -2
- data/lib/data_mapper/associations.rb +75 -3
- data/lib/data_mapper/associations/belongs_to_association.rb +70 -36
- data/lib/data_mapper/associations/has_and_belongs_to_many_association.rb +195 -86
- data/lib/data_mapper/associations/has_many_association.rb +168 -61
- data/lib/data_mapper/associations/has_n_association.rb +23 -3
- data/lib/data_mapper/attributes.rb +73 -0
- data/lib/data_mapper/auto_migrations.rb +2 -6
- data/lib/data_mapper/base.rb +5 -9
- data/lib/data_mapper/database.rb +4 -3
- data/lib/data_mapper/embedded_value.rb +66 -30
- data/lib/data_mapper/identity_map.rb +1 -3
- data/lib/data_mapper/is/tree.rb +121 -0
- data/lib/data_mapper/migration.rb +155 -0
- data/lib/data_mapper/persistence.rb +532 -218
- data/lib/data_mapper/property.rb +306 -0
- data/lib/data_mapper/query.rb +164 -0
- data/lib/data_mapper/support/blank.rb +2 -2
- data/lib/data_mapper/support/connection_pool.rb +5 -6
- data/lib/data_mapper/support/enumerable.rb +3 -3
- data/lib/data_mapper/support/errors.rb +10 -1
- data/lib/data_mapper/support/inflector.rb +174 -238
- data/lib/data_mapper/support/object.rb +54 -0
- data/lib/data_mapper/support/serialization.rb +19 -1
- data/lib/data_mapper/support/string.rb +7 -16
- data/lib/data_mapper/support/symbol.rb +3 -15
- data/lib/data_mapper/support/typed_set.rb +68 -0
- data/lib/data_mapper/types/base.rb +44 -0
- data/lib/data_mapper/types/string.rb +34 -0
- data/lib/data_mapper/validations/number_validator.rb +40 -0
- data/lib/data_mapper/validations/string_validator.rb +20 -0
- data/lib/data_mapper/validations/validator.rb +13 -0
- data/performance.rb +26 -1
- data/profile_data_mapper.rb +1 -1
- data/rakefile.rb +42 -2
- data/spec/acts_as_tree_spec.rb +11 -3
- data/spec/adapters/data_object_adapter_spec.rb +31 -0
- data/spec/associations/belongs_to_association_spec.rb +98 -0
- data/spec/associations/has_and_belongs_to_many_association_spec.rb +377 -0
- data/spec/associations/has_many_association_spec.rb +337 -0
- data/spec/attributes_spec.rb +23 -1
- data/spec/auto_migrations_spec.rb +86 -29
- data/spec/callbacks_spec.rb +107 -0
- data/spec/column_spec.rb +5 -2
- data/spec/count_command_spec.rb +33 -1
- data/spec/database_spec.rb +18 -0
- data/spec/dependency_spec.rb +4 -2
- data/spec/embedded_value_spec.rb +8 -8
- data/spec/fixtures/people.yaml +1 -1
- data/spec/fixtures/projects.yaml +10 -1
- data/spec/fixtures/tasks.yaml +6 -0
- data/spec/fixtures/tasks_tasks.yaml +2 -0
- data/spec/fixtures/tomatoes.yaml +1 -0
- data/spec/is_a_tree_spec.rb +149 -0
- data/spec/load_command_spec.rb +71 -9
- data/spec/magic_columns_spec.rb +17 -2
- data/spec/migration_spec.rb +267 -0
- data/spec/models/animal.rb +1 -1
- data/spec/models/candidate.rb +8 -0
- data/spec/models/career.rb +1 -1
- data/spec/models/chain.rb +8 -0
- data/spec/models/comment.rb +1 -1
- data/spec/models/exhibit.rb +1 -1
- data/spec/models/fence.rb +7 -0
- data/spec/models/fruit.rb +2 -2
- data/spec/models/job.rb +8 -0
- data/spec/models/person.rb +2 -3
- data/spec/models/post.rb +1 -1
- data/spec/models/project.rb +21 -1
- data/spec/models/section.rb +1 -1
- data/spec/models/serializer.rb +1 -1
- data/spec/models/task.rb +9 -0
- data/spec/models/tomato.rb +27 -0
- data/spec/models/user.rb +8 -2
- data/spec/models/zoo.rb +2 -7
- data/spec/paranoia_spec.rb +1 -1
- data/spec/{base_spec.rb → persistence_spec.rb} +207 -18
- data/spec/postgres_spec.rb +48 -6
- data/spec/property_spec.rb +90 -9
- data/spec/query_spec.rb +71 -5
- data/spec/save_command_spec.rb +11 -0
- data/spec/spec_helper.rb +14 -11
- data/spec/support/blank_spec.rb +8 -0
- data/spec/support/inflector_spec.rb +41 -0
- data/spec/support/object_spec.rb +9 -0
- data/spec/{serialization_spec.rb → support/serialization_spec.rb} +1 -1
- data/spec/support/silence_spec.rb +15 -0
- data/spec/{support_spec.rb → support/string_spec.rb} +3 -3
- data/spec/support/struct_spec.rb +12 -0
- data/spec/support/typed_set_spec.rb +66 -0
- data/spec/table_spec.rb +3 -3
- data/spec/types/string.rb +81 -0
- data/spec/validates_uniqueness_of_spec.rb +17 -0
- data/spec/validations/number_validator.rb +59 -0
- data/spec/validations/string_validator.rb +14 -0
- metadata +59 -17
- data/do_performance.rb +0 -153
- data/lib/data_mapper/support/active_record_impersonation.rb +0 -103
- data/lib/data_mapper/support/weak_hash.rb +0 -46
- data/spec/active_record_impersonation_spec.rb +0 -129
- data/spec/associations_spec.rb +0 -232
- data/spec/conditions_spec.rb +0 -49
- data/spec/has_many_association_spec.rb +0 -173
- data/spec/models/animals_exhibit.rb +0 -8
@@ -17,6 +17,9 @@ module DataMapper
|
|
17
17
|
TRUE_ALIASES << "T".freeze << "\004\bT".freeze
|
18
18
|
FALSE_ALIASES << "F".freeze << "\004\bF".freeze
|
19
19
|
|
20
|
+
def empty_insert_sql
|
21
|
+
"() VALUES ()"
|
22
|
+
end
|
20
23
|
|
21
24
|
def create_connection
|
22
25
|
|
@@ -28,6 +31,7 @@ module DataMapper
|
|
28
31
|
builder['password', :password]
|
29
32
|
builder['dbname', :database]
|
30
33
|
builder['socket', :socket]
|
34
|
+
builder['port', :port]
|
31
35
|
|
32
36
|
logger.debug { connection_string.strip }
|
33
37
|
|
@@ -37,6 +37,7 @@ module DataMapper
|
|
37
37
|
builder['password', :password]
|
38
38
|
builder['dbname', :database]
|
39
39
|
builder['socket', :socket]
|
40
|
+
builder['port', :port]
|
40
41
|
conn = DataObject::Postgres::Connection.new(connection_string.strip)
|
41
42
|
conn.logger = self.logger
|
42
43
|
conn.open
|
@@ -239,8 +240,13 @@ module DataMapper
|
|
239
240
|
end
|
240
241
|
end
|
241
242
|
|
243
|
+
# size is still required, as length in postgres behaves slightly differently
|
242
244
|
def size
|
243
|
-
|
245
|
+
case self.type
|
246
|
+
#strings in postgres can be unlimited length
|
247
|
+
when :string then return (@options.has_key?(:length) || @options.has_key?(:size) ? @size : nil)
|
248
|
+
else nil
|
249
|
+
end
|
244
250
|
end
|
245
251
|
end # class Column
|
246
252
|
end # module Mappings
|
@@ -23,11 +23,12 @@ module DataMapper
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def type_cast_boolean(raw_value)
|
26
|
+
return nil if raw_value.nil? || (raw_value.respond_to?(:empty?) && raw_value.empty?)
|
26
27
|
case raw_value
|
27
28
|
when TrueClass, FalseClass then raw_value
|
28
29
|
when *self::class::TRUE_ALIASES then true
|
29
30
|
when *self::class::FALSE_ALIASES then false
|
30
|
-
else "Can't type-cast #{raw_value.inspect} to a boolean"
|
31
|
+
else raise CoersionError.new("Can't type-cast #{raw_value.inspect} to a boolean")
|
31
32
|
end
|
32
33
|
end
|
33
34
|
|
@@ -45,7 +46,7 @@ module DataMapper
|
|
45
46
|
|
46
47
|
def type_cast_class(raw_value)
|
47
48
|
return nil if raw_value.blank?
|
48
|
-
|
49
|
+
Object::recursive_const_get(raw_value)
|
49
50
|
end
|
50
51
|
|
51
52
|
def type_cast_integer(raw_value)
|
@@ -56,10 +56,14 @@ module DataMapper
|
|
56
56
|
# setting both the original_value, and the
|
57
57
|
# instance-variable through method chaining to avoid
|
58
58
|
# lots of extra short-lived local variables.
|
59
|
-
|
60
|
-
column.
|
61
|
-
|
62
|
-
|
59
|
+
begin
|
60
|
+
type_casted_values[column.name] = instance.instance_variable_set(
|
61
|
+
column.instance_variable_name,
|
62
|
+
column.type_cast_value(values[index])
|
63
|
+
)
|
64
|
+
rescue => e
|
65
|
+
raise MaterializationError.new("Failed to materialize column #{column.name.inspect} with value #{values[index].inspect}\n#{e.display}")
|
66
|
+
end
|
63
67
|
end
|
64
68
|
|
65
69
|
instance.original_values = type_casted_values
|
@@ -71,7 +75,11 @@ module DataMapper
|
|
71
75
|
return instance
|
72
76
|
|
73
77
|
rescue => e
|
74
|
-
|
78
|
+
if e.is_a?(MaterializationError)
|
79
|
+
raise e
|
80
|
+
else
|
81
|
+
raise MaterializationError.new("Failed to materialize row: #{values.inspect}\n#{e.display}")
|
82
|
+
end
|
75
83
|
end
|
76
84
|
|
77
85
|
def loaded_set
|
@@ -84,7 +92,7 @@ module DataMapper
|
|
84
92
|
instance = @database_context.identity_map.get(@klass, instance_id)
|
85
93
|
|
86
94
|
if instance.nil? || @reload
|
87
|
-
instance = instance_type.
|
95
|
+
instance = instance_type.allocate() if instance.nil?
|
88
96
|
instance.instance_variable_set(:@__key, instance_id)
|
89
97
|
instance.instance_variable_set(:@new_record, false)
|
90
98
|
@database_context.identity_map.set(instance)
|
@@ -358,7 +366,11 @@ module DataMapper
|
|
358
366
|
else raise "CAN HAS CRASH? #{clause.inspect}"
|
359
367
|
end
|
360
368
|
rescue => e
|
361
|
-
|
369
|
+
if e.is_a?(ConditionsError)
|
370
|
+
raise e
|
371
|
+
else
|
372
|
+
raise ConditionsError.new(clause, value, e)
|
373
|
+
end
|
362
374
|
end
|
363
375
|
|
364
376
|
private
|
@@ -368,10 +380,12 @@ module DataMapper
|
|
368
380
|
qualify_columns = qualify_columns?
|
369
381
|
@columns_for_select = []
|
370
382
|
|
371
|
-
|
383
|
+
i = 0
|
384
|
+
columns.each do |column|
|
372
385
|
class_for_loader = column.table.klass
|
373
386
|
@loaders[class_for_loader].add_column(column, i) if class_for_loader
|
374
387
|
@columns_for_select << column.to_sql(qualify_columns)
|
388
|
+
i += 1
|
375
389
|
end
|
376
390
|
|
377
391
|
@columns_for_select
|
@@ -482,8 +496,13 @@ module DataMapper
|
|
482
496
|
|
483
497
|
case x = conditions_hash.delete(:conditions)
|
484
498
|
when Array then
|
485
|
-
|
486
|
-
|
499
|
+
# DO NOT mutate incoming Array values!!!
|
500
|
+
# Otherwise the mutated version may impact all the
|
501
|
+
# way up to the options passed to the finders,
|
502
|
+
# and have unintended side-effects.
|
503
|
+
array_copy = x.dup
|
504
|
+
clause = array_copy.shift
|
505
|
+
expression_to_sql(clause, array_copy, collection)
|
487
506
|
when Hash then
|
488
507
|
x.each_pair do |key,value|
|
489
508
|
expression_to_sql(key, value, collection)
|
@@ -7,7 +7,7 @@ module DataMapper
|
|
7
7
|
# Ordinal, Length/Size, Nullability are just a few.
|
8
8
|
class Column
|
9
9
|
attr_reader :type, :name, :ordinal, :size, :default, :check
|
10
|
-
attr_writer :lazy, :index
|
10
|
+
attr_writer :lazy, :index, :unique
|
11
11
|
attr_accessor :table, :options
|
12
12
|
|
13
13
|
def initialize(adapter, table, name, type, ordinal, options = {})
|
@@ -15,13 +15,17 @@ module DataMapper
|
|
15
15
|
@table = table
|
16
16
|
@name, self.type, @options = name.to_sym, type, options
|
17
17
|
@ordinal = ordinal
|
18
|
-
|
18
|
+
parse_options!
|
19
|
+
end
|
20
|
+
|
21
|
+
def parse_options!
|
19
22
|
@key = @options[:key] == true || @options[:serial] == true
|
20
23
|
@nullable = @options.has_key?(:nullable) ? @options[:nullable] : !@key
|
21
24
|
@lazy = @options.has_key?(:lazy) ? @options[:lazy] : (@type == :text && !@key)
|
22
25
|
@serial = @options[:serial] == true
|
23
26
|
@default = @options[:default]
|
24
|
-
|
27
|
+
|
28
|
+
@unique = if @options[:index] == :unique then @options.delete(:index); true else false end
|
25
29
|
@index = @options[:index]
|
26
30
|
@check = @options[:check] # only for postgresql
|
27
31
|
|
@@ -36,8 +40,11 @@ module DataMapper
|
|
36
40
|
else nil
|
37
41
|
end
|
38
42
|
end
|
43
|
+
@size = @size.last if @size.is_a?(Range)
|
39
44
|
end
|
40
45
|
|
46
|
+
def defaulted?() instance_variables.include?("@default") end
|
47
|
+
|
41
48
|
def type=(value)
|
42
49
|
self.flush_sql_caches!
|
43
50
|
@type = value
|
@@ -167,7 +174,7 @@ module DataMapper
|
|
167
174
|
def rename!(new_name)
|
168
175
|
old_name = name # Store the old_name
|
169
176
|
|
170
|
-
new_column = @table.add_column(new_name, self.type, self.options)
|
177
|
+
new_column = @table.add_column(new_name, self.type, self.options.merge(:ordinal => self.ordinal))
|
171
178
|
|
172
179
|
# Create the new column
|
173
180
|
new_column.create!
|
@@ -181,11 +188,8 @@ module DataMapper
|
|
181
188
|
command.execute_non_query
|
182
189
|
end
|
183
190
|
|
184
|
-
|
185
|
-
|
186
|
-
# Drop the old column
|
187
|
-
new_column.drop!
|
188
|
-
true
|
191
|
+
self.drop!
|
192
|
+
new_column
|
189
193
|
end
|
190
194
|
|
191
195
|
def to_long_form
|
@@ -0,0 +1,172 @@
|
|
1
|
+
module DataMapper
|
2
|
+
module Adapters
|
3
|
+
module Sql
|
4
|
+
module Mappings
|
5
|
+
|
6
|
+
class Conditions
|
7
|
+
def initialize(table, adapter, qualify_columns=false, options={})
|
8
|
+
@table = table
|
9
|
+
@qualify_columns = qualify_columns
|
10
|
+
|
11
|
+
# BEGIN: Partion out the options hash into general options,
|
12
|
+
# and conditions.
|
13
|
+
standard_find_options = adapter.class::FIND_OPTIONS
|
14
|
+
conditions_hash = {}
|
15
|
+
|
16
|
+
options.each do |key,value|
|
17
|
+
unless standard_find_options.include?(key) && key != :conditions
|
18
|
+
conditions_hash[key] = value
|
19
|
+
end
|
20
|
+
end
|
21
|
+
# END
|
22
|
+
|
23
|
+
@conditions = parse_conditions(conditions_hash)
|
24
|
+
end
|
25
|
+
|
26
|
+
# Generate a statement after 'WHERE' based on the initialization
|
27
|
+
# arguments.
|
28
|
+
def to_params_sql
|
29
|
+
parameters = []
|
30
|
+
sql = ""
|
31
|
+
|
32
|
+
unless @conditions.empty?
|
33
|
+
sql << ' WHERE ('
|
34
|
+
|
35
|
+
last_index = @conditions.size
|
36
|
+
current_index = 0
|
37
|
+
|
38
|
+
@conditions.each do |condition|
|
39
|
+
case condition
|
40
|
+
when String then sql << condition
|
41
|
+
when Array then
|
42
|
+
sql << condition.shift
|
43
|
+
parameters += condition
|
44
|
+
else
|
45
|
+
raise "Unable to parse condition: #{condition.inspect}" if condition
|
46
|
+
end
|
47
|
+
|
48
|
+
if (current_index += 1) == last_index
|
49
|
+
sql << ')'
|
50
|
+
else
|
51
|
+
sql << ') AND ('
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
parameters.unshift(sql)
|
57
|
+
end
|
58
|
+
|
59
|
+
def parse_conditions(conditions_hash)
|
60
|
+
collection = []
|
61
|
+
|
62
|
+
case x = conditions_hash.delete(:conditions)
|
63
|
+
when Array then
|
64
|
+
# DO NOT mutate incoming Array values!!!
|
65
|
+
# Otherwise the mutated version may impact all the
|
66
|
+
# way up to the options passed to the finders,
|
67
|
+
# and have unintended side-effects.
|
68
|
+
array_copy = x.dup
|
69
|
+
clause = array_copy.shift
|
70
|
+
expression_to_sql(clause, array_copy, collection)
|
71
|
+
when Hash then
|
72
|
+
x.each_pair do |key,value|
|
73
|
+
expression_to_sql(key, value, collection)
|
74
|
+
end
|
75
|
+
else
|
76
|
+
raise "Unable to parse conditions: #{x.inspect}" if x
|
77
|
+
end
|
78
|
+
|
79
|
+
if @table.paranoid?
|
80
|
+
conditions_hash[@table.paranoid_column.name] = nil
|
81
|
+
end
|
82
|
+
|
83
|
+
conditions_hash.each_pair do |key,value|
|
84
|
+
expression_to_sql(key, value, collection)
|
85
|
+
end
|
86
|
+
|
87
|
+
collection
|
88
|
+
end
|
89
|
+
|
90
|
+
# expression_to_sql takes a set of arguments, and turns them into a an
|
91
|
+
# Array of generated SQL, followed by optional Values to interpolate as SQL-Parameters.
|
92
|
+
#
|
93
|
+
# Parameters:
|
94
|
+
# +clause+ The name of the column as a Symbol, a raw-SQL String, a Mappings::Column
|
95
|
+
# instance, or a Symbol::Operator.
|
96
|
+
# +value+ The Value for the condition.
|
97
|
+
# +collector+ An Array representing all conditions that is appended to by expression_to_sql
|
98
|
+
#
|
99
|
+
# Returns: Undefined Output. The work performed is added to the +collector+ argument.
|
100
|
+
# Example:
|
101
|
+
# conditions = []
|
102
|
+
# expression_to_sql(:name, 'Bob', conditions)
|
103
|
+
# => +undefined return value+
|
104
|
+
# conditions.inspect
|
105
|
+
# => ["name = ?", 'Bob']
|
106
|
+
def expression_to_sql(clause, value, collector)
|
107
|
+
case clause
|
108
|
+
when Symbol::Operator then
|
109
|
+
operator = case clause.type
|
110
|
+
when :gt then '>'
|
111
|
+
when :gte then '>='
|
112
|
+
when :lt then '<'
|
113
|
+
when :lte then '<='
|
114
|
+
when :not then inequality_operator(value)
|
115
|
+
when :eql then equality_operator(value)
|
116
|
+
when :like then equality_operator(value, 'LIKE')
|
117
|
+
when :in then equality_operator(value)
|
118
|
+
else raise ArgumentError.new('Operator type not supported')
|
119
|
+
end
|
120
|
+
#Table[column name] is column.to_sql(true/false based on associations or not)
|
121
|
+
collector << ["#{@table[clause].to_sql(@qualify_columns)} #{operator} ?", value]
|
122
|
+
when Symbol then
|
123
|
+
collector << ["#{@table[clause].to_sql(@qualify_columns)} #{equality_operator(value)} ?", value]
|
124
|
+
when String then
|
125
|
+
collector << [clause, *value]
|
126
|
+
when Mappings::Column then
|
127
|
+
collector << ["#{clause.to_sql(@qualify_columns)} #{equality_operator(value)} ?", value]
|
128
|
+
else raise "CAN HAS CRASH? #{clause.inspect}"
|
129
|
+
end
|
130
|
+
rescue => e
|
131
|
+
raise ConditionsError.new(clause, value, e)
|
132
|
+
end
|
133
|
+
|
134
|
+
def equality_operator(value, default = '=')
|
135
|
+
case value
|
136
|
+
when NilClass then 'IS'
|
137
|
+
when Array then 'IN'
|
138
|
+
else default
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def inequality_operator(value, default = '<>')
|
143
|
+
case value
|
144
|
+
when NilClass then 'IS NOT'
|
145
|
+
when Array then 'NOT IN'
|
146
|
+
else default
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
class ConditionsError < StandardError
|
151
|
+
|
152
|
+
attr_reader :inner_error
|
153
|
+
|
154
|
+
def initialize(clause, value, inner_error)
|
155
|
+
@clause, @value, @inner_error = clause, value, inner_error
|
156
|
+
end
|
157
|
+
|
158
|
+
def message
|
159
|
+
"Conditions (:clause => #{@clause.inspect}, :value => #{@value.inspect}) failed: #{@inner_error}"
|
160
|
+
end
|
161
|
+
|
162
|
+
def backtrace
|
163
|
+
@inner_error.backtrace
|
164
|
+
end
|
165
|
+
|
166
|
+
end
|
167
|
+
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/column'
|
2
|
+
require File.dirname(__FILE__) + '/conditions'
|
2
3
|
require File.dirname(__FILE__) + '/associations_set'
|
3
4
|
|
4
5
|
module DataMapper
|
@@ -45,6 +46,10 @@ module DataMapper
|
|
45
46
|
@schema || @schema = @adapter.schema
|
46
47
|
end
|
47
48
|
|
49
|
+
def conditions(args)
|
50
|
+
Conditions.new(self, @adapter, @associations.empty?, args)
|
51
|
+
end
|
52
|
+
|
48
53
|
def paranoid?
|
49
54
|
@paranoid
|
50
55
|
end
|
@@ -73,6 +78,12 @@ module DataMapper
|
|
73
78
|
@associations
|
74
79
|
end
|
75
80
|
|
81
|
+
def activate_associations!(force = false)
|
82
|
+
@associations.each do |association|
|
83
|
+
association.activate! force
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
76
87
|
def reflect_columns
|
77
88
|
@adapter.reflect_columns(self)
|
78
89
|
end
|
@@ -85,6 +96,11 @@ module DataMapper
|
|
85
96
|
|
86
97
|
self.columns
|
87
98
|
end
|
99
|
+
|
100
|
+
def mapped_column_exists?(column_name)
|
101
|
+
@columns.each {|column| return true if column.name == column_name}
|
102
|
+
false
|
103
|
+
end
|
88
104
|
|
89
105
|
def exists?
|
90
106
|
@adapter.connection do |db|
|
@@ -136,19 +152,22 @@ module DataMapper
|
|
136
152
|
|
137
153
|
def truncate!
|
138
154
|
@adapter.connection do |db|
|
139
|
-
result = db.create_command(
|
155
|
+
result = db.create_command(to_truncate_sql).execute_non_query
|
140
156
|
database.identity_map.clear!(name)
|
141
157
|
result.to_i > 0
|
142
158
|
end
|
143
159
|
end
|
144
160
|
|
145
|
-
def count(
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
161
|
+
def count(args={})
|
162
|
+
sql = "SELECT COUNT(*) AS row_count FROM #{to_sql}"
|
163
|
+
parameters = []
|
164
|
+
|
165
|
+
paramsql, *parameters = conditions(args).to_params_sql
|
166
|
+
sql << paramsql #gotta shift it in
|
167
|
+
|
168
|
+
@adapter.connection do |db|
|
150
169
|
command = db.create_command(sql)
|
151
|
-
command.execute_reader do |reader|
|
170
|
+
command.execute_reader(*parameters) do |reader|
|
152
171
|
if reader.has_rows?
|
153
172
|
reader.current_row.first.to_i
|
154
173
|
else
|
@@ -175,13 +194,17 @@ module DataMapper
|
|
175
194
|
end
|
176
195
|
end
|
177
196
|
|
178
|
-
def key
|
197
|
+
def key
|
179
198
|
@key || begin
|
180
199
|
@key = @columns.find { |column| column.key? }
|
181
200
|
|
182
201
|
if @key.nil?
|
183
|
-
@
|
184
|
-
|
202
|
+
unless @klass.nil?
|
203
|
+
@klass.send(:property, :id, :integer, :serial => true, :ordinal => -1)
|
204
|
+
@key = self[:id]
|
205
|
+
else
|
206
|
+
@key = add_column(:id, :integer, :serial => true, :ordinal => -1)
|
207
|
+
end
|
185
208
|
end
|
186
209
|
|
187
210
|
@key
|
@@ -269,13 +292,13 @@ module DataMapper
|
|
269
292
|
@custom_name = value
|
270
293
|
self.name
|
271
294
|
end
|
272
|
-
|
295
|
+
|
273
296
|
def default_foreign_key
|
274
|
-
@default_foreign_key
|
297
|
+
@default_foreign_key ||= Inflector.foreign_key(@klass_or_name, key.name).freeze
|
275
298
|
end
|
276
299
|
|
277
300
|
def to_sql
|
278
|
-
@to_sql
|
301
|
+
@to_sql ||= quote_table.freeze
|
279
302
|
end
|
280
303
|
|
281
304
|
def to_s
|
@@ -343,6 +366,10 @@ module DataMapper
|
|
343
366
|
queries
|
344
367
|
end
|
345
368
|
|
369
|
+
def to_truncate_sql
|
370
|
+
"TRUNCATE TABLE #{to_sql}"
|
371
|
+
end
|
372
|
+
|
346
373
|
def to_drop_sql
|
347
374
|
@to_drop_sql || @to_drop_sql = "DROP TABLE #{to_sql}"
|
348
375
|
end
|
@@ -399,6 +426,7 @@ module DataMapper
|
|
399
426
|
@to_drop_sql = nil
|
400
427
|
@to_sql = nil
|
401
428
|
@name = nil
|
429
|
+
@columns_hash.clear
|
402
430
|
|
403
431
|
if flush_columns
|
404
432
|
@columns.each do |column|
|
@@ -411,9 +439,7 @@ module DataMapper
|
|
411
439
|
|
412
440
|
def activate!
|
413
441
|
@activated = true
|
414
|
-
|
415
|
-
association.activate!
|
416
|
-
end
|
442
|
+
activate_associations!
|
417
443
|
end
|
418
444
|
|
419
445
|
def activated?
|
@@ -430,4 +456,4 @@ module DataMapper
|
|
430
456
|
end
|
431
457
|
end
|
432
458
|
end
|
433
|
-
end
|
459
|
+
end
|