Reputation: 6049
I am using friendly_id
in my rails 4 application with slug
. Now I am using active_admin gem.
Problem:
When I click on show link from active admin for Group
resource, It is throwing the following exception:
ActiveRecord::RecordNotFound at /admin/groups/username20-s-group-1
I guess, I need to override some of the active_admin
default functions?
Upvotes: 12
Views: 5208
Reputation: 25
Really late to the party here, but we were struggling recently with this in a Rails 7.0 app and I wanted to share our fix.
If you see the uninitialized constant InheritedResources::Base (NameError)
error, put your class_eval
block inside an after_initialize
block in config/initializers/active_admin.rb
.
Rails.application.configure do
config.after_initialize do
ActiveAdmin::ResourceController.class_eval do
def find_resource
finder = resource_class.is_a?(FriendlyId) ? :slug : :id
scoped_collection.find_by(finder => params[:id])
end
end
end
end
This works because it will overwrite #find_resource
after Rails has initialized instead of in the middle of it while other classes have not loaded yet.
Upvotes: 1
Reputation: 70367
If you've tried some of the other answers here and gotten
uninitialized constant InheritedResources::Base (NameError)
Then you might consider monkey patching FriendlyId
rather than ActiveAdmin
. Create a new initializer file config/initializers/friendly_id_monkey_patch.rb
containing this:
module FriendlyIdModelMonkeyPatch
def to_param
if caller.to_s.include? 'active_admin'
id&.to_s
else
super
end
end
end
module FriendlyId::Model
prepend FriendlyIdModelMonkeyPatch
end
Now all of your FriendlyId
models will revert to using their ID in ActiveAdmin and their slug everywhere else.
See also this answer, which does the same thing but for only one model (rather than monkey patching for all FriendlyId
models)
Upvotes: 2
Reputation: 3424
IMHO, it's suboptimal to completely override the find_resource
as most of the answers suggest. Better to prepend a module and call super
preserving normal behaviour when FriendlyId is not in use. For reference you can check how this method is currently (as of writing) implemented, it is not simply scoped_collection.find(params[:id])
as one might think:
https://github.com/activeadmin/activeadmin/blob/b45b1fb05af9a7f6c5e2be94f61cf4a5f60ff3bb/lib/active_admin/resource_controller/data_access.rb#L104
module ActiveAdminFriendlyIdScoping
def find_resource
if resource_class.is_a? FriendlyId
scoped_collection.friendly.find params[:id]
# Or potentially even
# scoped_collection.friendly.send method_for_find, params[:id]
# Or you could do something like this
# raise "Using FriendlyId, find method configuration ignored" if method_for_find != :find
else
super
end
end
end
ActiveAdmin.setup do |config|
#...
Rails.application.config.to_prepare do
ActiveAdmin::ResourceController.prepend(ActiveAdminFriendlyIdScoping)
end
end
Upvotes: 0
Reputation: 1942
A better approach to @AndreyDeineko's is to override ActiveAdmin::ResourceController
's find_resource
method in config/initialisers/active_admin.rb
and leverage the methods provided by FriendlyId (5.x at this point):
In config/initialisers/active_admin.rb
:
ActiveAdmin.setup do |config|
# == Friendly Id addon
ActiveAdmin::ResourceController.class_eval do
def find_resource
if resource_class.is_a?(FriendlyId)
scoped_collection.friendly.find(params[:id])
else
scoped_collection.find(params[:id])
end
end
end
# initial config
end
This looks much cleaner to me, than putting it in the application controller, as it is related to the configuration of Active Admin.
Upvotes: 22
Reputation: 52367
There are cases, when application has quit a few resources, hence in order to keep it DRY there is a nice solution requiring few lines of code for whole application - simply override activeadmin's resource controller.
Create config/initializers/active_admin_monkey_patching.rb
file with the following content:
ActiveAdmin::ResourceController.class_eval do
def find_resource
finder = resource_class.is_a?(FriendlyId) ? :slug : :id
scoped_collection.find_by(finder => params[:id])
end
end
Do not forget to restart the server.
Upvotes: 30
Reputation: 41
class User < ActiveRecord::Base
extend FriendlyId
friendly_id :username, :use => [:slugged, :finders]
Upvotes: 0
Reputation: 6049
Found solution for the problem:
In your app/admin/[ResourceName.rb]
add:
# app/admin/group.rb
# find record with slug(friendly_id)
controller do
def find_resource
begin
scoped_collection.where(slug: params[:id]).first!
rescue ActiveRecord::RecordNotFound
scoped_collection.find(params[:id])
end
end
end
This solved my problem.
Upvotes: 6