FriendlyId is the “Swiss Army bulldozer” of slugging and permalink plugins for ActiveRecord. It allows you to create pretty URL’s and work with human-friendly strings as if they were numeric ids for ActiveRecord models.
# history.rb:94
def first_by_friendly_id(id)
super || slug_table_record(id)
end
super calls the finder method which uses parse_friendly_id, but if that fails (not found, nil), slug_table_record is called with the unparsed ID which results in a query something like this, which will fail because the slug isn't parsed and downcased.
SELECT ... WHERE "friendly_id_slugs"."sluggable_type" = 'MyModel' AND "friendly_id_slugs"."slug" = 'UNPARSED-VALUE'
Changing the method in history.rb to use the parse method results in expected behaviour:
# history.rb:94
def first_by_friendly_id(id)
super || slug_table_record(parse_friendly_id(id))
end
It likely needs to be applied elsewhere, such as exists_by_friendly_id?, where the same pattern super || method_using_unparsed_id(id) exposes the bug.
I also couldn't get parse_friendly_id to work in the documented way without monkey patching it in the initializer, but that's a different issue.
If
parse_friendly_id
is used, say to downcase, it's used by the regular finder methods, but not by history:https://github.com/norman/friendly_id/blob/master/lib/friendly_id/history.rb#L94
super
calls the finder method which usesparse_friendly_id
, but if that fails (not found, nil),slug_table_record
is called with the unparsed ID which results in a query something like this, which will fail because the slug isn't parsed and downcased.Changing the method in
history.rb
to use the parse method results in expected behaviour:It likely needs to be applied elsewhere, such as
exists_by_friendly_id?
, where the same patternsuper || method_using_unparsed_id(id)
exposes the bug.I also couldn't get parse_friendly_id to work in the documented way without monkey patching it in the initializer, but that's a different issue.