hashrocket / decent_exposure

A helper for creating declarative interfaces in controllers
MIT License
1.81k stars 107 forks source link

Find_by #17

Closed miguelsan closed 13 years ago

miguelsan commented 13 years ago

I want to hide the id of my objects in the URL. The best way is to have a slug attribute in the object, and override the method "to_param" in the object definition to return that slug. Afterwards, it can be called like this in the controller:

def show
  @post = Post.find_by_slug(params[:id])
end

But I can't get to make a find_by_slug with decent_exposure. I'd like to have something like this:

  expose(:post, :find_by => :slug)

Is it possible to extend the gem to allow this behavior? Searching after a different attribute than id seems a pretty normal pattern to me.

mrmemes-eth commented 13 years ago

Hi miguel. Sounds like a good candidate for a default_exposure. Something like this should get you where you want to go:

class PostsController < ActionController::Base
  default_exposure do
    if params.has_key?(:id)
      Post.find_by_slug(params[:id]).tap do |r|
        r.attributes = params[name] unless request.get?
      end
    else
      proxy.new(params[name])
    end
  end

  ...

end

Apologies that the default_exposure method isn't better documented :\

miguelsan commented 13 years ago

Now I see! Thanks for your answer, this is real help. My only concern is that I want to use it across different models, having to repeat the default_exposure everywhere. Not very DRY, maybe as a module, I'll see. On the other hand , you are right, the documentation is not very much helpful, I didn't get the meaning of the section Custom defaults, so I suppose I overlooked it. You can use my question as an example to improve it if you like. BTW, there is a typo in it: "heirachy", instead of hierarchy.

miguelsan commented 13 years ago

For other readers, here is a working version of the above code:

class PostsController < ActionController::Base
  default_exposure do |name|
    if params.has_key?(:id)
      Post.find_by_slug(params[:id]).tap do |r|
        r.attributes = params[name] unless request.get?
      end
    else
      Post.new(params[name])
    end
  end

  ...

end