diff options
Diffstat (limited to 'activerecord')
14 files changed, 79 insertions, 39 deletions
diff --git a/activerecord/lib/active_record/associations/builder/association.rb b/activerecord/lib/active_record/associations/builder/association.rb index c3fa4a05fd..2059d8acdf 100644 --- a/activerecord/lib/active_record/associations/builder/association.rb +++ b/activerecord/lib/active_record/associations/builder/association.rb @@ -74,7 +74,9 @@ module ActiveRecord::Associations::Builder if dependent_restrict_raises? raise ActiveRecord::DeleteRestrictionError.new(name) else - errors.add(:base, :restrict_dependent_destroy, :model => name.to_s.singularize) + key = association(name).reflection.macro == :has_one ? "one" : "many" + errors.add(:base, :"restrict_dependent_destroy.#{key}", + :record => self.class.human_attribute_name(name).downcase) return false end end diff --git a/activerecord/lib/active_record/associations/collection_proxy.rb b/activerecord/lib/active_record/associations/collection_proxy.rb index ba01df00e3..5eda0387c4 100644 --- a/activerecord/lib/active_record/associations/collection_proxy.rb +++ b/activerecord/lib/active_record/associations/collection_proxy.rb @@ -82,9 +82,8 @@ module ActiveRecord proxy_association.send :add_to_target, r yield(r) if block_given? end - end - if target.respond_to?(method) || (!proxy_association.klass.respond_to?(method) && Class.respond_to?(method)) + elsif target.respond_to?(method) || (!proxy_association.klass.respond_to?(method) && Class.respond_to?(method)) if load_target if target.respond_to?(method) target.send(method, *args, &block) diff --git a/activerecord/lib/active_record/coders/yaml_column.rb b/activerecord/lib/active_record/coders/yaml_column.rb index fb59d9fb07..77af540c3e 100644 --- a/activerecord/lib/active_record/coders/yaml_column.rb +++ b/activerecord/lib/active_record/coders/yaml_column.rb @@ -15,7 +15,7 @@ module ActiveRecord end def dump(obj) - YAML.dump obj + YAML.dump(obj) unless obj.nil? end def load(yaml) diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index 1d8e5d813a..039f6e1bd1 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -455,14 +455,14 @@ module ActiveRecord # Escapes binary strings for bytea input to the database. def escape_bytea(value) - @connection.escape_bytea(value) if value + PGconn.escape_bytea(value) if value end # Unescapes bytea output from a database to the binary string it represents. # NOTE: This is NOT an inverse of escape_bytea! This is only to be used # on escaped binary output from database drive. def unescape_bytea(value) - @connection.unescape_bytea(value) if value + PGconn.unescape_bytea(value) if value end # Quotes PostgreSQL-specific data types for SQL input. diff --git a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb index 0520fc8b62..6391ea3800 100644 --- a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb @@ -6,26 +6,11 @@ module ActiveRecord module ConnectionAdapters #:nodoc: class SQLiteColumn < Column #:nodoc: class << self - def string_to_binary(value) - value.gsub(/\0|\%/n) do |b| - case b - when "\0" then "%00" - when "%" then "%25" - end - end - end - def binary_to_string(value) if value.encoding != Encoding::ASCII_8BIT value = value.force_encoding(Encoding::ASCII_8BIT) end - - value.gsub(/%00|%25/n) do |b| - case b - when "%00" then "\0" - when "%25" then "%" - end - end + value end end end diff --git a/activerecord/lib/active_record/locale/en.yml b/activerecord/lib/active_record/locale/en.yml index 8892f7ef2f..896132d566 100644 --- a/activerecord/lib/active_record/locale/en.yml +++ b/activerecord/lib/active_record/locale/en.yml @@ -10,7 +10,9 @@ en: messages: taken: "has already been taken" record_invalid: "Validation failed: %{errors}" - restrict_dependent_destroy: "Cannot delete record because dependent %{model} exists" + restrict_dependent_destroy: + one: "Cannot delete record because a dependent %{record} exists" + many: "Cannot delete record because dependent %{record} exist" # Append your own errors here or at the model/attributes scope. # You can define own errors for models or model attributes. diff --git a/activerecord/lib/active_record/locking/optimistic.rb b/activerecord/lib/active_record/locking/optimistic.rb index e643c0d437..4d73cdd37a 100644 --- a/activerecord/lib/active_record/locking/optimistic.rb +++ b/activerecord/lib/active_record/locking/optimistic.rb @@ -40,11 +40,13 @@ module ActiveRecord # This locking mechanism will function inside a single Ruby process. To make it work across all # web requests, the recommended approach is to add +lock_version+ as a hidden field to your form. # - # You must ensure that your database schema defaults the +lock_version+ column to 0. - # # This behavior can be turned off by setting <tt>ActiveRecord::Base.lock_optimistically = false</tt>. - # To override the name of the +lock_version+ column, invoke the <tt>set_locking_column</tt> method. - # This method uses the same syntax as <tt>set_table_name</tt> + # To override the name of the +lock_version+ column, set the <tt>locking_column</tt> class attribute: + # + # class Person < ActiveRecord::Base + # self.locking_column = :lock_person + # end + # module Optimistic extend ActiveSupport::Concern diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index 6a28d7b155..b6d762c2e2 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -201,26 +201,26 @@ module ActiveRecord # # The returned NullRelation inherits from Relation and implements the # Null Object pattern so it is an object with defined null behavior: - # it always returns an empty array of records and avoids any database query. + # it always returns an empty array of records and does not query the database. # # Any subsequent condition chained to the returned relation will continue # generating an empty relation and will not fire any query to the database. # - # Used in cases where is needed a method or a scope that could return zero - # results but the response has to be chainable. + # This is useful in scenarios where you need a chainable response to a method + # or a scope that could return zero results. # # For example: # # @posts = current_user.visible_posts.where(:name => params[:name]) - # # => the visible_post method response has to be a chainable Relation + # # => the visible_posts method is expected to return a chainable Relation # # def visible_posts # case role - # if 'Country Manager' + # when 'Country Manager' # Post.where(:country => country) - # if 'Reviewer' + # when 'Reviewer' # Post.published - # if 'Bad User' + # when 'Bad User' # Post.none # => returning [] instead breaks the previous code # end # end diff --git a/activerecord/test/assets/test.txt b/activerecord/test/assets/test.txt new file mode 100644 index 0000000000..6754f0612e --- /dev/null +++ b/activerecord/test/assets/test.txt @@ -0,0 +1 @@ +%00 diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb index ab1e821aab..3967009c82 100644 --- a/activerecord/test/cases/associations/has_many_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_associations_test.rb @@ -738,6 +738,18 @@ class HasManyAssociationsTest < ActiveRecord::TestCase assert_equal number_of_clients + 1, companies(:first_firm).clients_of_firm.size end + def test_find_or_initialize_returns_the_instantiated_object + client = companies(:first_firm).clients_of_firm.find_or_initialize_by_name("name" => "Another Client") + assert_equal client, companies(:first_firm).clients_of_firm[-1] + end + + def test_find_or_initialize_only_instantiates_a_single_object + number_of_clients = Client.count + companies(:first_firm).clients_of_firm.find_or_initialize_by_name("name" => "Another Client").save! + companies(:first_firm).save! + assert_equal number_of_clients+1, Client.count + end + def test_find_or_create_with_hash post = authors(:david).posts.find_or_create_by_title(:title => 'Yet another post', :body => 'somebody') assert_equal post, authors(:david).posts.find_or_create_by_title(:title => 'Yet another post', :body => 'somebody') @@ -1171,7 +1183,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase assert !firm.errors.empty? - assert_equal "Cannot delete record because dependent company exists", firm.errors[:base].first + assert_equal "Cannot delete record because dependent companies exist", firm.errors[:base].first assert RestrictedFirm.exists?(:name => 'restrict') assert firm.companies.exists?(:name => 'child') ensure diff --git a/activerecord/test/cases/associations/has_one_associations_test.rb b/activerecord/test/cases/associations/has_one_associations_test.rb index 37be6a279d..246877bbed 100644 --- a/activerecord/test/cases/associations/has_one_associations_test.rb +++ b/activerecord/test/cases/associations/has_one_associations_test.rb @@ -184,13 +184,37 @@ class HasOneAssociationsTest < ActiveRecord::TestCase firm.destroy assert !firm.errors.empty? - assert_equal "Cannot delete record because dependent account exists", firm.errors[:base].first + assert_equal "Cannot delete record because a dependent account exists", firm.errors[:base].first assert RestrictedFirm.exists?(:name => 'restrict') assert firm.account.present? ensure ActiveRecord::Base.dependent_restrict_raises = option_before end + def test_dependence_with_restrict_with_dependent_restrict_raises_config_set_to_false_and_attribute_name + old_backend = I18n.backend + I18n.backend = I18n::Backend::Simple.new + I18n.backend.store_translations 'en', :activerecord => {:attributes => {:restricted_firm => {:account => "account model"}}} + + option_before = ActiveRecord::Base.dependent_restrict_raises + ActiveRecord::Base.dependent_restrict_raises = false + + firm = RestrictedFirm.create!(:name => 'restrict') + firm.create_account(:credit_limit => 10) + + assert_not_nil firm.account + + firm.destroy + + assert !firm.errors.empty? + assert_equal "Cannot delete record because a dependent account model exists", firm.errors[:base].first + assert RestrictedFirm.exists?(:name => 'restrict') + assert firm.account.present? + ensure + ActiveRecord::Base.dependent_restrict_raises = option_before + I18n.backend = old_backend + end + def test_successful_build_association firm = Firm.new("name" => "GlobalMegaCorp") firm.save diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb index 6c3e4fc6d0..d70525b57d 100644 --- a/activerecord/test/cases/base_test.rb +++ b/activerecord/test/cases/base_test.rb @@ -1301,11 +1301,24 @@ class BasicsTest < ActiveRecord::TestCase assert_equal(myobj, topic.content) end - def test_nil_serialized_attribute_with_class_constraint + def test_nil_serialized_attribute_without_class_constraint topic = Topic.new assert_nil topic.content end + def test_nil_not_serialized_without_class_constraint + assert Topic.new(:content => nil).save + assert_equal 1, Topic.where(:content => nil).count + end + + def test_nil_not_serialized_with_class_constraint + Topic.serialize :content, Hash + assert Topic.new(:content => nil).save + assert_equal 1, Topic.where(:content => nil).count + ensure + Topic.serialize(:content) + end + def test_should_raise_exception_on_serialized_attribute_with_type_mismatch myobj = MyObject.new('value1', 'value2') topic = Topic.new(:content => myobj) diff --git a/activerecord/test/cases/binary_test.rb b/activerecord/test/cases/binary_test.rb index f97aade311..25d2896ab0 100644 --- a/activerecord/test/cases/binary_test.rb +++ b/activerecord/test/cases/binary_test.rb @@ -8,7 +8,7 @@ unless current_adapter?(:SybaseAdapter, :DB2Adapter, :FirebirdAdapter) require 'models/binary' class BinaryTest < ActiveRecord::TestCase - FIXTURES = %w(flowers.jpg example.log) + FIXTURES = %w(flowers.jpg example.log test.txt) def test_mixed_encoding str = "\x80" diff --git a/activerecord/test/cases/helper.rb b/activerecord/test/cases/helper.rb index 359cabd016..734d017b6e 100644 --- a/activerecord/test/cases/helper.rb +++ b/activerecord/test/cases/helper.rb @@ -22,7 +22,7 @@ ActiveSupport::Deprecation.debug = true # Enable Identity Map only when ENV['IM'] is set to "true" ActiveRecord::IdentityMap.enabled = (ENV['IM'] == "true") -# Avoid deprecation warning setting dependent_restric_raises to false. The default is true +# Avoid deprecation warning setting dependent_restrict_raises to false. The default is true ActiveRecord::Base.dependent_restrict_raises = false # Connect to the database |