Search code examples
ruby-on-rails-3routesmodels

conditional to_param method


I am using the model instance method t_param to generate a SEO-style URL

def to_param
  url
end

that way I can generate links to the model with path_to_model(model) and query the model with Model.find_by_url(url). This works fine so far.

My question: I have RESTFUL admin routes for the backend. Can I somehow make the to_param method react to the route it is called by? Because I want to create links in the backend with the ID parameter and not the URL parameter. Or what is the correct approach here?


Solution

  • I had the same issue. A model really can't/shouldn't know anything about controllers. It's the controller's job to determine what resource is being requested, and to call the model to access it. If your AdminController needs to use the standard numeric ID, you're not going to want to touch to_param.

    As it turns out, the solution is quite simple, and I use it in production.

    Assuming you've namespaced your controllers, you'll have a MyModelController and a Admin::MyModelController, along with their helpers. In Admin, do things the standard way. In MyModelController, do the following:

    In your resource actions, refer to params[:id] but treat it like a permalink (URL). For example

    def get
      @my_model = MyModel.find_by_url(params[:id])
      ...
    end
    

    In your MyModelHelper

    def my_model_path my_model
      super my_model.url
    end
    
    def my_model_url my_model
      super my_model.url
    end
    

    To me it felt this was the best way to "not fight" rails and get what I needed done.

    There might be a more clever way to override the named routes. Also I think you can't use helper :all with this approach, unless you check state of whether you're in admin or not before generating paths/url's.