diff options
author | David Heinemeier Hansson <david@loudthinking.com> | 2013-11-14 11:03:31 -0800 |
---|---|---|
committer | David Heinemeier Hansson <david@loudthinking.com> | 2013-11-14 11:03:31 -0800 |
commit | a23bf6f55a2bea50ec39cc744e17c924d727c089 (patch) | |
tree | c3c14732612183b2fbd4e10b380361d1d1e5f794 /activerecord | |
parent | 83a065d181efc5eb1983cdf369bcb96c25fa9c2d (diff) | |
parent | 547999df256a5ac650eb012dabf713027b9bda1f (diff) | |
download | rails-a23bf6f55a2bea50ec39cc744e17c924d727c089.tar.gz rails-a23bf6f55a2bea50ec39cc744e17c924d727c089.tar.bz2 rails-a23bf6f55a2bea50ec39cc744e17c924d727c089.zip |
Merge pull request #12891 from javan/to-param
Add AR::Base.to_param for convenient "pretty" URLs derived from a model's attribute or method
Diffstat (limited to 'activerecord')
-rw-r--r-- | activerecord/CHANGELOG.md | 14 | ||||
-rw-r--r-- | activerecord/lib/active_record/integration.rb | 31 | ||||
-rw-r--r-- | activerecord/test/cases/integration_test.rb | 18 | ||||
-rw-r--r-- | activerecord/test/models/company.rb | 2 |
4 files changed, 65 insertions, 0 deletions
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index fa00d6db1c..88128c4859 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,17 @@ +* Added `ActiveRecord::Base.to_param` for convenient "pretty" URLs derived from a model's attribute or method. + + Example: + + class User < ActiveRecord::Base + to_param :name + end + + user = User.find_by(name: 'Fancy Pants') + user.id # => 123 + user.to_param # => "123-fancy-pants" + + *Javan Makhmali* + * Added `ActiveRecord::Base.no_touching`, which allows ignoring touch on models. Examples: diff --git a/activerecord/lib/active_record/integration.rb b/activerecord/lib/active_record/integration.rb index f88c8e30e6..f881fa74b2 100644 --- a/activerecord/lib/active_record/integration.rb +++ b/activerecord/lib/active_record/integration.rb @@ -1,3 +1,5 @@ +require 'active_support/core_ext/string/filters' + module ActiveRecord module Integration extend ActiveSupport::Concern @@ -65,5 +67,34 @@ module ActiveRecord "#{self.class.model_name.cache_key}/#{id}" end end + + module ClassMethods + # Defines your model's +to_param+ method to generate "pretty" URLs + # using +method_name+, which can be any attribute or method that + # responds to +to_s+. + # + # class User < ActiveRecord::Base + # to_param :name + # end + # + # user = User.find_by(name: 'Fancy Pants') + # user.id # => 123 + # user_path(user) # => "/users/123-fancy-pants" + # + # Because the generated param begins with the record's +id+, it is + # suitable for passing to +find+. In a controller, for example: + # + # params[:id] # => "123-fancy-pants" + # User.find(params[:id]).id # => 123 + def to_param(method_name) + define_method :to_param do + if (default = super()) && (result = send(method_name).to_s).present? + "#{default}-#{result.truncate(20, separator: /\s/, omission: nil).parameterize}" + else + default + end + end + end + end end end diff --git a/activerecord/test/cases/integration_test.rb b/activerecord/test/cases/integration_test.rb index 840865c4cf..1f62433ea2 100644 --- a/activerecord/test/cases/integration_test.rb +++ b/activerecord/test/cases/integration_test.rb @@ -23,6 +23,24 @@ class IntegrationTest < ActiveRecord::TestCase assert_equal '1', client.to_param end + def test_to_param_class_method + firm = Firm.find(4) + assert_equal '4-flamboyant-software', firm.to_param + end + + def to_param_class_method_uses_default_if_blank + firm = Firm.find(4) + firm.name = nil + assert_equal '4', firm.to_param + firm.name = ' ' + assert_equal '4', firm.to_param + end + + def to_param_class_method_uses_default_if_not_persisted + firm = Firm.new(name: 'Fancy Shirts') + assert_equal nil, firm.to_param + end + def test_cache_key_for_existing_record_is_not_timezone_dependent utc_key = Developer.first.cache_key diff --git a/activerecord/test/models/company.rb b/activerecord/test/models/company.rb index 0b0b304121..76411ecb37 100644 --- a/activerecord/test/models/company.rb +++ b/activerecord/test/models/company.rb @@ -40,6 +40,8 @@ module Namespaced end class Firm < Company + to_param :name + has_many :clients, -> { order "id" }, :dependent => :destroy, :before_remove => :log_before_remove, :after_remove => :log_after_remove has_many :unsorted_clients, :class_name => "Client" has_many :unsorted_clients_with_symbol, :class_name => :Client |