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.

@@ -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
- if base_class == self
40
- super(column_names)
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
- if base_class == self
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 ||= begin
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
- if base_class == self
75
- super
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
- super
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?(method_name)
93
- active_record = ActiveRecord::Base
94
- superclass = ActiveRecord::Base.superclass
95
-
96
- (active_record.method_defined?(method_name) ||
97
- active_record.private_method_defined?(method_name)) &&
98
- !superclass.method_defined?(method_name) &&
99
- !superclass.private_method_defined?(method_name)
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
- if base_class == self
34
- generated_external_attribute_methods.module_eval do
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
- return unless attr_name
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)
@@ -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 = attributes_from_column_definition
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
- attributes_from_column_definition.each do |attr, orig_value|
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 first column name,
305
- # unless you pass <tt>:name</tt> as an option.
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 = @changed_attributes.keys
115
- @attributes.update(coder['attributes'].except(*dirty))
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
@@ -59,7 +59,7 @@ module ActiveRecord
59
59
  private
60
60
 
61
61
  def invert_create_table(args)
62
- [:drop_table, args]
62
+ [:drop_table, [args.first]]
63
63
  end
64
64
 
65
65
  def invert_rename_table(args)
@@ -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, :reorder, :reverse_order, :uniq]
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
- scope = self.select(column_name)
181
- self.connection.select_values(scope.to_sql).map! do |value|
182
- type_cast_using_column(value, column_for(column_name))
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? && reorder_value.nil?
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, :reorder_value, :reverse_order_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 return `nil` when the getter method for that attribute is used:
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
- # => nil
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.reorder_value = args.flatten
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 = @reorder_value ? @reorder_value : @order_values
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 this class without taking into account the default_scope.
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 meaning that all queries inside the block will
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 unscoped with <tt>scope</tt>
34
- # does not work. Assuming that <tt>published</tt> is a <tt>scope</tt> following two statements are same.
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
- # Post.unscoped.published
37
- # Post.published
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.now - 1.week)
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.now</tt> value when the <tt>Post</tt>
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.now - 1.week) }
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
- ActiveSupport::Base64.encode64(Marshal.dump(data)) if data
54
+ ::Base64.encode64(Marshal.dump(data)) if data
55
55
  end
56
56
 
57
57
  def unmarshal(data)
58
- Marshal.load(ActiveSupport::Base64.decode64(data)) if data
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
- # ActiveSupport::Base64.encode64(Marshal.dump(data))
172
+ # ::Base64.encode64(Marshal.dump(data))
173
173
  #
174
174
  # and unmarshaling data is
175
175
  #
176
- # Marshal.load(ActiveSupport::Base64.decode64(data))
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 @@ module ActiveRecord
3
3
  MAJOR = 3
4
4
  MINOR = 2
5
5
  TINY = 0
6
- PRE = "rc1"
6
+ PRE = "rc2"
7
7
 
8
8
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
9
9
  end
@@ -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
- <% if options[:indexes] -%>
12
- <% attributes.select {|attr| attr.reference? }.each do |attribute| -%>
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
- version: 3.2.0.rc1
5
- prerelease: 6
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
- date: 2011-12-20 00:00:00.000000000 Z
13
- dependencies:
14
- - !ruby/object:Gem::Dependency
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
- requirement: &2156029700 !ruby/object:Gem::Requirement
24
+ prerelease: false
25
+ requirement: &id001 !ruby/object:Gem::Requirement
17
26
  none: false
18
- requirements:
19
- - - =
20
- - !ruby/object:Gem::Version
21
- version: 3.2.0.rc1
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
- prerelease: false
24
- version_requirements: *2156029700
25
- - !ruby/object:Gem::Dependency
38
+ version_requirements: *id001
39
+ - !ruby/object:Gem::Dependency
26
40
  name: activemodel
27
- requirement: &2156028220 !ruby/object:Gem::Requirement
41
+ prerelease: false
42
+ requirement: &id002 !ruby/object:Gem::Requirement
28
43
  none: false
29
- requirements:
30
- - - =
31
- - !ruby/object:Gem::Version
32
- version: 3.2.0.rc1
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
- prerelease: false
35
- version_requirements: *2156028220
36
- - !ruby/object:Gem::Dependency
55
+ version_requirements: *id002
56
+ - !ruby/object:Gem::Dependency
37
57
  name: arel
38
- requirement: &2156025120 !ruby/object:Gem::Requirement
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
- prerelease: false
46
- version_requirements: *2156025120
47
- - !ruby/object:Gem::Dependency
72
+ version_requirements: *id003
73
+ - !ruby/object:Gem::Dependency
48
74
  name: tzinfo
49
- requirement: &2156024360 !ruby/object:Gem::Requirement
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
- prerelease: false
57
- version_requirements: *2156024360
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
- extra_rdoc_files:
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.8.7
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
+