Skip to content

Commit

Permalink
Allow redefining to_param delimiter using param_delimiter
Browse files Browse the repository at this point in the history
This commit allows customizing the delimiter used by `to_param` when
`to_key` returns multiple value. This unblocks supporting more varieties
of composite primary key types in Active Record.
  • Loading branch information
nvasilevski committed Aug 23, 2023
1 parent dd6d931 commit 37342a3
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 1 deletion.
4 changes: 4 additions & 0 deletions activemodel/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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*
Expand Down
10 changes: 9 additions & 1 deletion activemodel/lib/active_model/conversion.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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 <tt>:to_model</tt> implementation, which simply
# returns +self+.
Expand Down Expand Up @@ -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.
Expand Down
21 changes: 21 additions & 0 deletions activemodel/test/cases/conversion_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit 37342a3

Please sign in to comment.