0

I'm writing a simple page that will help me view the sync status of my sites custom gallery compared to my Flickr account.

I have a simple loop that iterates over a response from the Flickr API:

<% for collection in @flickr_hierarchy %>
  <%= traverse_collection(collection, 0) %>
<% end %>

traverse_collection is a Rails helper method as so:

module GalleryHelper

  def traverse_collection(collection, parent)
    parent = parent == 0 ? 0 : parent["id"]

    content_tag(:tr) do
      content_tag(:td, 'Collection')

      collectionLocal = Collection.where(flickr_id: collection.id).first

      if collectionLocal != nil
        content_tag(:td, 'Yes')
      else
        content_tag(:td, 'No')
      end
      content_tag(:td, '&nbsp;')
      content_tag(:td, '&nbsp;')
      content_tag(:td, collection.title)
      content_tag(:td, collection.id)
      content_tag(:td, parent.to_s)
      content_tag(:td, 'N/A')
      content_tag(:td) do
        if collectionLocal != nil
          button_to('Add all Sets', admin_add_all_sets_for_collection_path(flickr_collection_id: collection.id))
          button_to('Delete Collection', admin_delete_collection_path(flickr_collection_id: collection.id))
        else
          button_to('Add Collection', admin_add_collection_path(flickr_collection_id: collection.id, flickr_parent_collection_id: parent.to_s))
          button_to('Add Collection and Sets', admin_add_all_sets_for_collection_path(flickr_collection_id: collection.id, flickr_parent_collection_id: parent.to_s))
        end
      end
    end
  end

end

Unfortunately i've found out that there is no nice or non-messy code way to get the generated HTML to be output on my page.

Is there a good way to do this or should I be taking a different approach. Any ideas?

Thanks, Neil

rctneil
  • 7,016
  • 10
  • 40
  • 83
  • Could you explain the problem? Are you trying to take the HTML logic out of the helper? – kendotwill Mar 02 '15 at 17:12
  • @kendotwill I can't get the generated HTML to be output when I run that helper method from my view. – rctneil Mar 02 '15 at 17:15
  • Are you trying to generate the HTML after the page has already been loaded? – kendotwill Mar 02 '15 at 17:33
  • Can you provide more code, the controller? – kendotwill Mar 02 '15 at 17:55
  • @kendotwill No code is being generated after the page has loaded. There's no need for me to post the controller code. I have an var called `@flickr_hierarchy`. For each item of it I want to run that helper method which should spit out a chunk of HTML for the page to display. The display does not happen. I am assuming the HTML is being generated but I don;t know how to get it to output onto my page. – rctneil Mar 02 '15 at 17:58

3 Answers3

1

You can use render in your helper method.

Please see How to render a view/partial in a helper w/o the layout?

Just wrap the template with your business/presentation logic in a helper method, prepare your scope and let the rendering engine do the rendering.

Does that help?

UPDATE

You can call practically everything in your helper method including render, which will instruct Rails engine to render any view/partial into request response

This is the helper implementation

# app/helpers/application_helper.rb
module ApplicationHelper
  def hello()
    # Prepare your model into locals, which will be passed to your partial
    # template
    render partial: 'shared/hello', locals: {text: 'world'}
  end
end

This is the partial template used in helper method

<!-- views/shared/_hello.html.erb -->
<div>hello <%= text %></div>

This is the main controller view orchestrating the request

<!-- views/welcome/index.html.erb -->
<h1>Test</h1>
<%= hello %>
Community
  • 1
  • 1
Martin Macak
  • 3,507
  • 2
  • 30
  • 54
1

You should move the assembly of the HTML out of your helper and into a partial. Create a file app/views/gallery/_row.html.erb (you can name it whatever you want, but make sure the file starts with an underscore) and put your HTML there, like this:

