diff --git a/activemodel/CHANGELOG.md b/activemodel/CHANGELOG.md index 4cabd1bd5c9f4..bd697f8dee7f3 100644 --- a/activemodel/CHANGELOG.md +++ b/activemodel/CHANGELOG.md @@ -1,3 +1,7 @@ +* Add `ActiveModel::Conversion.param_delimiter` to configure delimiter being used in `to_param` + + *Nikita Vasilevsky* + * `undefine_attribute_methods` undefines alias attribute methods along with attribute methods. *Nikita Vasilevsky* diff --git a/activemodel/lib/active_model/conversion.rb b/activemodel/lib/active_model/conversion.rb index 5f82039cd6e7d..90ca23897b359 100644 --- a/activemodel/lib/active_model/conversion.rb +++ b/activemodel/lib/active_model/conversion.rb @@ -24,6 +24,14 @@ module ActiveModel module Conversion extend ActiveSupport::Concern + included do + ## + # :singleton-method: + # + # Accepts a string that will be used as a delimiter of object's key values in the `to_param` method. + class_attribute :param_delimiter, instance_reader: false, default: "-" + end + # If your object is already designed to implement all of the \Active \Model # you can use the default :to_model implementation, which simply # returns +self+. @@ -80,7 +88,7 @@ def to_key # person = Person.new(1) # person.to_param # => "1" def to_param - (persisted? && key = to_key) ? key.join("-") : nil + (persisted? && key = to_key) ? key.join(self.class.param_delimiter) : nil end # Returns a +string+ identifying the path associated with the object. diff --git a/activemodel/test/cases/conversion_test.rb b/activemodel/test/cases/conversion_test.rb index 48103119fdc32..d94f6b1185e55 100644 --- a/activemodel/test/cases/conversion_test.rb +++ b/activemodel/test/cases/conversion_test.rb @@ -53,4 +53,25 @@ def persisted? test "to_partial_path handles namespaced models" do assert_equal "helicopter/comanches/comanche", Helicopter::Comanche.new.to_partial_path end + + test "#to_param_delimiter allows redefining the delimiter used in #to_param" do + old_delimiter = Contact.param_delimiter + Contact.param_delimiter = "_" + assert_equal("abc_xyz", Contact.new(id: ["abc", "xyz"]).to_param) + ensure + Contact.param_delimiter = old_delimiter + end + + test "#to_param_delimiter is defined per class" do + old_contact_delimiter = Contact.param_delimiter + custom_contract = Class.new(Contact) + + Contact.param_delimiter = "_" + custom_contract.param_delimiter = ";" + + assert_equal("abc_xyz", Contact.new(id: ["abc", "xyz"]).to_param) + assert_equal("abc;xyz", custom_contract.new(id: ["abc", "xyz"]).to_param) + ensure + Contact.param_delimiter = old_contact_delimiter + end end