gabrielhilal
gabrielhilal

Reputation: 10769

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

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>

Upvotes: 0

Views: 389

Answers (2)

supermoogle
supermoogle

Reputation: 1207

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

Upvotes: 1

phoet
phoet

Reputation: 18835

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

Upvotes: 1

Related Questions