activerecord 3.2.22.5 → 4.0.0.beta1

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 (162) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1024 -543
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +20 -29
  5. data/examples/performance.rb +1 -1
  6. data/lib/active_record.rb +55 -44
  7. data/lib/active_record/aggregations.rb +40 -34
  8. data/lib/active_record/associations.rb +204 -276
  9. data/lib/active_record/associations/alias_tracker.rb +1 -1
  10. data/lib/active_record/associations/association.rb +30 -35
  11. data/lib/active_record/associations/association_scope.rb +40 -40
  12. data/lib/active_record/associations/belongs_to_association.rb +15 -2
  13. data/lib/active_record/associations/builder/association.rb +81 -28
  14. data/lib/active_record/associations/builder/belongs_to.rb +35 -57
  15. data/lib/active_record/associations/builder/collection_association.rb +54 -40
  16. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +23 -41
  17. data/lib/active_record/associations/builder/has_many.rb +8 -64
  18. data/lib/active_record/associations/builder/has_one.rb +13 -50
  19. data/lib/active_record/associations/builder/singular_association.rb +13 -13
  20. data/lib/active_record/associations/collection_association.rb +92 -88
  21. data/lib/active_record/associations/collection_proxy.rb +913 -63
  22. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +12 -10
  23. data/lib/active_record/associations/has_many_association.rb +35 -9
  24. data/lib/active_record/associations/has_many_through_association.rb +24 -14
  25. data/lib/active_record/associations/has_one_association.rb +33 -13
  26. data/lib/active_record/associations/has_one_through_association.rb +1 -1
  27. data/lib/active_record/associations/join_dependency.rb +2 -2
  28. data/lib/active_record/associations/join_dependency/join_association.rb +17 -22
  29. data/lib/active_record/associations/join_dependency/join_part.rb +1 -1
  30. data/lib/active_record/associations/join_helper.rb +1 -11
  31. data/lib/active_record/associations/preloader.rb +14 -17
  32. data/lib/active_record/associations/preloader/association.rb +29 -33
  33. data/lib/active_record/associations/preloader/collection_association.rb +1 -1
  34. data/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +1 -1
  35. data/lib/active_record/associations/preloader/has_many_through.rb +1 -1
  36. data/lib/active_record/associations/preloader/has_one.rb +1 -1
  37. data/lib/active_record/associations/preloader/through_association.rb +13 -17
  38. data/lib/active_record/associations/singular_association.rb +11 -11
  39. data/lib/active_record/associations/through_association.rb +2 -2
  40. data/lib/active_record/attribute_assignment.rb +133 -153
  41. data/lib/active_record/attribute_methods.rb +196 -93
  42. data/lib/active_record/attribute_methods/before_type_cast.rb +44 -5
  43. data/lib/active_record/attribute_methods/dirty.rb +31 -28
  44. data/lib/active_record/attribute_methods/primary_key.rb +38 -30
  45. data/lib/active_record/attribute_methods/query.rb +5 -4
  46. data/lib/active_record/attribute_methods/read.rb +62 -91
  47. data/lib/active_record/attribute_methods/serialization.rb +97 -66
  48. data/lib/active_record/attribute_methods/time_zone_conversion.rb +39 -45
  49. data/lib/active_record/attribute_methods/write.rb +32 -39
  50. data/lib/active_record/autosave_association.rb +56 -70
  51. data/lib/active_record/base.rb +53 -450
  52. data/lib/active_record/callbacks.rb +53 -18
  53. data/lib/active_record/coders/yaml_column.rb +11 -9
  54. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +353 -197
  55. data/lib/active_record/connection_adapters/abstract/database_limits.rb +9 -0
  56. data/lib/active_record/connection_adapters/abstract/database_statements.rb +130 -131
  57. data/lib/active_record/connection_adapters/abstract/query_cache.rb +24 -19
  58. data/lib/active_record/connection_adapters/abstract/quoting.rb +23 -3
  59. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +101 -91
  60. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +59 -0
  61. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +225 -96
  62. data/lib/active_record/connection_adapters/abstract/transaction.rb +203 -0
  63. data/lib/active_record/connection_adapters/abstract_adapter.rb +99 -46
  64. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +114 -36
  65. data/lib/active_record/connection_adapters/column.rb +46 -24
  66. data/lib/active_record/connection_adapters/connection_specification.rb +96 -0
  67. data/lib/active_record/connection_adapters/mysql2_adapter.rb +16 -32
  68. data/lib/active_record/connection_adapters/mysql_adapter.rb +181 -64
  69. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +97 -0
  70. data/lib/active_record/connection_adapters/postgresql/cast.rb +132 -0
  71. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +242 -0
  72. data/lib/active_record/connection_adapters/postgresql/oid.rb +347 -0
  73. data/lib/active_record/connection_adapters/postgresql/quoting.rb +158 -0
  74. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +30 -0
  75. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +448 -0
  76. data/lib/active_record/connection_adapters/postgresql_adapter.rb +454 -885
  77. data/lib/active_record/connection_adapters/schema_cache.rb +48 -16
  78. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +574 -13
  79. data/lib/active_record/connection_handling.rb +98 -0
  80. data/lib/active_record/core.rb +428 -0
  81. data/lib/active_record/counter_cache.rb +106 -108
  82. data/lib/active_record/dynamic_matchers.rb +110 -63
  83. data/lib/active_record/errors.rb +25 -8
  84. data/lib/active_record/explain.rb +8 -58
  85. data/lib/active_record/explain_subscriber.rb +6 -3
  86. data/lib/active_record/fixture_set/file.rb +56 -0
  87. data/lib/active_record/fixtures.rb +146 -148
  88. data/lib/active_record/inheritance.rb +77 -59
  89. data/lib/active_record/integration.rb +5 -5
  90. data/lib/active_record/locale/en.yml +8 -1
  91. data/lib/active_record/locking/optimistic.rb +38 -42
  92. data/lib/active_record/locking/pessimistic.rb +4 -4
  93. data/lib/active_record/log_subscriber.rb +19 -9
  94. data/lib/active_record/migration.rb +318 -153
  95. data/lib/active_record/migration/command_recorder.rb +90 -31
  96. data/lib/active_record/migration/join_table.rb +15 -0
  97. data/lib/active_record/model_schema.rb +69 -92
  98. data/lib/active_record/nested_attributes.rb +113 -148
  99. data/lib/active_record/null_relation.rb +65 -0
  100. data/lib/active_record/persistence.rb +188 -97
  101. data/lib/active_record/query_cache.rb +18 -36
  102. data/lib/active_record/querying.rb +19 -15
  103. data/lib/active_record/railtie.rb +91 -36
  104. data/lib/active_record/railties/console_sandbox.rb +0 -2
  105. data/lib/active_record/railties/controller_runtime.rb +2 -2
  106. data/lib/active_record/railties/databases.rake +90 -309
  107. data/lib/active_record/railties/jdbcmysql_error.rb +1 -1
  108. data/lib/active_record/readonly_attributes.rb +7 -3
  109. data/lib/active_record/reflection.rb +72 -56
  110. data/lib/active_record/relation.rb +241 -157
  111. data/lib/active_record/relation/batches.rb +25 -22
  112. data/lib/active_record/relation/calculations.rb +143 -121
  113. data/lib/active_record/relation/delegation.rb +96 -18
  114. data/lib/active_record/relation/finder_methods.rb +117 -183
  115. data/lib/active_record/relation/merger.rb +133 -0
  116. data/lib/active_record/relation/predicate_builder.rb +90 -42
  117. data/lib/active_record/relation/query_methods.rb +666 -136
  118. data/lib/active_record/relation/spawn_methods.rb +43 -150
  119. data/lib/active_record/result.rb +33 -6
  120. data/lib/active_record/sanitization.rb +24 -50
  121. data/lib/active_record/schema.rb +19 -12
  122. data/lib/active_record/schema_dumper.rb +31 -39
  123. data/lib/active_record/schema_migration.rb +36 -0
  124. data/lib/active_record/scoping.rb +0 -124
  125. data/lib/active_record/scoping/default.rb +48 -45
  126. data/lib/active_record/scoping/named.rb +74 -103
  127. data/lib/active_record/serialization.rb +6 -2
  128. data/lib/active_record/serializers/xml_serializer.rb +9 -15
  129. data/lib/active_record/store.rb +119 -15
  130. data/lib/active_record/tasks/database_tasks.rb +158 -0
  131. data/lib/active_record/tasks/mysql_database_tasks.rb +138 -0
  132. data/lib/active_record/tasks/postgresql_database_tasks.rb +90 -0
  133. data/lib/active_record/tasks/sqlite_database_tasks.rb +51 -0
  134. data/lib/active_record/test_case.rb +61 -38
  135. data/lib/active_record/timestamp.rb +8 -9
  136. data/lib/active_record/transactions.rb +65 -51
  137. data/lib/active_record/validations.rb +17 -15
  138. data/lib/active_record/validations/associated.rb +20 -14
  139. data/lib/active_record/validations/presence.rb +65 -0
  140. data/lib/active_record/validations/uniqueness.rb +93 -52
  141. data/lib/active_record/version.rb +4 -4
  142. data/lib/rails/generators/active_record.rb +3 -5
  143. data/lib/rails/generators/active_record/migration/migration_generator.rb +37 -7
  144. data/lib/rails/generators/active_record/migration/templates/migration.rb +20 -15
  145. data/lib/rails/generators/active_record/model/model_generator.rb +4 -3
  146. data/lib/rails/generators/active_record/model/templates/model.rb +1 -6
  147. data/lib/rails/generators/active_record/model/templates/module.rb +1 -1
  148. metadata +53 -46
  149. data/lib/active_record/attribute_methods/deprecated_underscore_read.rb +0 -32
  150. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +0 -191
  151. data/lib/active_record/connection_adapters/sqlite_adapter.rb +0 -583
  152. data/lib/active_record/dynamic_finder_match.rb +0 -68
  153. data/lib/active_record/dynamic_scope_match.rb +0 -23
  154. data/lib/active_record/fixtures/file.rb +0 -65
  155. data/lib/active_record/identity_map.rb +0 -162
  156. data/lib/active_record/observer.rb +0 -121
  157. data/lib/active_record/session_store.rb +0 -360
  158. data/lib/rails/generators/active_record/migration.rb +0 -15
  159. data/lib/rails/generators/active_record/observer/observer_generator.rb +0 -15
  160. data/lib/rails/generators/active_record/observer/templates/observer.rb +0 -4
  161. data/lib/rails/generators/active_record/session_migration/session_migration_generator.rb +0 -25
  162. data/lib/rails/generators/active_record/session_migration/templates/migration.rb +0 -12
