activerecord 3.0.0.beta2 → 3.0.0.beta3

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.

Files changed (28) hide show
  1. data/CHANGELOG +11 -1
  2. data/lib/active_record/associations.rb +26 -54
  3. data/lib/active_record/associations/association_collection.rb +13 -2
  4. data/lib/active_record/associations/association_proxy.rb +3 -1
  5. data/lib/active_record/associations/through_association_scope.rb +1 -1
  6. data/lib/active_record/attribute_methods/dirty.rb +6 -0
  7. data/lib/active_record/attribute_methods/time_zone_conversion.rb +4 -4
  8. data/lib/active_record/base.rb +66 -62
  9. data/lib/active_record/callbacks.rb +4 -2
  10. data/lib/active_record/connection_adapters/abstract/query_cache.rb +2 -3
  11. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +5 -3
  12. data/lib/active_record/connection_adapters/abstract_adapter.rb +1 -0
  13. data/lib/active_record/connection_adapters/postgresql_adapter.rb +45 -45
  14. data/lib/active_record/migration.rb +1 -1
  15. data/lib/active_record/named_scope.rb +26 -109
  16. data/lib/active_record/railties/databases.rake +3 -7
  17. data/lib/active_record/reflection.rb +11 -0
  18. data/lib/active_record/relation.rb +20 -1
  19. data/lib/active_record/relation/finder_methods.rb +18 -2
  20. data/lib/active_record/relation/predicate_builder.rb +4 -2
  21. data/lib/active_record/relation/query_methods.rb +26 -8
  22. data/lib/active_record/relation/spawn_methods.rb +9 -6
  23. data/lib/active_record/serializers/xml_serializer.rb +2 -1
  24. data/lib/active_record/validations/uniqueness.rb +3 -1
  25. data/lib/active_record/version.rb +1 -1
  26. data/lib/rails/generators/active_record/model/model_generator.rb +5 -0
  27. data/lib/rails/generators/active_record/model/templates/module.rb +5 -0
  28. metadata +8 -7
@@ -84,15 +84,9 @@ namespace :db do
84
84
  end
85
85
  end
86
86
  when 'postgresql'
87
- @encoding = config['encoding'] || ENV['CHARSET'] || 'utf8'
88
- schema_search_path = config['schema_search_path'] || 'public'
89
- first_in_schema_search_path = schema_search_path.split(',').first.strip
87
+ @encoding = config[:encoding] || ENV['CHARSET'] || 'utf8'
90
88
  begin
91
89
  ActiveRecord::Base.establish_connection(config.merge('database' => 'postgres', 'schema_search_path' => 'public'))
92
- unless ActiveRecord::Base.connection.all_schemas.include?(first_in_schema_search_path)
93
- ActiveRecord::Base.connection.create_schema(first_in_schema_search_path, config['username'])
94
- $stderr.puts "Schema #{first_in_schema_search_path} has been created."
95
- end
96
90
  ActiveRecord::Base.connection.create_database(config['database'], config.merge('encoding' => @encoding))
97
91
  ActiveRecord::Base.establish_connection(config)
98
92
  rescue
@@ -452,6 +446,8 @@ namespace :db do
452
446
  end
453
447
  end
454
448
 
449
+ task 'test:prepare' => 'db:test:prepare'
450
+
455
451
  def drop_database(config)
456
452
  case config['adapter']
457
453
  when 'mysql'
@@ -277,6 +277,17 @@ module ActiveRecord
277
277
  !options[:validate].nil? ? options[:validate] : (options[:autosave] == true || macro == :has_many)
278
278
  end
279
279
 
280
+ def dependent_conditions(record, base_class, extra_conditions)
281
+ dependent_conditions = []
282
+ dependent_conditions << "#{primary_key_name} = #{record.send(name).send(:owner_quoted_id)}"
283
+ dependent_conditions << "#{options[:as]}_type = '#{base_class.name}'" if options[:as]
284
+ dependent_conditions << klass.send(:sanitize_sql, options[:conditions]) if options[:conditions]
285
+ dependent_conditions << extra_conditions if extra_conditions
286
+ dependent_conditions = dependent_conditions.collect {|where| "(#{where})" }.join(" AND ")
287
+ dependent_conditions = dependent_conditions.gsub('@', '\@')
288
+ dependent_conditions
289
+ end
290
+
280
291
  private
281
292
  def derive_class_name
282
293
  class_name = name.to_s.camelize
@@ -13,8 +13,9 @@ module ActiveRecord
13
13
  delegate :insert, :to => :arel
14
14
 
15
15
  attr_reader :table, :klass
16
+ attr_accessor :extensions
16
17
 
