Rails 4 using controller concern to DRY update met

2019-08-06 17:29发布

问题:

I have a rails app where many of the models are editable using best_in_place, so I have a lot of controllers that look partially like this:

before_action :find_objects, except: [:new, :create]

def update
  @object.update_attributes(object_params)
  respond_to do |format|
    format.json { respond_with_bip @object}
  end
end

private

def object_params
  params.require(:object).permit(:foo, :bar)
end

def find_objects
  @object = Object.find(params[:id])
end

How do I move this particular repeated piece into a controller concern, given that the object being updated is going to come in with a particular name in the params hash, and object_params and find_objects should call their proper versions based on the model name? Is there some elegant meta-magic that'll sort this all out?

回答1:

I think this is a case where your code could be "too DRY". You can certainly accomplish this using meta-magic, but it could make your code confusing in the long run.

If you want to do the meta-magic, one trick is to use params[:controller] to get the name of the model. For example, if you have a PostsController, then:

params[:controller] # => "posts"
params[:controller].classify # => "Post"

Taking this a step further, you could write a generic find_object like this:

def find_object
  model_class = params[:controller].classify.constantize
  model_instance = model_class.find(params[:id])
  instance_variable_set("@#{model_class.name.underscore}", model_instance)
end

But as I said at the beginning, I'm not sure I would recommend this amount of abstraction just for the sake of DRY-ing your controller code.