@@ -1,10 +1,12 @@
1
- require 'active_support/core_ext/object/inclusion'
2
-
3
1
  module ActiveRecord::Associations::Builder
4
2
  class BelongsTo < SingularAssociation #:nodoc:
5
- self.macro = :belongs_to
3
+ def macro
4
+ :belongs_to
5
+ end
6
6
 
7
- self.valid_options += [:foreign_type, :polymorphic, :touch]
7
+ def valid_options
8
+ super + [:foreign_type, :polymorphic, :touch]
9
+ end
8
10
 
9
11
  def constructable?
10
12
  !options[:polymorphic]
@@ -14,75 +16,51 @@ module ActiveRecord::Associations::Builder
14
16
  reflection = super
15
17
  add_counter_cache_callbacks(reflection) if options[:counter_cache]
16
18
  add_touch_callbacks(reflection) if options[:touch]
17
- configure_dependency
18
19
  reflection
19
20
  end
20
21
 
21
- private
22
+ def add_counter_cache_callbacks(reflection)
23
+ cache_column = reflection.counter_cache_column
22
24
 
23
- def add_counter_cache_callbacks(reflection)
24
- cache_column = reflection.counter_cache_column
25
- name = self.name
26
-
27
- method_name = "belongs_to_counter_cache_after_create_for_#{name}"
28
- mixin.redefine_method(method_name) do
29
- record = send(name)
30
- record.class.increment_counter(cache_column, record.id) unless record.nil?
25
+ mixin.class_eval <<-CODE, __FILE__, __LINE__ + 1
26
+ def belongs_to_counter_cache_after_create_for_#{name}
27
+ record = #{name}
28
+ record.class.increment_counter(:#{cache_column}, record.id) unless record.nil?
31
29
  end
32
- model.after_create(method_name)
33
-
34
- method_name = "belongs_to_counter_cache_before_destroy_for_#{name}"
35
- mixin.redefine_method(method_name) do
36
- record = send(name)
37
30
 
38
- if record && !self.destroyed?
39
- record.class.decrement_counter(cache_column, record.id)
31
+ def belongs_to_counter_cache_before_destroy_for_#{name}
32
+ unless marked_for_destruction?
33
+ record = #{name}
34
+ record.class.decrement_counter(:#{cache_column}, record.id) unless record.nil?
40
35
  end
41
36
  end
42
- model.before_destroy(method_name)
37
+ CODE
43
38
 
44
- model.send(:module_eval,
45
- "#{reflection.class_name}.send(:attr_readonly,\"#{cache_column}\".intern) if defined?(#{reflection.class_name}) && #{reflection.class_name}.respond_to?(:attr_readonly)", __FILE__, __LINE__
46
- )
47
- end
39
+ model.after_create "belongs_to_counter_cache_after_create_for_#{name}"
40
+ model.before_destroy "belongs_to_counter_cache_before_destroy_for_#{name}"
48
41
 
49
- def add_touch_callbacks(reflection)
50
- name = self.name
51
- method_name = "belongs_to_touch_after_save_or_destroy_for_#{name}"
52
- touch = options[:touch]
42
+ klass = reflection.class_name.safe_constantize
43
+ klass.attr_readonly cache_column if klass && klass.respond_to?(:attr_readonly)
44
+ end
53
45
 
54
- mixin.redefine_method(method_name) do
55
- record = send(name)
46
+ def add_touch_callbacks(reflection)
47
+ mixin.class_eval <<-CODE, __FILE__, __LINE__ + 1
48
+ def belongs_to_touch_after_save_or_destroy_for_#{name}
49
+ record = #{name}
56
50
 
57
51
  unless record.nil?
58
- if touch == true
59
- record.touch
60
- else
61
- record.touch(touch)
62
- end
52
+ record.touch #{options[:touch].inspect if options[:touch] != true}
63
53
  end
64
54
  end
55
+ CODE
65
56
 
66
- model.after_save(method_name)
67
- model.after_touch(method_name)
68
- model.after_destroy(method_name)
69
- end
70
-
71
- def configure_dependency
72
- if options[:dependent]
73
- unless options[:dependent].in?([:destroy, :delete])
74
- raise ArgumentError, "The :dependent option expects either :destroy or :delete (#{options[:dependent].inspect})"
75
- end
57
+ model.after_save "belongs_to_touch_after_save_or_destroy_for_#{name}"
58
+ model.after_touch "belongs_to_touch_after_save_or_destroy_for_#{name}"
59
+ model.after_destroy "belongs_to_touch_after_save_or_destroy_for_#{name}"
60
+ end
76
61
 
77
- method_name = "belongs_to_dependent_#{options[:dependent]}_for_#{name}"
78
- model.send(:class_eval, <<-eoruby, __FILE__, __LINE__ + 1)
79
- def #{method_name}
80
- association = #{name}
81
- association.#{options[:dependent]} if association
82
- end
83
- eoruby
84
- model.after_destroy method_name
85
- end
86
- end
62
+ def valid_dependent_options
63
+ [:destroy, :delete]
64
+ end
87
65
  end
88
66
  end
@@ -1,24 +1,24 @@
1
+ require 'active_record/associations'
2
+
1
3
  module ActiveRecord::Associations::Builder
2
4
  class CollectionAssociation < Association #:nodoc:
3
- CALLBACKS = [:before_add, :after_add, :before_remove, :after_remove]
4
-
5
- self.valid_options += [
6
- :table_name, :order, :group, :having, :limit, :offset, :uniq, :finder_sql,
7
- :counter_sql, :before_add, :after_add, :before_remove, :after_remove
8
- ]
9
5
 
10
- attr_reader :block_extension
6
+ CALLBACKS = [:before_add, :after_add, :before_remove, :after_remove]
11
7
 
12
- def self.build(model, name, options, &extension)
13
- new(model, name, options, &extension).build
8
+ def valid_options
9
+ super + [:table_name, :finder_sql, :counter_sql, :before_add,
10
+ :after_add, :before_remove, :after_remove, :extend]
14
11
  end
15
12
 
16
- def initialize(model, name, options, &extension)
17
- super(model, name, options)
13
+ attr_reader :block_extension, :extension_module
14
+
15
+ def initialize(*args, &extension)
16
+ super(*args)
18
17
  @block_extension = extension
19
18
  end
20
19
 
21
20
  def build
21
+ show_deprecation_warnings
22
22
  wrap_block_extension
23
23
  reflection = super
24
24
  CALLBACKS.each { |callback_name| define_callback(callback_name) }
@@ -29,47 +29,61 @@ module ActiveRecord::Associations::Builder
29
29
  true
30
30
  end
31
31
 
32
- private
32
+ def show_deprecation_warnings
33
+ [:finder_sql, :counter_sql].each do |name|
34
+ if options.include? name
35
+ ActiveSupport::Deprecation.warn("The :#{name} association option is deprecated. Please find an alternative (such as using scopes).")
36
+ end
37
+ end
38
+ end
39
+
40
+ def wrap_block_extension
41
+ if block_extension
42
+ @extension_module = mod = Module.new(&block_extension)
43
+ silence_warnings do
44
+ model.parent.const_set(extension_module_name, mod)
45
+ end
33
46
 
34
- def wrap_block_extension
35
- options[:extend] = Array.wrap(options[:extend])
47
+ prev_scope = @scope
36
48
 
37
- if block_extension
38
- silence_warnings do
39
- model.parent.const_set(extension_module_name, Module.new(&block_extension))
40
- end
41
- options[:extend].push("#{model.parent}::#{extension_module_name}".constantize)
49
+ if prev_scope
50
+ @scope = proc { |owner| instance_exec(owner, &prev_scope).extending(mod) }
51
+ else
52
+ @scope = proc { extending(mod) }
42
53
  end
43
54
  end
55
+ end
44
56
 
45
- def extension_module_name
46
- @extension_module_name ||= "#{model.to_s.demodulize}#{name.to_s.camelize}AssociationExtension"
47
- end
57
+ def extension_module_name
58
+ @extension_module_name ||= "#{model.name.demodulize}#{name.to_s.camelize}AssociationExtension"
59
+ end
48
60
 
49
- def define_callback(callback_name)
50
- full_callback_name = "#{callback_name}_for_#{name}"
61
+ def define_callback(callback_name)
62
+ full_callback_name = "#{callback_name}_for_#{name}"
51
63
 
52
- # TODO : why do i need method_defined? I think its because of the inheritance chain
53
- model.class_attribute full_callback_name.to_sym unless model.method_defined?(full_callback_name)
54
- model.send("#{full_callback_name}=", Array.wrap(options[callback_name.to_sym]))
55
- end
64
+ # TODO : why do i need method_defined? I think its because of the inheritance chain
65
+ model.class_attribute full_callback_name.to_sym unless model.method_defined?(full_callback_name)
66
+ model.send("#{full_callback_name}=", Array(options[callback_name.to_sym]))
67
+ end
56
68
 
57
- def define_readers
58
- super
69
+ def define_readers
70
+ super
59
71
 
60
- name = self.name
61
- mixin.redefine_method("#{name.to_s.singularize}_ids") do
62
- association(name).ids_reader
72
+ mixin.class_eval <<-CODE, __FILE__, __LINE__ + 1
73
+ def #{name.to_s.singularize}_ids
74
+ association(:#{name}).ids_reader
63
75
  end
64
- end
76
+ CODE
77
+ end
65
78
 
66
- def define_writers
67
- super
79
+ def define_writers
80
+ super
68
81
 
69
- name = self.name
70
- mixin.redefine_method("#{name.to_s.singularize}_ids=") do |ids|
71
- association(name).ids_writer(ids)
82
+ mixin.class_eval <<-CODE, __FILE__, __LINE__ + 1
83
+ def #{name.to_s.singularize}_ids=(ids)
84
+ association(:#{name}).ids_writer(ids)
72
85
  end
73
- end
86
+ CODE
87
+ end
74
88
  end
75
89
  end
@@ -1,57 +1,39 @@
1
1
  module ActiveRecord::Associations::Builder
2
2
  class HasAndBelongsToMany < CollectionAssociation #:nodoc:
3
- self.macro = :has_and_belongs_to_many
3
+ def macro
4
+ :has_and_belongs_to_many
5
+ end
4
6
 
5
- self.valid_options += [:join_table, :association_foreign_key, :delete_sql, :insert_sql]
7
+ def valid_options
8
+ super + [:join_table, :association_foreign_key, :delete_sql, :insert_sql]
9
+ end
6
10
 
7
11
  def build
8
12
  reflection = super
9
- check_validity(reflection)
10
13
  define_destroy_hook
11
14
  reflection
12
15
  end
13
16
 
14
- private
17
+ def show_deprecation_warnings
18
+ super
15
19
 
16
- def define_destroy_hook
17
- name = self.name
18
- model.send(:include, Module.new {
19
- class_eval <<-RUBY, __FILE__, __LINE__ + 1
20
- def destroy_associations
21
- association(#{name.to_sym.inspect}).delete_all_on_destroy
22
- super
23
- end
24
- RUBY
25
- })
26
- end
27
-
28
- # TODO: These checks should probably be moved into the Reflection, and we should not be
29
- # redefining the options[:join_table] value - instead we should define a
30
- # reflection.join_table method.
31
- def check_validity(reflection)
32
- if reflection.association_foreign_key == reflection.foreign_key
33
- raise ActiveRecord::HasAndBelongsToManyAssociationForeignKeyNeeded.new(reflection)
20
+ [:delete_sql, :insert_sql].each do |name|
21
+ if options.include? name
22
+ ActiveSupport::Deprecation.warn("The :#{name} association option is deprecated. Please find an alternative (such as using has_many :through).")
34
23
  end
35
-
36
- reflection.options[:join_table] ||= join_table_name(
37
- model.send(:undecorated_table_name, model.to_s),
38
- model.send(:undecorated_table_name, reflection.class_name)
39
- )
40
24
  end
25
+ end
41
26
 
42
- # Generates a join table name from two provided table names.
43
- # The names in the join table names end up in lexicographic order.
44
- #
45
- # join_table_name("members", "clubs") # => "clubs_members"
46
- # join_table_name("members", "special_clubs") # => "members_special_clubs"
47
- def join_table_name(first_table_name, second_table_name)
48
- if first_table_name < second_table_name
49
- join_table = "#{first_table_name}_#{second_table_name}"
50
- else
51
- join_table = "#{second_table_name}_#{first_table_name}"
52
- end
53
-
54
- model.table_name_prefix + join_table + model.table_name_suffix
55
- end
27
+ def define_destroy_hook
28
+ name = self.name
29
+ model.send(:include, Module.new {
30
+ class_eval <<-RUBY, __FILE__, __LINE__ + 1
31
+ def destroy_associations
32
+ association(:#{name}).delete_all
33
+ super
34
+ end
35
+ RUBY
36
+ })
37
+ end
56
38
  end
57
39
  end
@@ -1,71 +1,15 @@
1
- require 'active_support/core_ext/object/inclusion'
2
-
3
1
  module ActiveRecord::Associations::Builder
4
2
  class HasMany < CollectionAssociation #:nodoc:
5
- self.macro = :has_many
6
-
7
- self.valid_options += [:primary_key, :dependent, :as, :through, :source, :source_type, :inverse_of]
8
-
9
- def build
10
- reflection = super
11
- configure_dependency
12
- reflection
3
+ def macro
4
+ :has_many
13
5
  end
14
6
 
15
- private
16
-
17
- def configure_dependency
18
- if options[:dependent]
19
- unless options[:dependent].in?([:destroy, :delete_all, :nullify, :restrict])
20
- raise ArgumentError, "The :dependent option expects either :destroy, :delete_all, " \
21
- ":nullify or :restrict (#{options[:dependent].inspect})"
22
- end
23
-
24
- send("define_#{options[:dependent]}_dependency_method")
25
- model.before_destroy dependency_method_name
26
- end
27
- end
28
-
29
- def define_destroy_dependency_method
30
- name = self.name
31
- mixin.redefine_method(dependency_method_name) do
32
- send(name).each do |o|
33
- # No point in executing the counter update since we're going to destroy the parent anyway
34
- counter_method = ('belongs_to_counter_cache_before_destroy_for_' + self.class.name.downcase).to_sym
35
- if o.respond_to?(counter_method)
36
- class << o
37
- self
38
- end.send(:define_method, counter_method, Proc.new {})
39
- end
40
- end
41
-
42
- send(name).delete_all
43
- end
44
- end
45
-
46
- def define_delete_all_dependency_method
47
- name = self.name
48
- mixin.redefine_method(dependency_method_name) do
49
- association(name).delete_all_on_destroy
50
- end
51
- end
52
-
53
- def define_nullify_dependency_method
54
- name = self.name
55
- mixin.redefine_method(dependency_method_name) do
56
- send(name).delete_all
57
- end
58
- end
59
-
60
- def define_restrict_dependency_method
61
- name = self.name
62
- mixin.redefine_method(dependency_method_name) do
63
- raise ActiveRecord::DeleteRestrictionError.new(name) unless send(name).empty?
64
- end
65
- end
7
+ def valid_options
8
+ super + [:primary_key, :dependent, :as, :through, :source, :source_type, :inverse_of, :counter_cache]
9
+ end
66
10
 
67
- def dependency_method_name
68
- "has_many_dependent_for_#{name}"
69
- end
11
+ def valid_dependent_options
12
+ [:destroy, :delete_all, :nullify, :restrict, :restrict_with_error, :restrict_with_exception]
13
+ end
70
14
  end
71
15
  end
@@ -1,62 +1,25 @@
1
- require 'active_support/core_ext/object/inclusion'
2
-
3
1
  module ActiveRecord::Associations::Builder
4
2
  class HasOne < SingularAssociation #:nodoc:
5
- self.macro = :has_one
6
-
7
- self.valid_options += [:order, :as]
3
+ def macro
4
+ :has_one
5
+ end
8
6
 
9
- class_attribute :through_options
10
- self.through_options = [:through, :source, :source_type]
7
+ def valid_options
8
+ valid = super + [:order, :as]
9
+ valid += [:through, :source, :source_type] if options[:through]
10
+ valid
11
+ end
11
12
 
12
13
  def constructable?
13
14
  !options[:through]
14
15
  end
15
16
 
16
- def build
17
- reflection = super
18
- configure_dependency unless options[:through]
19
- reflection
17
+ def configure_dependency
18
+ super unless options[:through]
20
19
  end
21
20
 
22
- private
23
-
24
- def validate_options
25
- valid_options = self.class.valid_options
26
- valid_options += self.class.through_options if options[:through]
27
- options.assert_valid_keys(valid_options)
28
- end
29
-
30
- def configure_dependency
31
- if options[:dependent]
32
- unless options[:dependent].in?([:destroy, :delete, :nullify, :restrict])
33
- raise ArgumentError, "The :dependent option expects either :destroy, :delete, " \
34
- ":nullify or :restrict (#{options[:dependent].inspect})"
35
- end
36
-
37
- send("define_#{options[:dependent]}_dependency_method")
38
- model.before_destroy dependency_method_name
39
- end
40
- end
41
-
42
- def dependency_method_name
43
- "has_one_dependent_#{options[:dependent]}_for_#{name}"
44
- end
45
-
46
- def define_destroy_dependency_method
47
- name = self.name
48
- mixin.redefine_method(dependency_method_name) do
49
- association(name).delete
50
- end
51
- end
52
- alias :define_delete_dependency_method :define_destroy_dependency_method
53
- alias :define_nullify_dependency_method :define_destroy_dependency_method
54
-
55
- def define_restrict_dependency_method
56
- name = self.name
57
- mixin.redefine_method(dependency_method_name) do
58
- raise ActiveRecord::DeleteRestrictionError.new(name) unless send(name).nil?
59
- end
60
- end
21
+ def valid_dependent_options
22
+ [:destroy, :delete, :nullify, :restrict, :restrict_with_error, :restrict_with_exception]
23
+ end
61
24
  end
62
25
  end