mirror of
https://github.com/github/rails.git
synced 2026-04-26 03:00:59 -04:00
Merge commit 'rails/master'
This commit is contained in:
@@ -1,5 +1,9 @@
|
||||
*Edge*
|
||||
|
||||
* Added :primary_key option to belongs_to associations. #765 [Szymon Nowak, Philip Hallstrom, Noel Rocha]
|
||||
# employees.company_name references companies.name
|
||||
Employee.belongs_to :company, :primary_key => 'name', :foreign_key => 'company_name'
|
||||
|
||||
* Implement #many? for NamedScope and AssociationCollection using #size. #1500 [Chris Kampmeier]
|
||||
|
||||
* Added :touch option to belongs_to associations that will touch the parent record when the current record is saved or destroyed [DHH]
|
||||
|
||||
@@ -963,6 +963,8 @@ module ActiveRecord
|
||||
# of the association with an "_id" suffix. So a class that defines a <tt>belongs_to :person</tt> association will use
|
||||
# "person_id" as the default <tt>:foreign_key</tt>. Similarly, <tt>belongs_to :favorite_person, :class_name => "Person"</tt>
|
||||
# will use a foreign key of "favorite_person_id".
|
||||
# [:primary_key]
|
||||
# Specify the method that returns the primary key of associated object used for the association. By default this is id.
|
||||
# [:dependent]
|
||||
# If set to <tt>:destroy</tt>, the associated object is destroyed when this object is. If set to
|
||||
# <tt>:delete</tt>, the associated object is deleted *without* calling its destroy method. This option should not be specified when
|
||||
@@ -993,6 +995,7 @@ module ActiveRecord
|
||||
#
|
||||
# Option examples:
|
||||
# belongs_to :firm, :foreign_key => "client_of"
|
||||
# belongs_to :person, :primary_key => "name", :foreign_key => "person_name"
|
||||
# belongs_to :author, :class_name => "Person", :foreign_key => "author_id"
|
||||
# belongs_to :valid_coupon, :class_name => "Coupon", :foreign_key => "coupon_id",
|
||||
# :conditions => 'discounts > #{payments_count}'
|
||||
@@ -1328,14 +1331,14 @@ module ActiveRecord
|
||||
method_name = "belongs_to_counter_cache_after_create_for_#{reflection.name}".to_sym
|
||||
define_method(method_name) do
|
||||
association = send(reflection.name)
|
||||
association.class.increment_counter(cache_column, send(reflection.primary_key_name)) unless association.nil?
|
||||
association.class.increment_counter(cache_column, association.id) unless association.nil?
|
||||
end
|
||||
after_create(method_name)
|
||||
|
||||
method_name = "belongs_to_counter_cache_before_destroy_for_#{reflection.name}".to_sym
|
||||
define_method(method_name) do
|
||||
association = send(reflection.name)
|
||||
association.class.decrement_counter(cache_column, send(reflection.primary_key_name)) unless association.nil?
|
||||
association.class.decrement_counter(cache_column, association.id) unless association.nil?
|
||||
end
|
||||
before_destroy(method_name)
|
||||
|
||||
@@ -1527,7 +1530,7 @@ module ActiveRecord
|
||||
|
||||
mattr_accessor :valid_keys_for_belongs_to_association
|
||||
@@valid_keys_for_belongs_to_association = [
|
||||
:class_name, :foreign_key, :foreign_type, :remote, :select, :conditions,
|
||||
:class_name, :primary_key, :foreign_key, :foreign_type, :remote, :select, :conditions,
|
||||
:include, :dependent, :counter_cache, :extend, :polymorphic, :readonly,
|
||||
:validate, :touch, :inverse_of
|
||||
]
|
||||
|
||||
@@ -14,7 +14,7 @@ module ActiveRecord
|
||||
|
||||
if record.nil?
|
||||
if counter_cache_name && !@owner.new_record?
|
||||
@reflection.klass.decrement_counter(counter_cache_name, @owner[@reflection.primary_key_name]) if @owner[@reflection.primary_key_name]
|
||||
@reflection.klass.decrement_counter(counter_cache_name, previous_record_id) if @owner[@reflection.primary_key_name]
|
||||
end
|
||||
|
||||
@target = @owner[@reflection.primary_key_name] = nil
|
||||
@@ -27,7 +27,7 @@ module ActiveRecord
|
||||
end
|
||||
|
||||
@target = (AssociationProxy === record ? record.target : record)
|
||||
@owner[@reflection.primary_key_name] = record.id unless record.new_record?
|
||||
@owner[@reflection.primary_key_name] = record_id(record) unless record.new_record?
|
||||
@updated = true
|
||||
end
|
||||
|
||||
@@ -43,13 +43,18 @@ module ActiveRecord
|
||||
|
||||
private
|
||||
def find_target
|
||||
the_target = @reflection.klass.find(
|
||||
find_method = if @reflection.options[:primary_key]
|
||||
"find_by_#{@reflection.options[:primary_key]}"
|
||||
else
|
||||
"find"
|
||||
end
|
||||
the_target = @reflection.klass.send(find_method,
|
||||
@owner[@reflection.primary_key_name],
|
||||
:select => @reflection.options[:select],
|
||||
:conditions => conditions,
|
||||
:include => @reflection.options[:include],
|
||||
:readonly => @reflection.options[:readonly]
|
||||
)
|
||||
) if @owner[@reflection.primary_key_name]
|
||||
set_inverse_instance(the_target, @owner)
|
||||
the_target
|
||||
end
|
||||
@@ -63,6 +68,19 @@ module ActiveRecord
|
||||
def we_can_set_the_inverse_on_this?(record)
|
||||
@reflection.has_inverse? && @reflection.inverse_of.macro == :has_one
|
||||
end
|
||||
|
||||
def record_id(record)
|
||||
record.send(@reflection.options[:primary_key] || :id)
|
||||
end
|
||||
|
||||
def previous_record_id
|
||||
@previous_record_id ||= if @reflection.options[:primary_key]
|
||||
previous_record = @owner.send(@reflection.name)
|
||||
previous_record.nil? ? nil : previous_record.id
|
||||
else
|
||||
@owner[@reflection.primary_key_name]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -7,7 +7,7 @@ module ActiveRecord
|
||||
else
|
||||
@target = (AssociationProxy === record ? record.target : record)
|
||||
|
||||
@owner[@reflection.primary_key_name] = record.id
|
||||
@owner[@reflection.primary_key_name] = record_id(record)
|
||||
@owner[@reflection.options[:foreign_type]] = record.class.base_class.name.to_s
|
||||
|
||||
@updated = true
|
||||
@@ -41,6 +41,10 @@ module ActiveRecord
|
||||
!@owner[@reflection.primary_key_name].nil?
|
||||
end
|
||||
|
||||
def record_id(record)
|
||||
record.send(@reflection.options[:primary_key] || :id)
|
||||
end
|
||||
|
||||
def association_class
|
||||
@owner[@reflection.options[:foreign_type]] ? @owner[@reflection.options[:foreign_type]].constantize : nil
|
||||
end
|
||||
|
||||
@@ -339,7 +339,8 @@ module ActiveRecord
|
||||
association.save(!autosave) if association.new_record? || autosave
|
||||
|
||||
if association.updated?
|
||||
self[reflection.primary_key_name] = association.id
|
||||
association_id = association.send(reflection.options[:primary_key] || :id)
|
||||
self[reflection.primary_key_name] = association_id
|
||||
# TODO: Removing this code doesn't seem to matter…
|
||||
if reflection.options[:polymorphic]
|
||||
self[reflection.options[:foreign_type]] = association.class.base_class.name.to_s
|
||||
|
||||
@@ -14,6 +14,7 @@ require 'models/tagging'
|
||||
require 'models/comment'
|
||||
require 'models/sponsor'
|
||||
require 'models/member'
|
||||
require 'models/essay'
|
||||
|
||||
class BelongsToAssociationsTest < ActiveRecord::TestCase
|
||||
fixtures :accounts, :companies, :developers, :projects, :topics,
|
||||
@@ -25,6 +26,11 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
|
||||
assert !Client.find(3).firm.nil?, "Microsoft should have a firm"
|
||||
end
|
||||
|
||||
def test_belongs_to_with_primary_key
|
||||
client = Client.create(:name => "Primary key client", :firm_name => companies(:first_firm).name)
|
||||
assert_equal companies(:first_firm).name, client.firm_with_primary_key.name
|
||||
end
|
||||
|
||||
def test_proxy_assignment
|
||||
account = Account.find(1)
|
||||
assert_nothing_raised { account.firm = account.firm }
|
||||
@@ -47,6 +53,13 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
|
||||
assert_equal apple.id, citibank.firm_id
|
||||
end
|
||||
|
||||
def test_natural_assignment_with_primary_key
|
||||
apple = Firm.create("name" => "Apple")
|
||||
citibank = Client.create("name" => "Primary key client")
|
||||
citibank.firm_with_primary_key = apple
|
||||
assert_equal apple.name, citibank.firm_name
|
||||
end
|
||||
|
||||
def test_no_unexpected_aliasing
|
||||
first_firm = companies(:first_firm)
|
||||
another_firm = companies(:another_firm)
|
||||
@@ -69,6 +82,15 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
|
||||
assert_equal apple, citibank.firm
|
||||
end
|
||||
|
||||
def test_creating_the_belonging_object_with_primary_key
|
||||
client = Client.create(:name => "Primary key client")
|
||||
apple = client.create_firm_with_primary_key("name" => "Apple")
|
||||
assert_equal apple, client.firm_with_primary_key
|
||||
client.save
|
||||
client.reload
|
||||
assert_equal apple, client.firm_with_primary_key
|
||||
end
|
||||
|
||||
def test_building_the_belonging_object
|
||||
citibank = Account.create("credit_limit" => 10)
|
||||
apple = citibank.build_firm("name" => "Apple")
|
||||
@@ -76,6 +98,13 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
|
||||
assert_equal apple.id, citibank.firm_id
|
||||
end
|
||||
|
||||
def test_building_the_belonging_object_with_primary_key
|
||||
client = Client.create(:name => "Primary key client")
|
||||
apple = client.build_firm_with_primary_key("name" => "Apple")
|
||||
client.save
|
||||
assert_equal apple.name, client.firm_name
|
||||
end
|
||||
|
||||
def test_natural_assignment_to_nil
|
||||
client = Client.find(3)
|
||||
client.firm = nil
|
||||
@@ -84,6 +113,14 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
|
||||
assert_nil client.client_of
|
||||
end
|
||||
|
||||
def test_natural_assignment_to_nil_with_primary_key
|
||||
client = Client.create(:name => "Primary key client", :firm_name => companies(:first_firm).name)
|
||||
client.firm_with_primary_key = nil
|
||||
client.save
|
||||
assert_nil client.firm_with_primary_key(true)
|
||||
assert_nil client.client_of
|
||||
end
|
||||
|
||||
def test_with_different_class_name
|
||||
assert_equal Company.find(1).name, Company.find(3).firm_with_other_name.name
|
||||
assert_not_nil Company.find(3).firm_with_other_name, "Microsoft should have a firm"
|
||||
@@ -110,6 +147,17 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
|
||||
assert_equal 0, Topic.find(debate.id).send(:read_attribute, "replies_count"), "First reply deleted"
|
||||
end
|
||||
|
||||
def test_belongs_to_with_primary_key_counter
|
||||
debate = Topic.create("title" => "debate")
|
||||
assert_equal 0, debate.send(:read_attribute, "replies_count"), "No replies yet"
|
||||
|
||||
trash = debate.replies_with_primary_key.create("title" => "blah!", "content" => "world around!")
|
||||
assert_equal 1, Topic.find(debate.id).send(:read_attribute, "replies_count"), "First reply created"
|
||||
|
||||
trash.destroy
|
||||
assert_equal 0, Topic.find(debate.id).send(:read_attribute, "replies_count"), "First reply deleted"
|
||||
end
|
||||
|
||||
def test_belongs_to_counter_with_assigning_nil
|
||||
p = Post.find(1)
|
||||
c = Comment.find(1)
|
||||
@@ -122,6 +170,18 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
|
||||
assert_equal 1, Post.find(p.id).comments.size
|
||||
end
|
||||
|
||||
def test_belongs_to_with_primary_key_counter_with_assigning_nil
|
||||
debate = Topic.create("title" => "debate")
|
||||
reply = Reply.create("title" => "blah!", "content" => "world around!", "parent_title" => "debate")
|
||||
|
||||
assert_equal debate.title, reply.parent_title
|
||||
assert_equal 1, Topic.find(debate.id).send(:read_attribute, "replies_count")
|
||||
|
||||
reply.topic_with_primary_key = nil
|
||||
|
||||
assert_equal 0, Topic.find(debate.id).send(:read_attribute, "replies_count")
|
||||
end
|
||||
|
||||
def test_belongs_to_counter_with_reassigning
|
||||
t1 = Topic.create("title" => "t1")
|
||||
t2 = Topic.create("title" => "t2")
|
||||
@@ -219,6 +279,18 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
|
||||
assert_equal firm, final_cut.firm(true)
|
||||
end
|
||||
|
||||
def test_assignment_before_child_saved_with_primary_key
|
||||
final_cut = Client.new("name" => "Final Cut")
|
||||
firm = Firm.find(1)
|
||||
final_cut.firm_with_primary_key = firm
|
||||
assert final_cut.new_record?
|
||||
assert final_cut.save
|
||||
assert !final_cut.new_record?
|
||||
assert !firm.new_record?
|
||||
assert_equal firm, final_cut.firm_with_primary_key
|
||||
assert_equal firm, final_cut.firm_with_primary_key(true)
|
||||
end
|
||||
|
||||
def test_new_record_with_foreign_key_but_no_object
|
||||
c = Client.new("firm_id" => 1)
|
||||
assert_equal Firm.find(:first), c.firm_with_basic_id
|
||||
@@ -304,6 +376,20 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
|
||||
sponsor.sponsorable = member
|
||||
assert_equal "Member", sponsor.sponsorable_type
|
||||
end
|
||||
|
||||
def test_polymorphic_assignment_with_primary_key_foreign_type_field_updating
|
||||
# should update when assigning a saved record
|
||||
essay = Essay.new
|
||||
writer = Author.create(:name => "David")
|
||||
essay.writer = writer
|
||||
assert_equal "Author", essay.writer_type
|
||||
|
||||
# should update when assigning a new record
|
||||
essay = Essay.new
|
||||
writer = Author.new
|
||||
essay.writer = writer
|
||||
assert_equal "Author", essay.writer_type
|
||||
end
|
||||
|
||||
def test_polymorphic_assignment_updates_foreign_id_field_for_new_and_saved_records
|
||||
sponsor = Sponsor.new
|
||||
@@ -317,6 +403,18 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
|
||||
assert_equal nil, sponsor.sponsorable_id
|
||||
end
|
||||
|
||||
def test_polymorphic_assignment_with_primary_key_updates_foreign_id_field_for_new_and_saved_records
|
||||
essay = Essay.new
|
||||
saved_writer = Author.create(:name => "David")
|
||||
new_writer = Author.new
|
||||
|
||||
essay.writer = saved_writer
|
||||
assert_equal saved_writer.name, essay.writer_id
|
||||
|
||||
essay.writer = new_writer
|
||||
assert_equal nil, essay.writer_id
|
||||
end
|
||||
|
||||
def test_belongs_to_proxy_should_not_respond_to_private_methods
|
||||
assert_raise(NoMethodError) { companies(:first_firm).private_method }
|
||||
assert_raise(NoMethodError) { companies(:second_client).firm.private_method }
|
||||
|
||||
@@ -2026,7 +2026,7 @@ class BasicsTest < ActiveRecord::TestCase
|
||||
|
||||
def test_inspect_instance
|
||||
topic = topics(:first)
|
||||
assert_equal %(#<Topic id: 1, title: "The First Topic", author_name: "David", author_email_address: "david@loudthinking.com", written_on: "#{topic.written_on.to_s(:db)}", bonus_time: "#{topic.bonus_time.to_s(:db)}", last_read: "#{topic.last_read.to_s(:db)}", content: "Have a nice day", approved: false, replies_count: 1, parent_id: nil, type: nil>), topic.inspect
|
||||
assert_equal %(#<Topic id: 1, title: "The First Topic", author_name: "David", author_email_address: "david@loudthinking.com", written_on: "#{topic.written_on.to_s(:db)}", bonus_time: "#{topic.bonus_time.to_s(:db)}", last_read: "#{topic.last_read.to_s(:db)}", content: "Have a nice day", approved: false, replies_count: 1, parent_id: nil, parent_title: nil, type: nil>), topic.inspect
|
||||
end
|
||||
|
||||
def test_inspect_new_instance
|
||||
|
||||
@@ -27,25 +27,25 @@ class ReflectionTest < ActiveRecord::TestCase
|
||||
|
||||
def test_read_attribute_names
|
||||
assert_equal(
|
||||
%w( id title author_name author_email_address bonus_time written_on last_read content approved replies_count parent_id type ).sort,
|
||||
%w( id title author_name author_email_address bonus_time written_on last_read content approved replies_count parent_id parent_title type ).sort,
|
||||
@first.attribute_names
|
||||
)
|
||||
end
|
||||
|
||||
def test_columns
|
||||
assert_equal 12, Topic.columns.length
|
||||
assert_equal 13, Topic.columns.length
|
||||
end
|
||||
|
||||
def test_columns_are_returned_in_the_order_they_were_declared
|
||||
column_names = Topic.columns.map { |column| column.name }
|
||||
assert_equal %w(id title author_name author_email_address written_on bonus_time last_read content approved replies_count parent_id type), column_names
|
||||
assert_equal %w(id title author_name author_email_address written_on bonus_time last_read content approved replies_count parent_id parent_title type), column_names
|
||||
end
|
||||
|
||||
def test_content_columns
|
||||
content_columns = Topic.content_columns
|
||||
content_column_names = content_columns.map {|column| column.name}
|
||||
assert_equal 8, content_columns.length
|
||||
assert_equal %w(title author_name author_email_address written_on bonus_time last_read content approved).sort, content_column_names.sort
|
||||
assert_equal 9, content_columns.length
|
||||
assert_equal %w(title author_name author_email_address written_on bonus_time last_read content approved parent_title).sort, content_column_names.sort
|
||||
end
|
||||
|
||||
def test_column_string_type_and_limit
|
||||
|
||||
@@ -87,6 +87,8 @@ class Author < ActiveRecord::Base
|
||||
has_many :tags, :through => :posts # through has_many :through
|
||||
has_many :post_categories, :through => :posts, :source => :categories
|
||||
|
||||
has_one :essay, :primary_key => :name, :as => :writer
|
||||
|
||||
belongs_to :author_address, :dependent => :destroy
|
||||
belongs_to :author_address_extra, :dependent => :delete, :class_name => "AuthorAddress"
|
||||
|
||||
|
||||
@@ -88,6 +88,7 @@ class Client < Company
|
||||
belongs_to :firm_with_select, :class_name => "Firm", :foreign_key => "firm_id", :select => "id"
|
||||
belongs_to :firm_with_other_name, :class_name => "Firm", :foreign_key => "client_of"
|
||||
belongs_to :firm_with_condition, :class_name => "Firm", :foreign_key => "client_of", :conditions => ["1 = ?", 1]
|
||||
belongs_to :firm_with_primary_key, :class_name => "Firm", :primary_key => "name", :foreign_key => "firm_name"
|
||||
belongs_to :readonly_firm, :class_name => "Firm", :foreign_key => "firm_id", :readonly => true
|
||||
|
||||
# Record destruction so we can test whether firm.clients.clear has
|
||||
|
||||
3
activerecord/test/models/essay.rb
Normal file
3
activerecord/test/models/essay.rb
Normal file
@@ -0,0 +1,3 @@
|
||||
class Essay < ActiveRecord::Base
|
||||
belongs_to :writer, :primary_key => :name, :polymorphic => true
|
||||
end
|
||||
@@ -4,12 +4,13 @@ class Reply < Topic
|
||||
named_scope :base
|
||||
|
||||
belongs_to :topic, :foreign_key => "parent_id", :counter_cache => true
|
||||
belongs_to :topic_with_primary_key, :class_name => "Topic", :primary_key => "title", :foreign_key => "parent_title", :counter_cache => "replies_count"
|
||||
has_many :replies, :class_name => "SillyReply", :dependent => :destroy, :foreign_key => "parent_id"
|
||||
|
||||
validate :errors_on_empty_content
|
||||
validate_on_create :title_is_wrong_create
|
||||
|
||||
attr_accessible :title, :author_name, :author_email_address, :written_on, :content, :last_read
|
||||
attr_accessible :title, :author_name, :author_email_address, :written_on, :content, :last_read, :parent_title
|
||||
|
||||
validate :check_empty_title
|
||||
validate_on_create :check_content_mismatch
|
||||
|
||||
@@ -39,6 +39,7 @@ class Topic < ActiveRecord::Base
|
||||
named_scope :by_rejected_ids, lambda {{ :conditions => { :id => all(:conditions => {:approved => false}).map(&:id) } }}
|
||||
|
||||
has_many :replies, :dependent => :destroy, :foreign_key => "parent_id"
|
||||
has_many :replies_with_primary_key, :class_name => "Reply", :dependent => :destroy, :primary_key => "title", :foreign_key => "parent_title"
|
||||
serialize :content
|
||||
|
||||
before_create :default_written_on
|
||||
|
||||
@@ -161,6 +161,12 @@ ActiveRecord::Schema.define do
|
||||
t.integer :course_id, :null => false
|
||||
end
|
||||
|
||||
create_table :essays, :force => true do |t|
|
||||
t.string :name
|
||||
t.string :writer_id
|
||||
t.string :writer_type
|
||||
end
|
||||
|
||||
create_table :events, :force => true do |t|
|
||||
t.string :title, :limit => 5
|
||||
end
|
||||
@@ -421,6 +427,7 @@ ActiveRecord::Schema.define do
|
||||
t.boolean :approved, :default => true
|
||||
t.integer :replies_count, :default => 0
|
||||
t.integer :parent_id
|
||||
t.string :parent_title
|
||||
t.string :type
|
||||
end
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ class Hash
|
||||
merge(other_hash) do |key, oldval, newval|
|
||||
oldval = oldval.to_hash if oldval.respond_to?(:to_hash)
|
||||
newval = newval.to_hash if newval.respond_to?(:to_hash)
|
||||
oldval.class.to_s == 'Hash' && newval.class.to_s == 'Hash' ? oldval.deep_merge(newval) : newval
|
||||
oldval.is_a?( Hash ) && newval.is_a?( Hash ) ? oldval.deep_merge(newval) : newval
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -8,6 +8,6 @@ class Hash
|
||||
# {}.diff(1 => 2) # => {1 => 2}
|
||||
# {1 => 2, 3 => 4}.diff(1 => 2) # => {3 => 4}
|
||||
def diff(h2)
|
||||
dup.delete_if { |k, v| h2[k] == v }.merge(h2.dup.delete_if { |k, v| has_key?(k) })
|
||||
dup.delete_if { |k, v| h2[k] == v }.merge!(h2.dup.delete_if { |k, v| has_key?(k) })
|
||||
end
|
||||
end
|
||||
|
||||
@@ -21,7 +21,7 @@ class Hash
|
||||
# Performs the opposite of <tt>merge</tt>, with the keys and values from the first hash taking precedence over the second.
|
||||
# Modifies the receiver in place.
|
||||
def reverse_merge!(other_hash)
|
||||
replace(reverse_merge(other_hash))
|
||||
merge!( other_hash ){|k,o,n| o }
|
||||
end
|
||||
|
||||
alias_method :reverse_update, :reverse_merge!
|
||||
|
||||
@@ -98,6 +98,10 @@ module ActiveSupport
|
||||
super other_hash.with_indifferent_access
|
||||
end
|
||||
|
||||
def reverse_merge!(other_hash)
|
||||
replace(reverse_merge( other_hash ))
|
||||
end
|
||||
|
||||
# Removes a specified key from the hash.
|
||||
def delete(key)
|
||||
super(convert_key(key))
|
||||
@@ -109,7 +113,7 @@ module ActiveSupport
|
||||
|
||||
# Convert to a Hash with String keys.
|
||||
def to_hash
|
||||
Hash.new(default).merge(self)
|
||||
Hash.new(default).merge!(self)
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
Reference in New Issue
Block a user