17
- def initialize(klass, table)
18
+ def initialize(klass, table, &block)
18
19
  @klass, @table = klass, table
19
20
 
20
21
  @implicit_readonly = nil
@@ -22,6 +23,9 @@ module ActiveRecord
22
23
 
23
24
  SINGLE_VALUE_METHODS.each {|v| instance_variable_set(:"@#{v}_value", nil)}
24
25
  (ASSOCIATION_METHODS + MULTI_VALUE_METHODS).each {|v| instance_variable_set(:"@#{v}_values", [])}
26
+ @extensions = []
27
+
28
+ apply_modules(Module.new(&block)) if block_given?
25
29
  end
26
30
 
27
31
  def new(*args, &block)
@@ -307,11 +311,26 @@ module ActiveRecord
307
311
  @should_eager_load ||= (@eager_load_values.any? || (@includes_values.any? && references_eager_loaded_tables?))
308
312
  end
309
313
 
314
+ def ==(other)
315
+ case other
316
+ when Relation
317
+ other.to_sql == to_sql
318
+ when Array
319
+ to_a == other.to_a
320
+ end
321
+ end
322
+
323
+ def inspect
324
+ to_a.inspect
325
+ end
326
+
310
327
  protected
311
328
 
312
329
  def method_missing(method, *args, &block)
313
330
  if Array.method_defined?(method)
314
331
  to_a.send(method, *args, &block)
332
+ elsif @klass.scopes[method]
333
+ merge(@klass.send(method, *args, &block))
315
334
  elsif @klass.respond_to?(method)
316
335
  @klass.send(:with_scope, self) { @klass.send(method, *args, &block) }
317
336
  elsif arel.respond_to?(method)
@@ -106,13 +106,29 @@ module ActiveRecord
106
106
  # A convenience wrapper for <tt>find(:first, *args)</tt>. You can pass in all the
107
107
  # same arguments to this method as you can to <tt>find(:first)</tt>.
108
108
  def first(*args)
109
- args.any? ? apply_finder_options(args.first).first : find_first
109
+ if args.any?
110
+ if args.first.kind_of?(Integer) || (loaded? && !args.first.kind_of?(Hash))
111
+ to_a.first(*args)
112
+ else
113
+ apply_finder_options(args.first).first
114
+ end
115
+ else
116
+ find_first
117
+ end
110
118
  end
111
119
 
112
120
  # A convenience wrapper for <tt>find(:last, *args)</tt>. You can pass in all the
113
121
  # same arguments to this method as you can to <tt>find(:last)</tt>.
114
122
  def last(*args)
115
- args.any? ? apply_finder_options(args.first).last : find_last
123
+ if args.any?
124
+ if args.first.kind_of?(Integer) || (loaded? && !args.first.kind_of?(Hash))
125
+ to_a.last(*args)
126
+ else
127
+ apply_finder_options(args.first).last
128
+ end
129
+ else
130
+ find_last
131
+ end
116
132
  end
117
133
 
118
134
  # A convenience wrapper for <tt>find(:all, *args)</tt>. You can pass in all the
@@ -20,10 +20,12 @@ module ActiveRecord
20
20
  table = Arel::Table.new(table_name, :engine => @engine)
21
21
  end
22
22
 
23
- attribute = table[column]
23
+ unless attribute = table[column]
24
+ raise StatementInvalid, "No attribute named `#{column}` exists for table `#{table.name}`"
25
+ end
24
26
 
25
27
  case value
26
- when Array, ActiveRecord::Associations::AssociationCollection, ActiveRecord::NamedScope::Scope
28
+ when Array, ActiveRecord::Associations::AssociationCollection, ActiveRecord::Relation
27
29
  values = value.to_a
28
30
  attribute.in(values)
29
31
  when Range
@@ -1,3 +1,4 @@
1
+ require 'active_support/core_ext/array/wrap'
1
2
  require 'active_support/core_ext/object/blank'
2
3
 
3
4
  module ActiveRecord
@@ -9,9 +10,10 @@ module ActiveRecord
9
10
  attr_accessor :"#{query_method}_values"
10
11
 
11
12
  next if [:where, :having].include?(query_method)
12
- class_eval <<-CEVAL
13
- def #{query_method}(*args)
13
+ class_eval <<-CEVAL, __FILE__
14
+ def #{query_method}(*args, &block)
14
15
  new_relation = clone
16
+ new_relation.send(:apply_modules, Module.new(&block)) if block_given?
15
17
  value = Array.wrap(args.flatten).reject {|x| x.blank? }
16
18
  new_relation.#{query_method}_values += value if value.present?
17
19
  new_relation
