Skip to content

trailblazer/trailblazer-cells

Repository files navigation

Trailblazer::Cells

Trailblazer's file layout for Cells.

Overview

Trailblazer cells are view components based on the Cells gem, but following the Trailblazer naming conventions.

File Structure

├── app
│    ├── concepts
│    │   ├── blog_post
│    │   │    ├── cell
│    │   │    │   ├── edit.rb
│    │   │    │   ├── item.rb
│    │   │    │   ├── new.rb
│    │   │    │   └── show.rb
│    │   │    └── view
│    │   │        ├── edit.erb
│    │   │        ├── item.erb
│    │   │        ├── new.erb
│    │   │        └── show.erb
│    │   │        └── author_list.erb

Cell Class

# app/concepts/blog_post/cell/edit.rb
module BlogPost
  module Cell
    class Edit < Trailblazer::Cell

      # You can have helper methods.
      def post_url
        new_blog_post_path(model.id)
      end

      def summary
        "#{model.text[0..99]}..."
      end
    end # New
  end
end

Views

# app/concepts/blog_post/view/edit.erb
<h1>
  You're editing <%= model.titel %>
</h1>

<div class="summary">
  <%= summary %>
</div>

<%= render :edit_form %>
# app/concepts/blog_post/view/edit_form.erb
<%= simple_form_for model, url: post_url do %>
  ...
<% end %>

Rendering

# app/controllers/blog_post_controller.rb
class BlogPostController < ApplicationController
  def edit
    @blog_post = BlogPost.find(params[:id]) # do whatever you need here.

    render cell(BlogPost::Cell::Edit, @blog_post)
  end
end

View Prefixes

In Trailblazer, class structures such as the following are very common, let's say for a post concept, here are the class headers, and where the view directory gets resolved to.

module Post
  module Cell
    class New < Trailblazer::Cell         # => app/concepts/post/view
    class Show < Trailblazer::Cell        # => app/concepts/post/view
      class SideBar < Trailblazer::Cell   # => app/concepts/post/view

Automatic show

You don't have to define a show method, Trailblazer::Cell will have one that looks as follows.

class Trailblazer::Cell
  def show
    render
  end

View Name

When calling render, the view name is inferred from the class name.

module Post
  module Cell
    class New < Trailblazer::Cell         # => new.erb
    class Show < Trailblazer::Cell        # => show.erb
      class SideBar < Trailblazer::Cell   # => side_bar.erb

You can still override using render view: :name.

Layout

You can pass a layout cell into every Trailblazer::Cell which will render the layout.

Post::Cell::Show.new(post, layout: Gemgem::Cell::Layout).()

The :layout option has to refer to a cell class. When invoked, the layout cell will receive the content of the actual cell under :content, resulting in a call as follows.

Gemgem::Cell::Layout.new(post,
  content: Post::Cell::Show.new(post)
)

The layout cell's show view can sit in any directory, for example gemgem/view/layout.rb.

<html>
Yay, I'm the layout!

<%= content %>
</html>

It's up to you what you do with the :content option. Here's the Trailblazer way.

class Gemgem::Cell::Layout < Trailblazer::Cell
  self.view_paths = ["gemgem"]
  def content
    @options[:content]
  end
end

Cells with layout cells allow replacing a frameworks entire view stack, e.g. ActionView.

Namespaces

It works identical with namespaces.

View Paths

Some projects do not use the app/concept view path. This can be changed as follows.

Trailblazer::Cell.view_paths = ["concepts"]

Note that this will change for all cells, including bundled in gems. Introduce an Application::Cell if you don't like that.

Dependencies

This gem has only one dependency: cells. Note that it does not need trailblazer.