-
Notifications
You must be signed in to change notification settings - Fork 236
From Cells 3 to Cells 4 Upgrading Guide
You have to pick and install one (or multiple) template engines for your application. This will usually end in adding gem "cells-haml"
to your Gemfile
. Learn more.
The old dialect Cell::Base
and Cell::Rails
got superceded by Cell::ViewModel
. So, every cell should start like
class SongCell < Cell::ViewModel
def show
render
end
This also changes a few semantical things in your cell.
The helper #render_cell
got replaced with #cell
.
cell(:song, Song.find(1), genre: "Heavy Metal")
The first argument is a model to present, then a hash with additional parameters can be passed. It will return the cell instance. In a view, this will automatically call #to_s
, which internally invokes the #show
method.
Often, people use one cell class with multiple public methods to render different views. If you don't want to render the #show
method use #call
.
cell(:song, Song.find(1)).(:details)
Of course, this assumes you have a method #details
.
class SongCell < Cell::ViewModel
def details
render
end
Passing options used to work like this.
render_cell(:comment, @comment, layout: :fancy)
This still works with #cell
.
cell(:comment, @comment, layout: :fancy)
However, those options are now available via #options
.
def show
@layout = options[:layout]
render
end
You can also do that in the initializer.
def initialize(model, options)
@layout = options[:layout]
super
end
Don't you forget to call super
here!
You can still pass options to the method directly, this works as follows.
cell(:comment, @comment).call(:show, layout: :fancy)
Your action method will then need to process those options.
def show(layout=default)
render layout: layout
end
The second parameter to cell
is available via #model
.
Builders are no longer executed in the controller context. They also now receive the exact args
list that was passed into #cell
.
If you need controller data for your builders, push that into the options hash.
class SongCell < Cell::ViewModel
build do |model, options|
HitCell if model.is_a? Hit
end
The old configuration in application.rb
looks like this.
config.cells.with_assets = ["comment"] # references Comment::Cell.
This becomes a fully qualified underscore constant name.
config.cells.with_assets = ["comment/cell"] # references Comment::Cell.
Also, assets like comment.js
do no longer have their own directory but all sit in the cell's views
directory.
As the migration from Cells 3 to Cells 4 can be quite big, you might want to have an intermediate step along the way.
The code snippets below will allow you to update to the Cells 4 gem while keeping the Cell 3 DSL and all your controller methods/helper calls in your cell views.
This way you can upgrade to the Cells 4 gem and then rewrite your cells one a the time.
We do this by creating a new cell that acts as the bridge between the old style and the new style. Your own cells should inherit from ApplicationCell
to make the magic happen.
class ApplicationCell < Cell::ViewModel
# Include all the application helper methods and
include ApplicationHelper
# You need to include controller methods you where using from Rails explicitly.
include AbstractController::Helpers
include AbstractController::Translation
# Look at https://github.com/rails/rails/tree/4-2-3/actionpack/lib/abstract_controller
# if you need more.
# If you want to access controller methods from your cell, you can hook that up like this
delegate :current_user, :controller_name, :flash, to: :parent_controller
helper_method :current_user
helper_method :controller_name
helper_method :flash
# Cells 4 no longer uses action_name.
# This workaround sets it whenever a state is called.
attr_accessor :action_name
def call(state=:show, *args)
@action_name = state
super
end
end
As the render_cell
method was removed in Cells 4, we will place it back in our ApplicationHelper.
This throws a deprecation warning, so you should be able to pick out old render_cell
calls quite easily.
module ApplicationHelper
# Cells 3 style cell render call.
def render_cell(name, state, *args)
cell(name).(state, *args)
end
deprecate :render_cell
end