@@ -20,11 +22,12 @@ module ActiveRecord
20
22
  end
21
23
 
22
24
  [:where, :having].each do |query_method|
23
- class_eval <<-CEVAL
24
- def #{query_method}(*args)
25
+ class_eval <<-CEVAL, __FILE__
26
+ def #{query_method}(*args, &block)
25
27
  new_relation = clone
28
+ new_relation.send(:apply_modules, Module.new(&block)) if block_given?
26
29
  value = build_where(*args)
27
- new_relation.#{query_method}_values += [*value] if value.present?
30
+ new_relation.#{query_method}_values += Array.wrap(value) if value.present?
28
31
  new_relation
29
32
  end
30
33
  CEVAL
@@ -33,9 +36,10 @@ module ActiveRecord
33
36
  ActiveRecord::Relation::SINGLE_VALUE_METHODS.each do |query_method|
34
37
  attr_accessor :"#{query_method}_value"
35
38
 
36
- class_eval <<-CEVAL
37
- def #{query_method}(value = true)
39
+ class_eval <<-CEVAL, __FILE__
40
+ def #{query_method}(value = true, &block)
38
41
  new_relation = clone
42
+ new_relation.send(:apply_modules, Module.new(&block)) if block_given?
39
43
  new_relation.#{query_method}_value = value
40
44
  new_relation
41
45
  end
@@ -43,8 +47,16 @@ module ActiveRecord
43
47
  end
44
48
  end
45
49
 
46
- def lock(locks = true)
50
+ def extending(*modules)
51
+ new_relation = clone
52
+ new_relation.send :apply_modules, *modules
53
+ new_relation
54
+ end
55
+
56
+ def lock(locks = true, &block)
47
57
  relation = clone
58
+ relation.send(:apply_modules, Module.new(&block)) if block_given?
59
+
48
60
  case locks
49
61
  when String, TrueClass, NilClass
50
62
  clone.tap {|new_relation| new_relation.lock_value = locks || true }
@@ -191,6 +203,12 @@ module ActiveRecord
191
203
 
192
204
  private
193
205
 
206
+ def apply_modules(modules)
207
+ values = Array.wrap(modules)
208
+ @extensions += values if values.present?
209
+ values.each {|extension| extend(extension) }
210
+ end
211
+
194
212
  def reverse_sql_order(order_query)
