Search code examples
rubyruby-on-rails-4cellsrails-cells

How can I inject custom rendering code into a Cell?


I've created a Cell that renders a table view of data and I'd like to reuse it for other table views. For each row of that data, I'd like to have some unique elements mixed with the standard columns. Right now, a simplified portion version of my Cell's show.html.slim looks like:

- users.each do |user|
  tr
    / A column unique to User
    td
      = link_to_if current_user == user, "Groups", user_groups_path(user)
    / Common code that can be shared across other tables
    td user.name

I'd like to be able to extract the User-specific code from this level and inject it from above. The Cells documentation states:

If in doubt, encapsulate nested parts of your view into a separate cell. You can use the #cell method in your cell to instantiate a nested cell.

However, it's difficult to simply instantiate a new Cell (edit: within the table cell):

  1. I need to know what cell to create.
  2. I need to be able to pass in information from the parent cell (user in my example).
  3. I need to be able to pass in information specific to the child cell (current_user in my example).

What options exist for injecting this type of partial rendering into a Cell? Are any of them generally preferred solutions?


Solution

  • I ended up just defining some methods on my cell that accept blocks

    class DataTableCell < Cell::ViewModel
      def row_prefix(&blk)
        @_row_prefix = blk
      end
    
      def render_row_prefix(item)
        return unless @_row_prefix
        @_row_prefix.call(item).call
      end
    end
    

    Whenever I want to render the DataTableCell, I provide a block like:

    cell = cell(:data_table)
    cell.row_prefix do |item|
      cell(:users_row_prefix, user: item, current_user: current_user)
    end
    

    Inside my cell, I can just call render_row_prefix(row_item).

    I'm not in live with this solutions, as it can be kind of heavyweight, but it does work.