0

I am unsure of what the best way of doing this is, or if my thinking is fundamentally flawed.

I have a controller that creates a Plain Old Ruby Object (PORO) presenter on its #index action:

# app/controllers/my_controller.rb
class MyController < ApplicationController
    def index
        @my_presenter = MyPresenter.new(
            filter_1: params[:filter_1],
            filter_2: params[:filter_2])
    end
end

And the presenter which uses data from multiple models:

# app/presenters/my_presenter.rb
class MyPresenter
    def initialize(filter_1: nil, filter_2: nil)
        @my_data = MyModel.my_scope(filter_1) # scoping in the my_model.rb file
        @my_other_data = MyOtherModel.my_scope(filter_1, filter_2)
    end

    def show(view)
        # Somehow call the my_function.js from here and return the result to the view
    end
end

And, finally, the View that defers to the presenter:

<!-- app/views/my_controller/index.html.erb -->
<h1>The view</h1>

<%= @my_presenter.show(this) %>

I want the #show action of the presenter to call some JavaScript (D3 code for visualisation), and return the result to the View:

// app/assests/javascripts.js
function my_function(data) {
    // D3 visualisation to go here...
    return null
}

What is the best way to accomplish this?

Bradley Marques
  • 502
  • 3
  • 22

1 Answers1

0

I've had success using ActiveModel::Conversion. This mixes in a few things that allows you to tie a view to a presenter.

In your presenter

class MyPresenter

  include ActiveModel::Conversion

  def initialize(...)
  ...

end

then in view, you can do something like

<%=h render @my_presenter %>

With this, Rails will look for the view that represents your widget/presenter in app/views/my_presenters/_my_presenter.html.erb which you can flesh out with your html.

To get the D3 hookup, you should probably attach it after the document is loaded. Assuming you've got jQuery in there, you could do something like

$(function() {
  var my_function = function(data) { 
    // d3 stuff here
  };
  my_function(data)
});

This could probably sit in your application.js or maybe in the presenter partial wrapped in a <script> tag.

There's a write up of this technique here: http://blog.carbonfive.com/2014/01/07/presenters-to-widgets-with-activemodelconversion/

Hope this helps

mr rogers
  • 3,200
  • 1
  • 19
  • 31