195
213
  order_query.to_s.split(/,/).each { |s|
196
214
  if s.match(/\s(asc|ASC)$/)
@@ -6,10 +6,9 @@ module ActiveRecord
6
6
  merged_relation = clone
7
7
  return merged_relation unless r
8
8
 
9
- (ActiveRecord::Relation::ASSOCIATION_METHODS + ActiveRecord::Relation::MULTI_VALUE_METHODS).reject {|m| [:joins, :where].include?(m)}.each do |method|
10
- unless (value = r.send(:"#{method}_values")).blank?
11
- merged_relation.send(:"#{method}_values=", value)
12
- end
9
+ (Relation::ASSOCIATION_METHODS + Relation::MULTI_VALUE_METHODS).reject {|m| [:joins, :where].include?(m)}.each do |method|
10
+ value = r.send(:"#{method}_values")
11
+ merged_relation.send(:"#{method}_values=", value) if value.present?
13
12
  end
14
13
 
15
14
  merged_relation = merged_relation.joins(r.joins_values)
@@ -26,7 +25,7 @@ module ActiveRecord
26
25
 
27
26
  merged_relation.where_values = merged_wheres
28
27
 
29
- ActiveRecord::Relation::SINGLE_VALUE_METHODS.reject {|m| m == :lock}.each do |method|
28
+ Relation::SINGLE_VALUE_METHODS.reject {|m| m == :lock}.each do |method|
30
29
  unless (value = r.send(:"#{method}_value")).nil?
31
30
  merged_relation.send(:"#{method}_value=", value)
32
31
  end
@@ -34,6 +33,9 @@ module ActiveRecord
34
33
 
35
34
  merged_relation.lock_value = r.lock_value unless merged_relation.lock_value
36
35
 
36
+ # Apply scope extension modules
37
+ merged_relation.send :apply_modules, r.extensions
38
+
37
39
  merged_relation
38
40
  end
39
41
 
@@ -69,7 +71,7 @@ module ActiveRecord
69
71
  result
70
72
  end
71
73
 
72
- VALID_FIND_OPTIONS = [ :conditions, :include, :joins, :limit, :offset,
74
+ VALID_FIND_OPTIONS = [ :conditions, :include, :joins, :limit, :offset, :extend,
73
75
  :order, :select, :readonly, :group, :having, :from, :lock ]
74
76
 
75
77
  def apply_finder_options(options)
@@ -84,6 +86,7 @@ module ActiveRecord
84
86
 
85
87
  relation = relation.where(options[:conditions]) if options.has_key?(:conditions)
86
88
  relation = relation.includes(options[:include]) if options.has_key?(:include)
89
+ relation = relation.extending(options[:extend]) if options.has_key?(:extend)
87
90
 
88
91
  relation
89
92
  end
@@ -1,3 +1,4 @@
1
+ require 'active_support/core_ext/array/wrap'
1
2
  require 'active_support/core_ext/hash/conversions'
2
3
 
3
4
  module ActiveRecord #:nodoc:
@@ -186,7 +187,7 @@ module ActiveRecord #:nodoc:
186
187
  end
187
188
 
188
189
  def serializable_method_attributes
189
- Array(options[:methods]).inject([]) do |method_attributes, name|
190
+ Array.wrap(options[:methods]).inject([]) do |method_attributes, name|
190
191
  method_attributes << MethodAttribute.new(name.to_s, @serializable) if @serializable.respond_to?(name.to_s)
191
192
  method_attributes
192
193
  end
@@ -1,3 +1,5 @@
1
+ require 'active_support/core_ext/array/wrap'
2
+
1
3
  module ActiveRecord
2
4
  module Validations
3
5
  class UniquenessValidator < ActiveModel::EachValidator
@@ -19,7 +21,7 @@ module ActiveRecord
19
21
 
20
22
  relation = table.where(sql, *params)
21
23
 
22
- Array(options[:scope]).each do |scope_item|
24
+ Array.wrap(options[:scope]).each do |scope_item|
23
25
  scope_value = record.send(scope_item)
24
26
  relation = relation.where(scope_item => scope_value)
25
27
  end
@@ -3,7 +3,7 @@ module ActiveRecord
3
3
  MAJOR = 3
4
4
  MINOR = 0
5
5
  TINY = 0
6
- BUILD = "beta2"
6
+ BUILD = "beta3"
7
7
 
8
8
  STRING = [MAJOR, MINOR, TINY, BUILD].join('.')
9
9
  end
@@ -20,6 +20,11 @@ module ActiveRecord
20
20
  template 'model.rb', File.join('app/models', class_path, "#{file_name}.rb")
21
21
  end
22
22
 
23
+ def create_module_file
24
+ return if class_path.empty?
25
+ template 'module.rb', File.join('app/models', "#{class_path.join('/')}.rb")
26
+ end
27
+
23
28
  hook_for :test_framework
24
29
 
25
30
  protected
@@ -0,0 +1,5 @@
1
+ module <%= class_path.map(&:camelize).join('::') %>
2
+ def self.table_name_prefix
3
+ '<%= class_path.join('_') %>_'
4
+ end
5
+ end
metadata CHANGED
@@ -6,8 +6,8 @@ version: !ruby/object:Gem::Version
6
6
  - 3
7
7
  - 0
8
8
  - 0
9
- - beta2
10
- version: 3.0.0.beta2
9
+ - beta3
10
+ version: 3.0.0.beta3
11
11
  platform: ruby
12
12
  authors:
13
13
  - David Heinemeier Hansson
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-04-01 00:00:00 -07:00
18
+ date: 2010-04-13 00:00:00 -07:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -29,8 +29,8 @@ dependencies:
29
29
  - 3
30
30
  - 0
31
31
  - 0
32
- - beta2
33
- version: 3.0.0.beta2
32
+ - beta3
33
+ version: 3.0.0.beta3
34
34
  type: :runtime
35
35
  version_requirements: *id001
36
36
  - !ruby/object:Gem::Dependency
@@ -44,8 +44,8 @@ dependencies:
44
44
  - 3
45
45
  - 0
46
46
  - 0
47
- - beta2
48
- version: 3.0.0.beta2
47
+ - beta3
48
+ version: 3.0.0.beta3
49
49
  type: :runtime
50
50
  version_requirements: *id002
51
51
  - !ruby/object:Gem::Dependency
@@ -154,6 +154,7 @@ files:
154
154
  - lib/rails/generators/active_record/model/model_generator.rb
155
155
  - lib/rails/generators/active_record/model/templates/migration.rb
156
156
  - lib/rails/generators/active_record/model/templates/model.rb
157
+ - lib/rails/generators/active_record/model/templates/module.rb
157
158
  - lib/rails/generators/active_record/observer/observer_generator.rb
158
159
  - lib/rails/generators/active_record/observer/templates/observer.rb
159
160
  - lib/rails/generators/active_record/session_migration/session_migration_generator.rb