Skip to content

Commit

Permalink
Added support for scoped slugs using multiple columns
Browse files Browse the repository at this point in the history
  • Loading branch information
lankz authored and norman committed Feb 27, 2012
1 parent 9ca0cf2 commit 426e4f2
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 15 deletions.
22 changes: 13 additions & 9 deletions lib/friendly_id/scoped.rb
Expand Up @@ -105,27 +105,27 @@ module Configuration
# @return Symbol The scope value
attr_accessor :scope

# Gets the scope column.
# Gets the scope columns.
#
# Checks to see if the +:scope+ option passed to
# {FriendlyId::Base#friendly_id} refers to a relation, and if so, returns
# the realtion's foreign key. Otherwise it assumes the option value was
# the name of column and returns it cast to a String.
#
# @return String The scope column
def scope_column
(reflection_foreign_key or @scope).to_s
def scope_columns
[@scope].flatten.map { |s| (reflection_foreign_key(s) or s).to_s }
end

private

if ActiveRecord::VERSION::STRING < "3.1"
def reflection_foreign_key
model_class.reflections[@scope].try(:primary_key_name)
def reflection_foreign_key(scope)
model_class.reflections[scope].try(:primary_key_name)
end
else
def reflection_foreign_key
model_class.reflections[@scope].try(:foreign_key)
def reflection_foreign_key(scope)
model_class.reflections[scope].try(:foreign_key)
end
end
end
Expand All @@ -137,8 +137,12 @@ module SlugGenerator
private

def conflict
column = friendly_id_config.scope_column
conflicts.where(column => sluggable.send(column)).first
columns = friendly_id_config.scope_columns
matched = columns.inject(conflicts) do |memo, column|
memo.where(column => sluggable.send(column))
end

matched.first
end
end
end
Expand Down
5 changes: 3 additions & 2 deletions test/schema.rb
Expand Up @@ -30,6 +30,7 @@ def up

# This will be used to test scopes
add_column :novels, :novelist_id, :integer
add_column :novels, :publisher_id, :integer
remove_index :novels, :slug

# This will be used to test column name quoting
Expand All @@ -53,7 +54,7 @@ def slugged_tables
end

def simple_tables
["authors", "books"]
["authors", "books", "publishers"]
end

def tables
Expand All @@ -62,4 +63,4 @@ def tables
end
end
end
end
end
29 changes: 25 additions & 4 deletions test/scoped_test.rb
Expand Up @@ -8,7 +8,12 @@ class Novelist < ActiveRecord::Base
class Novel < ActiveRecord::Base
extend FriendlyId
belongs_to :novelist
friendly_id :name, :use => :scoped, :scope => :novelist
belongs_to :publisher
friendly_id :name, :use => :scoped, :scope => [:publisher, :novelist]
end

class Publisher < ActiveRecord::Base
has_many :novels
end

class ScopedTest < MiniTest::Unit::TestCase
Expand All @@ -21,7 +26,7 @@ def model_class
end

test "should detect scope column from belongs_to relation" do
assert_equal "novelist_id", Novel.friendly_id_config.scope_column
assert_equal ["publisher_id", "novelist_id"], Novel.friendly_id_config.scope_columns
end

test "should detect scope column from explicit column name" do
Expand All @@ -30,7 +35,7 @@ def model_class
extend FriendlyId
friendly_id :empty, :use => :scoped, :scope => :dummy
end
assert_equal "dummy", model_class.friendly_id_config.scope_column
assert_equal ["dummy"], model_class.friendly_id_config.scope_columns
end

test "should allow duplicate slugs outside scope" do
Expand Down Expand Up @@ -59,4 +64,20 @@ def model_class
model_class.friendly_id :name, :use => [:scoped, :history]
end
end
end

test "should apply scope with multiple columns" do
transaction do
novelist = Novelist.create! :name => "a"
publisher = Publisher.create! :name => "b"

novel1 = Novel.create! :name => "c", :novelist => novelist, :publisher => publisher
novel2 = Novel.create! :name => "c", :novelist => novelist, :publisher => Publisher.create(:name => "d")
novel3 = Novel.create! :name => "c", :novelist => Novelist.create(:name => "e"), :publisher => publisher
novel4 = Novel.create! :name => "c", :novelist => novelist, :publisher => publisher

assert_equal novel1.friendly_id, novel2.friendly_id
assert_equal novel2.friendly_id, novel3.friendly_id
assert novel3.friendly_id != novel4.friendly_id
end
end
end

0 comments on commit 426e4f2

Please sign in to comment.