how to DRY a respond_to that is the same in all actions?

377 views Asked by At

I have a controller that will server widgets:

class WidgetsController < ApplicationController
  def widget1
    respond_to do |format|
      format.html
      format.js { render js: js_constructor }
    end
  end

  def widget2
    respond_to do |format|
      format.html
      format.js { render js: js_constructor }
    end
  end

  private
  def js_constructor
    content = render_to_string(params[:action], layout: false)
    "document.write(#{content.to_json})"
  end
end

This controller will get bigger, so I would like to avoid repeating this block of code in all actions:

respond_to do |format|
  format.html
  format.js { render js: js_constructor }
end

Any idea?

EDIT: just to give some context...

The route is flexible/dynamic: get 'widgets/:action', to: 'widgets#:action'

So, if I visit widgets/widget1 it will render the view widget1.html.erb.

If I include the script in another server it will construct the widget1 over there:

<script type='text/javascript' src='http://localhost:3000/widgets/widget1.js'></script>
2

There are 2 answers

1
supermoogle On BEST ANSWER

I would write a single action that takes the "view" as a parameter. You're basically doing a #show action that renders different views.

get 'widgets/:template', to: 'widgets#show'

class WidgetsController < ApplicationController
  def show
    respond_to do |format|
      format.html { render params.require(:template) }
      format.js { render js: js_constructor }
    end
  end

  private
  def js_constructor
    content = render_to_string(params.require(:template), layout: false)
    "document.write(#{content.to_json})"
  end
end
0
phoet On

And the answer is meta-programming:

class WidgetsController < ApplicationController
  [:widget1, :widget2].each do |name|
    define_method(name) do
      respond_to do |format|
        format.html
        format.js { render js: js_constructor }
      end
    end
  end

  private

  def js_constructor
    content = render_to_string(params[:action], layout: false)
    "document.write(#{content.to_json})"
  end
end