<tr>
  <td>Collection</td>
  <td><%= collection_local.present? ? "Yes" : "No" %></td>
  <td>&nbsp;</td>
  <td>&nbsp;</td>
  <td><%= collection.title %></td>
  <td><%= collection.id %></td>
  <td><%= parent %></td>
  <td>N/A</td>
  <td>
    <% if collection_local.present? %>
      <%= button_to(
            "Add all Sets", 
            admin_add_all_sets_for_collection_path(flickr_collection_id: collection.id)
            ) %>
      <%= button_to(
            "Delete Collection",
            admin_delete_collection_path(flickr_collection_id: collection.id)
            ) %>
    <% else %>
      <%= button_to(
            "Add Collection", 
            admin_add_collection_path(
              flickr_collection_id: collection.id, 
              flickr_parent_collection_id: parent.to_s
            )) %>
      <%= button_to(
            "Add Collection and Sets",
            admin_add_all_sets_for_collection_path(
              flickr_collection_id: collection.id, 
              flickr_parent_collection_id: parent.to_s
            )) %>
    <% end %>
  </td>
</tr>

Now all your helper has to do is call render with the name of the partial and the "locals" (variables) that your partial needs. The name in this case is gallery/row (filename without the underscore and extension), and the variables that the partial needs are: collection, collection_local, and parent. Therefore the render call would look like this:

module GalleryHelper

  def traverse_collection(collection, parent)
    parent = parent == 0 ? 0 : parent["id"]
    collection_local = Collection.where(flickr_id: collection.id).first

    render(
      partial: "gallery/row",
      locals: {
        collection: collection,
        collection_local: collection_local,
        parent: parent
      })
  end
end

Does that help?

There is more information about how to use partials in the official Ruby on Rails Guides.

Matt Brictson
  • 10,904
  • 1
  • 38
  • 43
  • That makes a lot of sense! I shall give that a go hopefully this evening when I get time. Thanks. I shall report back with how I get on. – rctneil Mar 03 '15 at 08:28
  • This is perfect. Thanks for helping me see where I should have separated the concerns and keeping my code more agile and tidy! – rctneil Mar 03 '15 at 21:11
0

You have to add a plus sign + at the end of each content_tag and maybe the button_to. Otherwise only the last content_tag will get created.

module GalleryHelper

  def traverse_collection(collection, parent)
    parent = parent == 0 ? 0 : parent["id"]

    collectionLocal = Collection.where(flickr_id: collection.id).first

    content_tag(:tr) do
      content_tag(:td, 'Collection') +

      content_tag(:td, (collectionLocal != nil) ? 'Yes' : 'No' ) +
      content_tag(:td, '&nbsp;') + 
      content_tag(:td, '&nbsp;') +
      content_tag(:td, collection.title) +
      content_tag(:td, collection.id) +
      content_tag(:td, parent.to_s) +
      content_tag(:td, 'N/A') +
      content_tag(:td) do
        if collectionLocal != nil
          button_to('Add all Sets', admin_add_all_sets_for_collection_path(flickr_collection_id: collection.id)) +
          button_to('Delete Collection', admin_delete_collection_path(flickr_collection_id: collection.id))
        else
          button_to('Add Collection', admin_add_collection_path(flickr_collection_id: collection.id, flickr_parent_collection_id: parent.to_s)) +
          button_to('Add Collection and Sets', admin_add_all_sets_for_collection_path(flickr_collection_id: collection.id, flickr_parent_collection_id: parent.to_s))
        end
      end
    end
  end
end

Rails- nested content_tag

Community
  • 1
  • 1
kendotwill
  • 1,892
  • 18
  • 17
  • This makes no difference what so ever. – rctneil Mar 02 '15 at 21:09
  • @rctneil I tested it with the assumption that `@flickr_hierarchy` is not nil. If you view the source in the browser after after loading the page and you don't see an empty tr `` then you function is not being called at all. I would start by debugging if your `for` is being executed. You will need a `+` at the end of your `content_tags` if you want to fix your current code. – kendotwill Mar 03 '15 at 06:13