activerecord 3.2.0.rc1 → 3.2.0.rc2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- data/lib/active_record/associations/association.rb +1 -6
- data/lib/active_record/attribute_methods.rb +32 -42
- data/lib/active_record/attribute_methods/read.rb +23 -23
- data/lib/active_record/attribute_methods/serialization.rb +12 -8
- data/lib/active_record/base.rb +3 -6
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +2 -9
- data/lib/active_record/counter_cache.rb +1 -1
- data/lib/active_record/identity_map.rb +3 -4
- data/lib/active_record/locking/optimistic.rb +12 -15
- data/lib/active_record/migration/command_recorder.rb +1 -1
- data/lib/active_record/persistence.rb +0 -8
- data/lib/active_record/railties/databases.rake +1 -0
- data/lib/active_record/relation.rb +1 -1
- data/lib/active_record/relation/calculations.rb +4 -4
- data/lib/active_record/relation/finder_methods.rb +1 -1
- data/lib/active_record/relation/query_methods.rb +6 -5
- data/lib/active_record/relation/spawn_methods.rb +11 -2
- data/lib/active_record/scoping/default.rb +8 -6
- data/lib/active_record/scoping/named.rb +3 -3
- data/lib/active_record/session_store.rb +4 -4
- data/lib/active_record/version.rb +1 -1
- data/lib/rails/generators/active_record/migration/migration_generator.rb +1 -1
- data/lib/rails/generators/active_record/migration/templates/migration.rb +9 -3
- data/lib/rails/generators/active_record/model/model_generator.rb +5 -1
- data/lib/rails/generators/active_record/model/templates/migration.rb +3 -5
- metadata +96 -51
@@ -230,13 +230,8 @@ module ActiveRecord
|
|
230
230
|
end
|
231
231
|
|
232
232
|
def build_record(attributes, options)
|
233
|
-
attributes = (attributes || {}).reverse_merge(creation_attributes)
|
234
|
-
|
235
233
|
reflection.build_association(attributes, options) do |record|
|
236
|
-
record.assign_attributes(
|
237
|
-
create_scope.except(*record.changed),
|
238
|
-
:without_protection => true
|
239
|
-
)
|
234
|
+
record.assign_attributes(create_scope.except(*record.changed), :without_protection => true)
|
240
235
|
end
|
241
236
|
end
|
242
237
|
end
|
@@ -35,48 +35,26 @@ module ActiveRecord
|
|
35
35
|
# accessors, mutators and query methods.
|
36
36
|
def define_attribute_methods
|
37
37
|
return if attribute_methods_generated?
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
@attribute_methods_generated = true
|
42
|
-
else
|
43
|
-
base_class.define_attribute_methods
|
44
|
-
end
|
38
|
+
superclass.define_attribute_methods unless self == base_class
|
39
|
+
super(column_names)
|
40
|
+
@attribute_methods_generated = true
|
45
41
|
end
|
46
42
|
|
47
43
|
def attribute_methods_generated?
|
48
|
-
|
49
|
-
@attribute_methods_generated ||= false
|
50
|
-
else
|
51
|
-
base_class.attribute_methods_generated?
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
def generated_attribute_methods
|
56
|
-
@generated_attribute_methods ||= (base_class == self ? super : base_class.generated_attribute_methods)
|
44
|
+
@attribute_methods_generated ||= false
|
57
45
|
end
|
58
46
|
|
47
|
+
# We will define the methods as instance methods, but will call them as singleton
|
48
|
+
# methods. This allows us to use method_defined? to check if the method exists,
|
49
|
+
# which is fast and won't give any false positives from the ancestors (because
|
50
|
+
# there are no ancestors).
|
59
51
|
def generated_external_attribute_methods
|
60
|
-
@generated_external_attribute_methods ||=
|
61
|
-
if base_class == self
|
62
|
-
# We will define the methods as instance methods, but will call them as singleton
|
63
|
-
# methods. This allows us to use method_defined? to check if the method exists,
|
64
|
-
# which is fast and won't give any false positives from the ancestors (because
|
65
|
-
# there are no ancestors).
|
66
|
-
Module.new { extend self }
|
67
|
-
else
|
68
|
-
base_class.generated_external_attribute_methods
|
69
|
-
end
|
70
|
-
end
|
52
|
+
@generated_external_attribute_methods ||= Module.new { extend self }
|
71
53
|
end
|
72
54
|
|
73
55
|
def undefine_attribute_methods
|
74
|
-
|
75
|
-
|
76
|
-
@attribute_methods_generated = false
|
77
|
-
else
|
78
|
-
base_class.undefine_attribute_methods
|
79
|
-
end
|
56
|
+
super
|
57
|
+
@attribute_methods_generated = false
|
80
58
|
end
|
81
59
|
|
82
60
|
def instance_method_already_implemented?(method_name)
|
@@ -84,19 +62,31 @@ module ActiveRecord
|
|
84
62
|
raise DangerousAttributeError, "#{method_name} is defined by ActiveRecord"
|
85
63
|
end
|
86
64
|
|
87
|
-
|
65
|
+
if superclass == Base
|
66
|
+
super
|
67
|
+
else
|
68
|
+
# If B < A and A defines its own attribute method, then we don't want to overwrite that.
|
69
|
+
defined = method_defined_within?(method_name, superclass, superclass.generated_attribute_methods)
|
70
|
+
defined && !ActiveRecord::Base.method_defined?(method_name) || super
|
71
|
+
end
|
88
72
|
end
|
89
73
|
|
90
74
|
# A method name is 'dangerous' if it is already defined by Active Record, but
|
91
75
|
# not by any ancestors. (So 'puts' is not dangerous but 'save' is.)
|
92
|
-
def dangerous_attribute_method?(
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
76
|
+
def dangerous_attribute_method?(name)
|
77
|
+
method_defined_within?(name, Base)
|
78
|
+
end
|
79
|
+
|
80
|
+
def method_defined_within?(name, klass, sup = klass.superclass)
|
81
|
+
if klass.method_defined?(name) || klass.private_method_defined?(name)
|
82
|
+
if sup.method_defined?(name) || sup.private_method_defined?(name)
|
83
|
+
klass.instance_method(name).owner != sup.instance_method(name).owner
|
84
|
+
else
|
85
|
+
true
|
86
|
+
end
|
87
|
+
else
|
88
|
+
false
|
89
|
+
end
|
100
90
|
end
|
101
91
|
|
102
92
|
def attribute_method?(attribute)
|
@@ -30,15 +30,33 @@ module ActiveRecord
|
|
30
30
|
end
|
31
31
|
|
32
32
|
def undefine_attribute_methods
|
33
|
-
|
34
|
-
|
35
|
-
instance_methods.each { |m| undef_method(m) }
|
36
|
-
end
|
33
|
+
generated_external_attribute_methods.module_eval do
|
34
|
+
instance_methods.each { |m| undef_method(m) }
|
37
35
|
end
|
38
36
|
|
39
37
|
super
|
40
38
|
end
|
41
39
|
|
40
|
+
def type_cast_attribute(attr_name, attributes, cache = {}) #:nodoc:
|
41
|
+
return unless attr_name
|
42
|
+
attr_name = attr_name.to_s
|
43
|
+
|
44
|
+
if generated_external_attribute_methods.method_defined?(attr_name)
|
45
|
+
if attributes.has_key?(attr_name) || attr_name == 'id'
|
46
|
+
generated_external_attribute_methods.send(attr_name, attributes[attr_name], attributes, cache, attr_name)
|
47
|
+
end
|
48
|
+
elsif !attribute_methods_generated?
|
49
|
+
# If we haven't generated the caster methods yet, do that and
|
50
|
+
# then try again
|
51
|
+
define_attribute_methods
|
52
|
+
type_cast_attribute(attr_name, attributes, cache)
|
53
|
+
else
|
54
|
+
# If we get here, the attribute has no associated DB column, so
|
55
|
+
# just return it verbatim.
|
56
|
+
attributes[attr_name]
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
42
60
|
protected
|
43
61
|
# We want to generate the methods via module_eval rather than define_method,
|
44
62
|
# because define_method is slower on dispatch and uses more memory (because it
|
@@ -105,25 +123,7 @@ module ActiveRecord
|
|
105
123
|
# Returns the value of the attribute identified by <tt>attr_name</tt> after it has been typecast (for example,
|
106
124
|
# "2004-12-12" in a data column is cast to a date object, like Date.new(2004, 12, 12)).
|
107
125
|
def read_attribute(attr_name)
|
108
|
-
|
109
|
-
|
110
|
-
attr_name = attr_name.to_s
|
111
|
-
methods = self.class.generated_external_attribute_methods
|
112
|
-
|
113
|
-
if methods.method_defined?(attr_name)
|
114
|
-
if @attributes.has_key?(attr_name) || attr_name == 'id'
|
115
|
-
methods.send(attr_name, @attributes[attr_name], @attributes, @attributes_cache, attr_name)
|
116
|
-
end
|
117
|
-
elsif !self.class.attribute_methods_generated?
|
118
|
-
# If we haven't generated the caster methods yet, do that and
|
119
|
-
# then try again
|
120
|
-
self.class.define_attribute_methods
|
121
|
-
read_attribute(attr_name)
|
122
|
-
else
|
123
|
-
# If we get here, the attribute has no associated DB column, so
|
124
|
-
# just return it verbatim.
|
125
|
-
@attributes[attr_name]
|
126
|
-
end
|
126
|
+
self.class.type_cast_attribute(attr_name, @attributes, @attributes_cache)
|
127
127
|
end
|
128
128
|
|
129
129
|
private
|
@@ -58,6 +58,18 @@ module ActiveRecord
|
|
58
58
|
self.serialized_attributes = serialized_attributes.merge(attr_name.to_s => coder)
|
59
59
|
end
|
60
60
|
|
61
|
+
def initialize_attributes(attributes) #:nodoc:
|
62
|
+
super
|
63
|
+
|
64
|
+
serialized_attributes.each do |key, coder|
|
65
|
+
if attributes.key?(key)
|
66
|
+
attributes[key] = Attribute.new(coder, attributes[key], :serialized)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
attributes
|
71
|
+
end
|
72
|
+
|
61
73
|
private
|
62
74
|
|
63
75
|
def attribute_cast_code(attr_name)
|
@@ -69,14 +81,6 @@ module ActiveRecord
|
|
69
81
|
end
|
70
82
|
end
|
71
83
|
|
72
|
-
def set_serialized_attributes
|
73
|
-
self.class.serialized_attributes.each do |key, coder|
|
74
|
-
if @attributes.key?(key)
|
75
|
-
@attributes[key] = Attribute.new(coder, @attributes[key], :serialized)
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
84
|
def type_cast_attribute_for_write(column, value)
|
81
85
|
if column && coder = self.class.serialized_attributes[column.name]
|
82
86
|
Attribute.new(coder, value, :unserialized)
|
data/lib/active_record/base.rb
CHANGED
@@ -469,7 +469,7 @@ module ActiveRecord #:nodoc:
|
|
469
469
|
# # Instantiates a single new object bypassing mass-assignment security
|
470
470
|
# User.new({ :first_name => 'Jamie', :is_admin => true }, :without_protection => true)
|
471
471
|
def initialize(attributes = nil, options = {})
|
472
|
-
@attributes =
|
472
|
+
@attributes = self.class.initialize_attributes(self.class.column_defaults.dup)
|
473
473
|
@association_cache = {}
|
474
474
|
@aggregation_cache = {}
|
475
475
|
@attributes_cache = {}
|
@@ -482,7 +482,6 @@ module ActiveRecord #:nodoc:
|
|
482
482
|
@relation = nil
|
483
483
|
|
484
484
|
ensure_proper_type
|
485
|
-
set_serialized_attributes
|
486
485
|
|
487
486
|
populate_with_current_scope_attributes
|
488
487
|
|
@@ -503,11 +502,9 @@ module ActiveRecord #:nodoc:
|
|
503
502
|
# post.init_with('attributes' => { 'title' => 'hello world' })
|
504
503
|
# post.title # => 'hello world'
|
505
504
|
def init_with(coder)
|
506
|
-
@attributes = coder['attributes']
|
505
|
+
@attributes = self.class.initialize_attributes(coder['attributes'])
|
507
506
|
@relation = nil
|
508
507
|
|
509
|
-
set_serialized_attributes
|
510
|
-
|
511
508
|
@attributes_cache, @previously_changed, @changed_attributes = {}, {}, {}
|
512
509
|
@association_cache = {}
|
513
510
|
@aggregation_cache = {}
|
@@ -534,7 +531,7 @@ module ActiveRecord #:nodoc:
|
|
534
531
|
_run_after_initialize_callbacks if respond_to?(:_run_after_initialize_callbacks)
|
535
532
|
|
536
533
|
@changed_attributes = {}
|
537
|
-
|
534
|
+
self.class.column_defaults.each do |attr, orig_value|
|
538
535
|
@changed_attributes[attr] = orig_value if field_changed?(attr, orig_value, @attributes[attr])
|
539
536
|
end
|
540
537
|
|
@@ -301,15 +301,8 @@ module ActiveRecord
|
|
301
301
|
# Adds a new index to the table. +column_name+ can be a single Symbol, or
|
302
302
|
# an Array of Symbols.
|
303
303
|
#
|
304
|
-
# The index will be named after the table and the
|
305
|
-
#
|
306
|
-
#
|
307
|
-
# When creating an index on multiple columns, the first column is used as a name
|
308
|
-
# for the index. For example, when you specify an index on two columns
|
309
|
-
# [<tt>:first</tt>, <tt>:last</tt>], the DBMS creates an index for both columns as well as an
|
310
|
-
# index for the first column <tt>:first</tt>. Using just the first name for this index
|
311
|
-
# makes sense, because you will never have to create a singular index with this
|
312
|
-
# name.
|
304
|
+
# The index will be named after the table and the column name(s), unless
|
305
|
+
# you pass <tt>:name</tt> as an option.
|
313
306
|
#
|
314
307
|
# ===== Examples
|
315
308
|
#
|
@@ -65,7 +65,7 @@ module ActiveRecord
|
|
65
65
|
# Post.update_counters [10, 15], :comment_count => 1
|
66
66
|
# # Executes the following SQL:
|
67
67
|
# # UPDATE posts
|
68
|
-
# # SET comment_count = COALESCE(comment_count, 0) + 1
|
68
|
+
# # SET comment_count = COALESCE(comment_count, 0) + 1
|
69
69
|
# # WHERE id IN (10, 15)
|
70
70
|
def update_counters(id, counters)
|
71
71
|
updates = counters.map do |counter_name, value|
|
@@ -111,13 +111,12 @@ module ActiveRecord
|
|
111
111
|
# model object.
|
112
112
|
def reinit_with(coder)
|
113
113
|
@attributes_cache = {}
|
114
|
-
dirty
|
115
|
-
|
114
|
+
dirty = @changed_attributes.keys
|
115
|
+
attributes = self.class.initialize_attributes(coder['attributes'].except(*dirty))
|
116
|
+
@attributes.update(attributes)
|
116
117
|
@changed_attributes.update(coder['attributes'].slice(*dirty))
|
117
118
|
@changed_attributes.delete_if{|k,v| v.eql? @attributes[k]}
|
118
119
|
|
119
|
-
set_serialized_attributes
|
120
|
-
|
121
120
|
run_callbacks :find
|
122
121
|
|
123
122
|
self
|
@@ -64,21 +64,6 @@ module ActiveRecord
|
|
64
64
|
send(lock_col + '=', previous_lock_value + 1)
|
65
65
|
end
|
66
66
|
|
67
|
-
def attributes_from_column_definition
|
68
|
-
result = self.class.column_defaults.dup
|
69
|
-
|
70
|
-
# If the locking column has no default value set,
|
71
|
-
# start the lock version at zero. Note we can't use
|
72
|
-
# <tt>locking_enabled?</tt> at this point as
|
73
|
-
# <tt>@attributes</tt> may not have been initialized yet.
|
74
|
-
|
75
|
-
if result.key?(self.class.locking_column) && lock_optimistically
|
76
|
-
result[self.class.locking_column] ||= 0
|
77
|
-
end
|
78
|
-
|
79
|
-
result
|
80
|
-
end
|
81
|
-
|
82
67
|
def update(attribute_names = @attributes.keys) #:nodoc:
|
83
68
|
return super unless locking_enabled?
|
84
69
|
return 0 if attribute_names.empty?
|
@@ -180,6 +165,18 @@ module ActiveRecord
|
|
180
165
|
counters = counters.merge(locking_column => 1) if locking_enabled?
|
181
166
|
super
|
182
167
|
end
|
168
|
+
|
169
|
+
# If the locking column has no default value set,
|
170
|
+
# start the lock version at zero. Note we can't use
|
171
|
+
# <tt>locking_enabled?</tt> at this point as
|
172
|
+
# <tt>@attributes</tt> may not have been initialized yet.
|
173
|
+
def initialize_attributes(attributes) #:nodoc:
|
174
|
+
if attributes.key?(locking_column) && lock_optimistically
|
175
|
+
attributes[locking_column] ||= 0
|
176
|
+
end
|
177
|
+
|
178
|
+
attributes
|
179
|
+
end
|
183
180
|
end
|
184
181
|
end
|
185
182
|
end
|
@@ -368,13 +368,5 @@ module ActiveRecord
|
|
368
368
|
@new_record = false
|
369
369
|
id
|
370
370
|
end
|
371
|
-
|
372
|
-
# Initializes the attributes array with keys matching the columns from the linked table and
|
373
|
-
# the values matching the corresponding default value of that column, so
|
374
|
-
# that a new instance, or one populated from a passed-in Hash, still has all the attributes
|
375
|
-
# that instances loaded from the database would.
|
376
|
-
def attributes_from_column_definition
|
377
|
-
self.class.column_defaults.dup
|
378
|
-
end
|
379
371
|
end
|
380
372
|
end
|
@@ -38,6 +38,7 @@ db_namespace = namespace :db do
|
|
38
38
|
desc 'Create the database from config/database.yml for the current Rails.env (use db:create:all to create all dbs in the config)'
|
39
39
|
task :create => :load_config do
|
40
40
|
configs_for_environment.each { |config| create_database(config) }
|
41
|
+
ActiveRecord::Base.establish_connection(configs_for_environment.first)
|
41
42
|
end
|
42
43
|
|
43
44
|
def mysql_creation_options(config)
|
@@ -7,7 +7,7 @@ module ActiveRecord
|
|
7
7
|
JoinOperation = Struct.new(:relation, :join_class, :on)
|
8
8
|
ASSOCIATION_METHODS = [:includes, :eager_load, :preload]
|
9
9
|
MULTI_VALUE_METHODS = [:select, :group, :order, :joins, :where, :having, :bind]
|
10
|
-
SINGLE_VALUE_METHODS = [:limit, :offset, :lock, :readonly, :from, :
|
10
|
+
SINGLE_VALUE_METHODS = [:limit, :offset, :lock, :readonly, :from, :reordering, :reverse_order, :uniq]
|
11
11
|
|
12
12
|
include FinderMethods, Calculations, SpawnMethods, QueryMethods, Batches, Explain, Delegation
|
13
13
|
|
@@ -168,7 +168,7 @@ module ActiveRecord
|
|
168
168
|
|
169
169
|
# This method is designed to perform select by a single column as direct SQL query
|
170
170
|
# Returns <tt>Array</tt> with values of the specified column name
|
171
|
-
# The values has same data type as column.
|
171
|
+
# The values has same data type as column.
|
172
172
|
#
|
173
173
|
# Examples:
|
174
174
|
#
|
@@ -177,9 +177,9 @@ module ActiveRecord
|
|
177
177
|
# Person.where(:confirmed => true).limit(5).pluck(:id)
|
178
178
|
#
|
179
179
|
def pluck(column_name)
|
180
|
-
|
181
|
-
|
182
|
-
|
180
|
+
column_name = column_name.to_s
|
181
|
+
klass.connection.select_all(select(column_name).arel).map! do |attributes|
|
182
|
+
klass.type_cast_attribute(attributes.keys.first, klass.initialize_attributes(attributes))
|
183
183
|
end
|
184
184
|
end
|
185
185
|
|
@@ -134,7 +134,7 @@ module ActiveRecord
|
|
134
134
|
def last(*args)
|
135
135
|
if args.any?
|
136
136
|
if args.first.kind_of?(Integer) || (loaded? && !args.first.kind_of?(Hash))
|
137
|
-
if order_values.empty?
|
137
|
+
if order_values.empty?
|
138
138
|
order("#{primary_key} DESC").limit(*args).reverse
|
139
139
|
else
|
140
140
|
to_a.last(*args)
|
@@ -9,7 +9,7 @@ module ActiveRecord
|
|
9
9
|
:select_values, :group_values, :order_values, :joins_values,
|
10
10
|
:where_values, :having_values, :bind_values,
|
11
11
|
:limit_value, :offset_value, :lock_value, :readonly_value, :create_with_value,
|
12
|
-
:from_value, :
|
12
|
+
:from_value, :reordering_value, :reverse_order_value,
|
13
13
|
:uniq_value
|
14
14
|
|
15
15
|
def includes(*args)
|
@@ -63,10 +63,10 @@ module ActiveRecord
|
|
63
63
|
# => [#<Model field: "value", other_field: "value", and_one_more: "value">]
|
64
64
|
#
|
65
65
|
# Any attributes that do not have fields retrieved by a select
|
66
|
-
# will
|
66
|
+
# will raise a ActiveModel::MissingAttributeError when the getter method for that attribute is used:
|
67
67
|
#
|
68
68
|
# >> Model.select(:field).first.other_field
|
69
|
-
# =>
|
69
|
+
# => ActiveModel::MissingAttributeError: missing attribute: other_field
|
70
70
|
def select(value = Proc.new)
|
71
71
|
if block_given?
|
72
72
|
to_a.select {|*block_args| value.call(*block_args) }
|
@@ -97,7 +97,8 @@ module ActiveRecord
|
|
97
97
|
return self if args.blank?
|
98
98
|
|
99
99
|
relation = clone
|
100
|
-
relation.
|
100
|
+
relation.reordering_value = true
|
101
|
+
relation.order_values = args.flatten
|
101
102
|
relation
|
102
103
|
end
|
103
104
|
|
@@ -263,7 +264,7 @@ module ActiveRecord
|
|
263
264
|
|
264
265
|
arel.group(*@group_values.uniq.reject{|g| g.blank?}) unless @group_values.empty?
|
265
266
|
|
266
|
-
order = @
|
267
|
+
order = @order_values
|
267
268
|
order = reverse_sql_order(order) if @reverse_order_value
|
268
269
|
arel.order(*order.uniq.reject{|o| o.blank?}) unless order.empty?
|
269
270
|
|
@@ -22,7 +22,7 @@ module ActiveRecord
|
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
-
(Relation::MULTI_VALUE_METHODS - [:joins, :where]).each do |method|
|
25
|
+
(Relation::MULTI_VALUE_METHODS - [:joins, :where, :order]).each do |method|
|
26
26
|
value = r.send(:"#{method}_values")
|
27
27
|
merged_relation.send(:"#{method}_values=", merged_relation.send(:"#{method}_values") + value) if value.present?
|
28
28
|
end
|
@@ -48,7 +48,7 @@ module ActiveRecord
|
|
48
48
|
|
49
49
|
merged_relation.where_values = merged_wheres
|
50
50
|
|
51
|
-
(Relation::SINGLE_VALUE_METHODS - [:lock, :create_with]).each do |method|
|
51
|
+
(Relation::SINGLE_VALUE_METHODS - [:lock, :create_with, :reordering]).each do |method|
|
52
52
|
value = r.send(:"#{method}_value")
|
53
53
|
merged_relation.send(:"#{method}_value=", value) unless value.nil?
|
54
54
|
end
|
@@ -57,6 +57,15 @@ module ActiveRecord
|
|
57
57
|
|
58
58
|
merged_relation = merged_relation.create_with(r.create_with_value) unless r.create_with_value.empty?
|
59
59
|
|
60
|
+
if (r.reordering_value)
|
61
|
+
# override any order specified in the original relation
|
62
|
+
merged_relation.reordering_value = true
|
63
|
+
merged_relation.order_values = r.order_values
|
64
|
+
else
|
65
|
+
# merge in order_values from r
|
66
|
+
merged_relation.order_values += r.order_values
|
67
|
+
end
|
68
|
+
|
60
69
|
# Apply scope extension modules
|
61
70
|
merged_relation.send :apply_modules, r.extensions
|
62
71
|
|
@@ -12,7 +12,7 @@ module ActiveRecord
|
|
12
12
|
end
|
13
13
|
|
14
14
|
module ClassMethods
|
15
|
-
# Returns a scope for
|
15
|
+
# Returns a scope for the model without the default_scope.
|
16
16
|
#
|
17
17
|
# class Post < ActiveRecord::Base
|
18
18
|
# def self.default_scope
|
@@ -23,18 +23,20 @@ module ActiveRecord
|
|
23
23
|
# Post.all # Fires "SELECT * FROM posts WHERE published = true"
|
24
24
|
# Post.unscoped.all # Fires "SELECT * FROM posts"
|
25
25
|
#
|
26
|
-
# This method also accepts a block
|
26
|
+
# This method also accepts a block. All queries inside the block will
|
27
27
|
# not use the default_scope:
|
28
28
|
#
|
29
29
|
# Post.unscoped {
|
30
30
|
# Post.limit(10) # Fires "SELECT * FROM posts LIMIT 10"
|
31
31
|
# }
|
32
32
|
#
|
33
|
-
# It is recommended to use block form of unscoped because chaining
|
34
|
-
#
|
33
|
+
# It is recommended to use the block form of unscoped because chaining
|
34
|
+
# unscoped with <tt>scope</tt> does not work. Assuming that
|
35
|
+
# <tt>published</tt> is a <tt>scope</tt>, the following two statements
|
36
|
+
# are equal: the default_scope is applied on both.
|
35
37
|
#
|
36
|
-
#
|
37
|
-
#
|
38
|
+
# Post.unscoped.published
|
39
|
+
# Post.published
|
38
40
|
def unscoped #:nodoc:
|
39
41
|
block_given? ? relation.scoping { yield } : relation
|
40
42
|
end
|
@@ -118,16 +118,16 @@ module ActiveRecord
|
|
118
118
|
# when they are used. For example, the following would be incorrect:
|
119
119
|
#
|
120
120
|
# class Post < ActiveRecord::Base
|
121
|
-
# scope :recent, where('published_at >= ?', Time.
|
121
|
+
# scope :recent, where('published_at >= ?', Time.current - 1.week)
|
122
122
|
# end
|
123
123
|
#
|
124
|
-
# The example above would be 'frozen' to the <tt>Time.
|
124
|
+
# The example above would be 'frozen' to the <tt>Time.current</tt> value when the <tt>Post</tt>
|
125
125
|
# class was defined, and so the resultant SQL query would always be the same. The correct
|
126
126
|
# way to do this would be via a lambda, which will re-evaluate the scope each time
|
127
127
|
# it is called:
|
128
128
|
#
|
129
129
|
# class Post < ActiveRecord::Base
|
130
|
-
# scope :recent, lambda { where('published_at >= ?', Time.
|
130
|
+
# scope :recent, lambda { where('published_at >= ?', Time.current - 1.week) }
|
131
131
|
# end
|
132
132
|
#
|
133
133
|
# Named \scopes can also have extensions, just as with <tt>has_many</tt> declarations:
|
@@ -51,11 +51,11 @@ module ActiveRecord
|
|
51
51
|
class SessionStore < ActionDispatch::Session::AbstractStore
|
52
52
|
module ClassMethods # :nodoc:
|
53
53
|
def marshal(data)
|
54
|
-
|
54
|
+
::Base64.encode64(Marshal.dump(data)) if data
|
55
55
|
end
|
56
56
|
|
57
57
|
def unmarshal(data)
|
58
|
-
Marshal.load(
|
58
|
+
Marshal.load(::Base64.decode64(data)) if data
|
59
59
|
end
|
60
60
|
|
61
61
|
def drop_table!
|
@@ -169,11 +169,11 @@ module ActiveRecord
|
|
169
169
|
# are implemented as class methods that you may override. By default,
|
170
170
|
# marshaling data is
|
171
171
|
#
|
172
|
-
#
|
172
|
+
# ::Base64.encode64(Marshal.dump(data))
|
173
173
|
#
|
174
174
|
# and unmarshaling data is
|
175
175
|
#
|
176
|
-
# Marshal.load(
|
176
|
+
# Marshal.load(::Base64.decode64(data))
|
177
177
|
#
|
178
178
|
# This marshaling behavior is intended to store the widest range of
|
179
179
|
# binary session data in a +text+ column. For higher performance,
|
@@ -3,7 +3,7 @@ require 'rails/generators/active_record'
|
|
3
3
|
module ActiveRecord
|
4
4
|
module Generators
|
5
5
|
class MigrationGenerator < Base
|
6
|
-
argument :attributes, :type => :array, :default => [], :banner => "field:type field:type"
|
6
|
+
argument :attributes, :type => :array, :default => [], :banner => "field[:type][:index] field[:type][:index]"
|
7
7
|
|
8
8
|
def create_migration_file
|
9
9
|
set_local_assigns!
|
@@ -2,14 +2,20 @@ class <%= migration_class_name %> < ActiveRecord::Migration
|
|
2
2
|
<%- if migration_action == 'add' -%>
|
3
3
|
def change
|
4
4
|
<% attributes.each do |attribute| -%>
|
5
|
-
add_column :<%= table_name %>, :<%= attribute.name %>, :<%= attribute.type %>
|
5
|
+
add_column :<%= table_name %>, :<%= attribute.name %>, :<%= attribute.type %><%= attribute.inject_options %>
|
6
|
+
<%- if attribute.has_index? -%>
|
7
|
+
add_index :<%= table_name %>, :<%= attribute.index_name %><%= attribute.inject_index_options %>
|
8
|
+
<%- end %>
|
6
9
|
<%- end -%>
|
7
10
|
end
|
8
11
|
<%- else -%>
|
9
12
|
def up
|
10
13
|
<% attributes.each do |attribute| -%>
|
11
14
|
<%- if migration_action -%>
|
12
|
-
<%= migration_action %>_column :<%= table_name %>, :<%= attribute.name %><% if migration_action == 'add' %>, :<%= attribute.type %><% end %>
|
15
|
+
<%= migration_action %>_column :<%= table_name %>, :<%= attribute.name %><% if migration_action == 'add' %>, :<%= attribute.type %><%= attribute.inject_options %><% end %>
|
16
|
+
<% if attribute.has_index? && migration_action == 'add' %>
|
17
|
+
add_index :<%= table_name %>, :<%= attribute.index_name %><%= attribute.inject_index_options %>
|
18
|
+
<% end -%>
|
13
19
|
<%- end -%>
|
14
20
|
<%- end -%>
|
15
21
|
end
|
@@ -17,7 +23,7 @@ class <%= migration_class_name %> < ActiveRecord::Migration
|
|
17
23
|
def down
|
18
24
|
<% attributes.reverse.each do |attribute| -%>
|
19
25
|
<%- if migration_action -%>
|
20
|
-
<%= migration_action == 'add' ? 'remove' : 'add' %>_column :<%= table_name %>, :<%= attribute.name %><% if migration_action == 'remove' %>, :<%= attribute.type %><% end %>
|
26
|
+
<%= migration_action == 'add' ? 'remove' : 'add' %>_column :<%= table_name %>, :<%= attribute.name %><% if migration_action == 'remove' %>, :<%= attribute.type %><%= attribute.inject_options %><% end %>
|
21
27
|
<%- end -%>
|
22
28
|
<%- end -%>
|
23
29
|
end
|
@@ -3,7 +3,7 @@ require 'rails/generators/active_record'
|
|
3
3
|
module ActiveRecord
|
4
4
|
module Generators
|
5
5
|
class ModelGenerator < Base
|
6
|
-
argument :attributes, :type => :array, :default => [], :banner => "field:type field:type"
|
6
|
+
argument :attributes, :type => :array, :default => [], :banner => "field[:type][:index] field[:type][:index]"
|
7
7
|
|
8
8
|
check_class_collision
|
9
9
|
|
@@ -26,6 +26,10 @@ module ActiveRecord
|
|
26
26
|
template 'module.rb', File.join('app/models', "#{class_path.join('/')}.rb") if behavior == :invoke
|
27
27
|
end
|
28
28
|
|
29
|
+
def attributes_with_index
|
30
|
+
attributes.select { |a| a.has_index? || (a.reference? && options[:indexes]) }
|
31
|
+
end
|
32
|
+
|
29
33
|
hook_for :test_framework
|
30
34
|
|
31
35
|
protected
|
@@ -2,16 +2,14 @@ class <%= migration_class_name %> < ActiveRecord::Migration
|
|
2
2
|
def change
|
3
3
|
create_table :<%= table_name %> do |t|
|
4
4
|
<% attributes.each do |attribute| -%>
|
5
|
-
t.<%= attribute.type %> :<%= attribute.name %>
|
5
|
+
t.<%= attribute.type %> :<%= attribute.name %><%= attribute.inject_options %>
|
6
6
|
<% end -%>
|
7
7
|
<% if options[:timestamps] %>
|
8
8
|
t.timestamps
|
9
9
|
<% end -%>
|
10
10
|
end
|
11
|
-
<%
|
12
|
-
|
13
|
-
add_index :<%= table_name %>, :<%= attribute.name %>_id
|
14
|
-
<% end -%>
|
11
|
+
<% attributes_with_index.each do |attribute| -%>
|
12
|
+
add_index :<%= table_name %>, :<%= attribute.index_name %><%= attribute.inject_index_options %>
|
15
13
|
<% end -%>
|
16
14
|
end
|
17
15
|
end
|
metadata
CHANGED
@@ -1,69 +1,100 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: activerecord
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
prerelease:
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 977940591
|
5
|
+
prerelease: true
|
6
|
+
segments:
|
7
|
+
- 3
|
8
|
+
- 2
|
9
|
+
- 0
|
10
|
+
- rc2
|
11
|
+
version: 3.2.0.rc2
|
6
12
|
platform: ruby
|
7
|
-
authors:
|
13
|
+
authors:
|
8
14
|
- David Heinemeier Hansson
|
9
15
|
autorequire:
|
10
16
|
bindir: bin
|
11
17
|
cert_chain: []
|
12
|
-
|
13
|
-
|
14
|
-
|
18
|
+
|
19
|
+
date: 2012-01-04 00:00:00 -02:00
|
20
|
+
default_executable:
|
21
|
+
dependencies:
|
22
|
+
- !ruby/object:Gem::Dependency
|
15
23
|
name: activesupport
|
16
|
-
|
24
|
+
prerelease: false
|
25
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
17
26
|
none: false
|
18
|
-
requirements:
|
19
|
-
- - =
|
20
|
-
- !ruby/object:Gem::Version
|
21
|
-
|
27
|
+
requirements:
|
28
|
+
- - "="
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
hash: 977940591
|
31
|
+
segments:
|
32
|
+
- 3
|
33
|
+
- 2
|
34
|
+
- 0
|
35
|
+
- rc2
|
36
|
+
version: 3.2.0.rc2
|
22
37
|
type: :runtime
|
23
|
-
|
24
|
-
|
25
|
-
- !ruby/object:Gem::Dependency
|
38
|
+
version_requirements: *id001
|
39
|
+
- !ruby/object:Gem::Dependency
|
26
40
|
name: activemodel
|
27
|
-
|
41
|
+
prerelease: false
|
42
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
28
43
|
none: false
|
29
|
-
requirements:
|
30
|
-
- - =
|
31
|
-
- !ruby/object:Gem::Version
|
32
|
-
|
44
|
+
requirements:
|
45
|
+
- - "="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
hash: 977940591
|
48
|
+
segments:
|
49
|
+
- 3
|
50
|
+
- 2
|
51
|
+
- 0
|
52
|
+
- rc2
|
53
|
+
version: 3.2.0.rc2
|
33
54
|
type: :runtime
|
34
|
-
|
35
|
-
|
36
|
-
- !ruby/object:Gem::Dependency
|
55
|
+
version_requirements: *id002
|
56
|
+
- !ruby/object:Gem::Dependency
|
37
57
|
name: arel
|
38
|
-
|
58
|
+
prerelease: false
|
59
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
39
60
|
none: false
|
40
|
-
requirements:
|
61
|
+
requirements:
|
41
62
|
- - ~>
|
42
|
-
- !ruby/object:Gem::Version
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
hash: 977940606
|
65
|
+
segments:
|
66
|
+
- 3
|
67
|
+
- 0
|
68
|
+
- 0
|
69
|
+
- rc1
|
43
70
|
version: 3.0.0.rc1
|
44
71
|
type: :runtime
|
45
|
-
|
46
|
-
|
47
|
-
- !ruby/object:Gem::Dependency
|
72
|
+
version_requirements: *id003
|
73
|
+
- !ruby/object:Gem::Dependency
|
48
74
|
name: tzinfo
|
49
|
-
|
75
|
+
prerelease: false
|
76
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
50
77
|
none: false
|
51
|
-
requirements:
|
78
|
+
requirements:
|
52
79
|
- - ~>
|
53
|
-
- !ruby/object:Gem::Version
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
hash: 41
|
82
|
+
segments:
|
83
|
+
- 0
|
84
|
+
- 3
|
85
|
+
- 29
|
54
86
|
version: 0.3.29
|
55
87
|
type: :runtime
|
56
|
-
|
57
|
-
|
58
|
-
description: Databases on Rails. Build a persistent domain model by mapping database
|
59
|
-
tables to Ruby classes. Strong conventions for associations, validations, aggregations,
|
60
|
-
migrations, and testing come baked-in.
|
88
|
+
version_requirements: *id004
|
89
|
+
description: Databases on Rails. Build a persistent domain model by mapping database tables to Ruby classes. Strong conventions for associations, validations, aggregations, migrations, and testing come baked-in.
|
61
90
|
email: david@loudthinking.com
|
62
91
|
executables: []
|
92
|
+
|
63
93
|
extensions: []
|
64
|
-
|
94
|
+
|
95
|
+
extra_rdoc_files:
|
65
96
|
- README.rdoc
|
66
|
-
files:
|
97
|
+
files:
|
67
98
|
- CHANGELOG.md
|
68
99
|
- MIT-LICENSE
|
69
100
|
- README.rdoc
|
@@ -213,30 +244,44 @@ files:
|
|
213
244
|
- lib/rails/generators/active_record/session_migration/session_migration_generator.rb
|
214
245
|
- lib/rails/generators/active_record/session_migration/templates/migration.rb
|
215
246
|
- lib/rails/generators/active_record.rb
|
247
|
+
has_rdoc: true
|
216
248
|
homepage: http://www.rubyonrails.org
|
217
249
|
licenses: []
|
250
|
+
|
218
251
|
post_install_message:
|
219
|
-
rdoc_options:
|
252
|
+
rdoc_options:
|
220
253
|
- --main
|
221
254
|
- README.rdoc
|
222
|
-
require_paths:
|
255
|
+
require_paths:
|
223
256
|
- lib
|
224
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
257
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
225
258
|
none: false
|
226
|
-
requirements:
|
227
|
-
- -
|
228
|
-
- !ruby/object:Gem::Version
|
259
|
+
requirements:
|
260
|
+
- - ">="
|
261
|
+
- !ruby/object:Gem::Version
|
262
|
+
hash: 57
|
263
|
+
segments:
|
264
|
+
- 1
|
265
|
+
- 8
|
266
|
+
- 7
|
229
267
|
version: 1.8.7
|
230
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
268
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
231
269
|
none: false
|
232
|
-
requirements:
|
233
|
-
- -
|
234
|
-
- !ruby/object:Gem::Version
|
270
|
+
requirements:
|
271
|
+
- - ">"
|
272
|
+
- !ruby/object:Gem::Version
|
273
|
+
hash: 25
|
274
|
+
segments:
|
275
|
+
- 1
|
276
|
+
- 3
|
277
|
+
- 1
|
235
278
|
version: 1.3.1
|
236
279
|
requirements: []
|
280
|
+
|
237
281
|
rubyforge_project:
|
238
|
-
rubygems_version: 1.
|
282
|
+
rubygems_version: 1.3.7
|
239
283
|
signing_key:
|
240
284
|
specification_version: 3
|
241
285
|
summary: Object-relational mapper framework (part of Rails).
|
242
286
|
test_files: []
|
287
|
+
|