Happy New Year to all my fellow readers! I hope you had a good party!

In this post I wanna clarify why representers in Roar are much more versatile than one might think at first sight.

Model != Resource

I know, Rails teaches us that every resource is a model with exactly one representation. This is wrong. Not only can a resource be just anything, ranging from simple 1-to-1 mappings of database rows to virtual models like a workflow but also can your business models be represented in completely different contexts.

Let’s get back to our fruity example to learn more about this.

orange = Fruit.find_by_title("Orange")
orange.extend(FruitRepresenter).to_json
#=> {"title":"Orange","colors":["orange"]}

In the last discussion we had a Fruit and a Bowl model which were represented in their respective resources. While the fruit just contains some properties the bowl was a composition thereof. This is pretty “rails-conform” (I use this word with a negative undertone) and can simply be abstracted to hundreds of projects where people expose users, blog posts or events in their resources. This is what we call a 1-to-1 mapping of model to resource.

Let’s have some Booze!

We wrote a simple FruitRepresenter for mapping apples, lemons or oranges to documents, and we had the BowlRepresenter to provide documents for fruit collections. That was nice. But you can do more with fruits. Why not open a distillery and make some good booze from pears or grapes?

What that means for our REST API is that we have to represent fruits as ingredients. We also want to document what fruits are contained in a bottle of schnaps.

module IngredientRepresenter
  include Roar::Representer::JSON
 
  property :title
  collection :tastes_like
end

The new IngredientRepresenter looks a bit similar to our FruitRepresenter, however, it represents a fruit in another context.

pear = Fruit.find_by_title("Pear")
pear.extend(IngredientRepresenter).to_json
#=> undefined method `tastes_like'

An exception. While the pear exposes a #title method it does not have a #tastes_like method. Why did I do that? I wanted to emphasize that the representer doesn’t guess anything from the represented object (the pear). It is up to the fruit to provide decent accessors like the #tastes_like reader. No magic or implicit semantics in Roar. And this is a good thing.

Another Context, Another Module.

We could easily push the missing methods into the IngredientRepresenter itself, but we will learn in an upcoming post that it is better to provide additional accessors in a separate module.

module Ingredient
  def tastes_like
    TastesLike.query(title) # returns array.
  end
 
  def tastes_like=(*)
  end
end

In the reader, we query the world-famous TastesLike™ web service. Since we don’t need a writer, the second method ain’t doing nothing.

pear.extend(Ingredient, IngredientRepresenter).to_json
#=> {"title":"Pear","tastes_like":["pear","mango"]}

Cool, this is a fruit represented in a completely different context. What about the parsing, does that work, too?

apple = Fruit.new
apple.extend(Ingredient, IngredientRepresenter)
apple.from_json("{\"title\":\"Apple\",
  \"tastes_like\":[\"Pear\",\"Apple\",\"Mango\"]}")
#=> #<Fruit title="Apple", colors=[]>

Yepp, parsing an ingredient and mapping it to a fruit also works fine.

Fruits in a Bottle.

Let’s see how collections can be represented in different contexts.

module BottleRepresenter
  include Roar::Representer::JSON
 
  collection :fruits, :class => Fruit, 
    :extend => [Ingredient, IngredientRepresenter]
end

The bottle representer knows that it’s composed of Fruit instances. It does use the IngredientRepresenter for parsing and rendering, though. BTW, if you don’t like the long :extend assignment you are free to “hard-include” the modules directly in your models.

Summary

So what we’re doing here is having one model used in two completely different contexts: the conventional “fruit” context and the “ingredient” context. Imagine you’d be doing this with #as_json and different hash-parsing algorithms in your controllers – good luck.

There’s nothing like giving a quick update about Cells on a rainy sunday evening. Almost a year ago we were happy to introduce state-args into Cells. State-args help to prevent saving state in instance variables and instead pass variables from #render_cell as arguments, making your code more explicit.

One big problem was that filters couldn’t take advantage of that feature, thanks to a design flaw in Rails’ callback implementation.

Example?

Consider the following call to render a freaky bassist cell.

render_cell :bassist, :play, "C-sharp", "4/4"

The cell class wants to process the incoming data in a before_filter.

class BassistCell < Cell::Rails
  include Cell::Filters
 
  before_filter :prepare
 
  def prepare(state, tone, timing)
    @before = "In #{tone} and #{timing}"
  end

What now works with the new cells-filters gem is that filters (here, a before filter) can receive the state-args. The implementation is very simple using the hooks gem for easy peasy hooks and callbacks in Ruby.

However, we introduce a dependency to another gem, that’s why cells-filters was released as a separate gem. Go and try it! We might need to add some more behaviour to it, but please don’t ask me to completely bloat it.

You can still use the old-school filters from the Rails Callbacks module but you won’t be able to retrieve state-args. I don’t feel like fixing this in the Rails core itself as the implementation is a bit too complex for me.

Cells Development and a Roadmap.

Dudes, Cells is getting more and more of a standard in Rails development. In the last year, 2011, we had almost 90.000 downloads – this is awesome! Thank you so much.

We have more plans with Cells for 2012, here’s a short summary what we’re planning.

  • Get rid of the Rails dependency at all. We already got Cell::Base to use cells without a controller. Now we want to go one step further and make cells completely decoupled from Rails. Imagine cells (and, numerous “helper” gems like formtastic) being renderable in Sinatra or without a framework at all.
  • Use tilt as an alternative rendering engine. The Rails rendering layer is outdated and should use an abstracting rendering gem like tilt – until we can achieve this in the core, we will provide this in cells. That’ll make huge parts of cells completely independent from Rails.
  • Screencasts! Yeah, I’m working on a screencast series about cells, best practices and interesting solutions users sent in over the recent years.

Beside that, we’re permanently trying to incorporate the cells architecture into the Rails core. Let’s see where this will lead to in Rails 4.0. Happy new year, and… Cheers!

Those of you having asked for mountable cells will be happy with the recent 3.8.0 release! We entirely removed the ActionController dependency. That essentially means you can have cells outside of the standard Rails stack. Cool, heh?

Cells 3.8.0 Released

Two little things in 3.8 changed. Cell::Base and Cell::Rails are now different classes with different semantics. Don’t panic – if you still derive your cells from Cell::Rails and use the #render_cell interface, only, nothing will change for you.

However, we had to tweak the API of some semi-public methods, here’s the new signatures.

Cell::Rails.create_cell_for(name, controller)
Cell::Rails.render_cell_for(name, state, controller, *args)

Well, nothing serious, it’s just the controller sliding to the end. If you use this anywhere, be sure to change it.

What’s new?

What is new is that Cell::Base is now decoupled from the ActionController. There simply is no AC-reference in Base anymore. However, this reference is still managed in Cell::Rails on purpose:

  • Calls to #url_for and friends automatically query the parent controller for host and action name. This makes it easy to embedd cells into a controller view and still having correct links in the cell.
  • Having the AC reference, people can still use request, params and session – if they need it. We strongly discourage accessing HTTP properties from a view component, though.

Let’s see what the new decoupled Base brings us.

Cells on Routes.

Deriving your cell from Base makes it routeable.

class PostsCell < Cell::Base
  def show
    @posts = Post.find(:all)
    render
  end

Routeable? Mountable? Well, let’s look at config/routes.rb to understand this.

match "/posts" => proc { |env|
  content = 
    Cell::Base.render_cell_for(:posts, :show)
  [ 200, {}, [ content ]]
}

How cool is that? You can mount a cell to a route without the ActionController overhead and still use the rendering, the caching and testing you all love from Cells. And, hey, it’s super super fast now.

The lack of the AC dependency makes cells even more versatile.

More on Routing

Since we got rid of the AC instance we have to take care of our URLs ourself. The cell still has access to all the URL helpers. Nevertheless, those helpers usually query the controller for host name portions, etc. That’s actually very simple with cells, too.

class PostsCell < Cell::Base
  def default_url_options
    {:host => "apotomo.de"}
  end

Just override the #default_url_options method as used from AC. This allows using the URL helpers as usual.

PostsCell.new.posts_url
#=> "http://apotomo.de/posts"

Let me know how these changes work for you! I’m eager to see new cases of applications in the next weeks.

We talked about Representers earlier last week. Today, I wanna describe DCI and how it fits perfectly together with representers in Roar.

What is DCI?

For years we’ve been taught that “Fat Models, Skinny Controllers” is the way to organize code. Push all your domain code into your ActiveRecord classes. Many people, including me, agree that this is bullshit. This leads to bloated classes, usually combined with one or two object instances taking care of an entire workflow (aka request).

DCI is an architectural pattern that makes the model “fat-on-demand”: Data objects are enhanced with roles at runtime, but only when needed.

The DCI pattern consists of three concepts.

  1. Data objects are supposed to contain application data. Nothing else. This would be your ActiveRecord row instance, but without any predefined behaviour. Just data.
  2. Context objects define what is done in the current workflow. In Rails, a controller running an action could be a context object.
  3. Roles are behaviour for data objects in a particular context. In Ruby, a Rails controller could mixin a module (a “role”) into an empty model row and thus let it process something.

Hooray for DCI – But Why?

Now the thing is, I absolutely hate to hype something (except stuff I did, of course). However, DCI makes code better maintainable, easier to follow and way easier to test. Period.

BTW, did you already check out my new Roar gem? It’s hip!

Think of a classical model found in many Rails applications with maybe one hundred methods. Or fifty. Fifty methods to interfere with each other. In a DCI setup, an object has a limited behaviour scope. The limited knowledge makes it easier to debug and predictable.

One Model, Multiple Faces

Since representers are modules they fit perfectly into the DCI approach, making them roles. Let’s consider the fruit representer from last week, again.

require 'roar/representer/json'
 
module FruitRepresenter
  include Roar::Representer::JSON
 
  property :title
  collection :colors
end

You still can include this representer into its “host” class directly.

class Fruit
  include Roar::Representer
  include FruitRepresenter
end

The problem now is that the Fruit class is limited to one representation, only. Forever and a day you may only render one particular representation. The key about representations, however, is that one model may be represented by multiple, yeah, representations.

Now, back to the start, let’s assume the Fruit class is some empty ActiveRecord class without any prior knowledge of representations at all.

class Fruit < ActiveRecord::Base
end
 
lemon = Fruit.from_json("{\"title\":\"Lemon\"}")
#=> undefined method `from_json' for Fruit:Class

Yeah, there is no #from_json class method.

Representers On DCI

In order to use the DCI approach, we first need an instance. Here’s how the lemon instance, and only this instance, can be extended with the fruit representer.

lemon = Fruit.new.extend(FruitRepresenter)
lemon.from_json("{\"title\":\"Lemon\"}")
lemon.title #=> "Lemon"

Awesome! The built-in Ruby #extend method makes the lemon instance aware of its representation and mixes in #from_json and friends.

Naturally, this works in both ways.

orange = Fruit.find_by_title("Orange")
orange.extend(FruitRepresenter).to_json
#=> {"title":"Apple","colors":["green"]}

The mixed-in representer also lets us render the JSON document.

Gimme Complexity!

On a flat level with single objects, this works out-of-the-box with recent Roar/representable versions. Problems arise when we have nested setups.

module BowlRepresenter
  include Roar::Representer::JSON
  include Roar::Representer::Feature::Hypermedia
 
  property :location
  collection :items, :as => Fruit,
    :extend => FruitRepresenter
 
  link :self do
    "http://bowl/#{location}"
  end
end

Using the :extend option we can give representable a hint about the representer to use when rendering/parsing contained objects.

And, hey, this works.

empty_bowl = Bowl.new
empty_bowl.extend(BowlRepresenter)
emtpy_bowl.from_json("{\"location\":\"kitchen\", \
  \"items\":[{\"title\":\"Lemon\",\"colors\":[]}]}")
 
puts empty_bowl.items.first.title #=> "Lemon"

Discussion Needed!

Having representers on an object level makes the whole thing really clean and versatile. You can test document rendering and parsing without polluting classes. And you can have a FruitRepresenter, a RottenVegetableRepresenter and what else you like for your orange instance. BTW, oranges ain’t no vegetables.

We still discuss about the API and need your opinion. Right now, we got this

collection :items, :as => Fruit,
    :extend => FruitRepresenter

Here, :as describes the class that encapsulates the contained data. The :extend option helps representable to find the correct module for the nested item. Now, what about this?

collection :items, :class => Fruit,
    :module => FruitRepresenter

Does that make sense? These options really just describe what’s on the right side of the hash rocket. Thanks to Scott for discussion here. Now, tell us your story!

This post introduces the new Roar gem, a framework-agnostic REST framework for Ruby that puts focus on object-oriented REST documents.

More object-orientation?

The calls for more object-orientation in Ruby frameworks are growing ever louder. Most web frameworks, like Rails, come with a nice database abstraction, a Rack-like HTTP endpoint, routing, and a template engine. It’s the lack of additional abstraction layers that make many programmers ask for “more OOP”.

Already yawning? Yeah, I wrote about that earlier this year. Let’s talk about working solutions now. Let’s talk about REST.

REST is about Documents!

REST is not only about pretty URLs. The problem ain’t URLs at all. Most frameworks have a decent routing layer to connect resource logic (aka controllers) to URLs. However, the key of REST is pushing documents between clients and servers, so why don’t we finally focus on documents?

It’s the document parsing, processing and rendering that makes our heads spinning.

Note: I here use the terms representation and document interchangable just because I can!

Parsing and Processing

Both clients and services have to parse incoming documents. Consider this JSON document.

{"title":  "Lemon",
 "colors": ["green"]}

This could be sent to a resource to create a new fruit, or be retrieved by some client which issued a GET request.

In Rails, and many HTTP gems, this is automatically parsed using a JSON gem.

params = JSON['{"title":  "Lemon",
                "colors": ["green"]}']
 
params["title"] #=> "Lemon"
params["colors"][0] #=> "green"

We’re using a hash access to read properties from that document. This is handy! Now, assume the sender forgot to include the colors.

params = JSON['{"title":  "Lemon"}']
 
params["colors"][0]
#=>NoMethodError: undefined method `[]' for nil:NilClass

An exception, shit! While processing the parsed document (aka hash), we have to take care of missing keys, wrong types etc. We as the consumer have to know about all the pitfalls with this particular document.

Rendering

Now that our parsing and processing code is finished, how do we render outgoing representations? We could use #to_json.

@lemon.to_json(:only => [:title, :colors])

Being a quick solution for rendering small models this approach hits the wall when we have nested models but still want a plain JSON representation, or when we want to embed hypermedia. Also, we put “REST” logic into our database layer. It’s up to you to judge.

What about template languages? Let’s try jbuilder for JSON rendering.

Jbuilder.encode do |json|
  json.title  @lemon.title
  json.colors @lemon.colors
end

Nice! But, wait. How do I test this? Can I test this separately? What if I want different representations for the same model? Do I need different templates? And… is it cool to have format knowledge both in our parsing layer and in our rendering layer? I mean, both need to know about the title property and the colors array.

Representers: OOP to our Documents!

I won’t further discuss the shown concepts here. Let me just criticize that they are not object-oriented and encourage the distribution of document internals about the entire framework.

Here’s how representers can handle all that and make you a happy man at the same time!.

require 'roar/representer/json'
 
module FruitRepresenter
  include Roar::Representer::Base
 
  property :title
  collection :colors
end

This is all we need to declare the basic syntax of the fruit document. Note that it resides in a module which can be used anywhere in your app.

Rendering a Lemon

Now let’s say our database layer provides us a class Fruit with ActiveRecord-like behaviour.

lemon = Fruit.new(:title => "Lemon")
puts lemon.title #=> "Lemon"

Since the representer knows everything about the document format it can be used for rendering JSON. We just have to include the FruitRepresenter module into the class and new methods will be available.

Fruit.class_eval do # DB layer.
  include Roar::Representer::JSON
  include FruitRepresenter
end
 
lemon.to_json
#=> "{\"title\":\"Lemon\",\"colors\":[]}"

Awesome, the FruitRepresenter module gives us a #to_json method. Internally, this method compiles the JSON document by asking the represented object (aka lemon) for its properties and values. Remember, the representer knows about those properties, since we declared them. It does not know anything about ActiveRecord and the like.

Now, what about parsing?

Parsing a Lemon

The great thing about representers is: they work bidirectional. That alone is one of the main advantages to many other gems out there. Bidirectional? Let’s just see what that is.

orange = Fruit.from_json("{\"title\":\"Orange\"}")
puts orange.inspect
#=> #<Fruit:0x9df73a8 @title="Orange", @colors=[]>

We can parse representations and create objects from it! That’s bidirectional: rendering and parsing is combined in one representer.

Again, the representer does not know anything about the underlying database – it just creates an object it was mixed into, reads from the document and assigns properties using polite setters. Nothing more, bro.

Don’t like the class method? If you already have an instance, you can use #from_json on the instance.

orange.from_json("{\"title\":\"Yummy Orange\"}")
orange.title #=> "Yummy Orange"

Nesting Representers

Now that we have fruits, lets put ‘em in a bowl. A fruit bowl contains a list of fruits.

bowl = Bowl.new
bowl.items << lemon
bowl.items << orange

In order to bind the fruit bowl to a REST resource we write another representer module.

module BowlRepresenter
  include Roar::Representer::Base
 
  property :location
  collection :items, :as => Fruit
end
 
Bowl.class_eval do # DB layer.
  include Roar::Representer::JSON
  include BowlRepresenter
end

Properties can be typed using the :as option. The target class must be a representer, too. That’s the only requirement.

bowl.to_json
#=> {"items":[
  {"title":"Lemon","colors":[]},
  {"title":"Orange","colors":[]}
]}

Typed properties allow us to build more complex representations without breaking with OOP. The collection assignment makes building lists as easy as possible. And if you still need to tweak things, there are some helpful configuration options around – more on that in one of the next posts.

Representers love HATEOAS

HATEOAS? Check out this talk I gave if you want to learn about Hypermedia and HATEOAS.

Hypermedia helps clients to operate the API without having to compute URLs. We want hypermedia in our documents.

module BowlRepresenter
  include Roar::Representer::Feature::Hypermedia
 
  link :self do
    "http://bowls/#{location}"
  end
end

Including the Hypermedia feature dynamically adds a new method #link to our representer module. What does it do?

bowl.location = :desk
bowl.to_json
#=> {
"items":[
  {"title":"Lemon","colors":[]},
  {"title":"Orange","colors":[]}],
"links":[{"rel":"self","href":"http://bowls/desk"}]
}

Seems like an easy way to embed links in our documents. In roar-rails the Rails URL helpers work like a charm within the link blocks – making it super simple to provide hypermedia to consumers and still being railsy.

Representers on the Client Side

Ok, representers basically are plain modules. Why not use ‘em on the client side as well? The client doesn’t have access to the model layer – if it does, something’s wrong! However, it’s absolutely ok to share the representer modules.

class Bowl
  include Roar::Representer::JSON
  include Roar::Representer::Feature::HttpVerbs
  include BowlRepresenter # from a gem.
end

See how we simply use an empty class with the mixed-in representer on the client side? Remember, we don’t want to have access to the database here.

The next step is creating a new fruit bowl.

bowl = Bowl.new
bowl.location = "kitchen"
bowl.post!("http://bowls")

This code is enough to send a POST request to the specified URL. The bowl instance will serialize a JSON document, send it to the URL using the HttpVerbs feature, receive the new bowl, deserialize it and update its properties accordingly. You may know this behaviour from REST client gems like ActiveResource – here, with less code and manageable complexity.

Consume Hypermedia, it’s gooood.

The representer also makes it easy to extract hypermedia links from documents.

bowl.links[:self]
#=> "http://bowls/kitchen"

No parsing needed, the representer knows where to find your hypermedia. How cool is that?

XML is not a Crime!

Roar comes with both JSON and XML representers.

module BowlRepresenter
  include Roar::Representer::XML
end
 
bowl.to_xml
#=> '<bowl>
#  <link rel="self" href="http://bowl/kitchen"/>
#</bowl>'

Now choose if you want JSON or XML – it’s up to you! I still don’t understand the XML hating – did I miss something or is it just “too java”?

Roar – and more?

The Roar project is still evolving. However, the current API is almost stable. New features, new concepts, testing helpers, etc will be added over time just like in every framework. Roar is framework-agnostic and can be used anywhere, as long as it’s Ruby.

Its modulare feature architecture makes it easy to extend your documents. Currently, we have some exciting on-going brainstorming and hacking on features like client-side caching in the representer instance, generic error handling, validations, DSLs, … We need you to try it out, complain, propose, help, and spread the word. Thank you for reading until here, you rock!

Today I had an interesting experience which I’d like to share with my friends. No, I didn’t discover my dark side, I knew that before. What I found out is that mocking as a test method comes in handy once you get it.

Why Don’t You Use RSpec?

I’ve never been an RSpec fan. Not that I don’t like the BDD-approach, which I do appreciate, I was always scared about its internal complexity. I happened to stay with MiniTest, and this has nothing – and i mean nothing – to do with the opinion of Mr. Rails.

Now, I don’t say that RSpec sucks and is too complex. This would be bullshit and I might even soon switch to using this powerful framework (just to make my friend Justin happy) but right now, this test framework still is too powerful for me.

1
2
3
4
5
6
7
8
9
10
class StringTest < MiniTest::Spec
  describe "String" do
    before do
      @string = "Be nice."
    end
 
    describe "#to_xml" do
      it "returns a string" do
        assert_kind_of String, @string.to_xml
      end

That’s pure MiniTest code, included in Ruby 1.9 and working out-of-the-box.

Testing with Assertions Is Not A Crime!

What MiniTest::Spec gives me is basically a BDD interace for classical testers. I say classic as I learned that testers not using expectations are called classic. Old school. Yo.

I can use the keyword methods describe and it to phrase my requirements to the object (line 2 and 8). Before and after hooks provide convenient setup and teardown blocks (line 3).

However, I still use assertions rather than matchers as found in RSpec. I could use matchers, though. MiniTest provides these.

  it "returns a string" do
    @string.to_xml.must_be_kind_of String
  end

Wow, this is “better readable” in many people’s opinion. I still prefer assertions. But that’s not the point of this essay. What I was going to talk about is mocking. Right, mocking.

Who needs Mocking?

Now let’s say my #to_xml method accepts an additional parameter to configure the behaviour. We’d have to test that, too.

  it "accepts the uppercase option" do
    assert_equal @string.to_xml(uppercase: true),
      "<STRING>BE NICE.<STRING>"
  end

This could go on forever, and we test all the features that the method provides in numerous test cases – or its – uppercase, lowercase, reverse, whatever.

Until now, I’ve been testing only using state verification. I run the method and test the state of my string instance afterwards using assertions. This is called state verification.

Purposeless, I now decide that my app needs another method. Here’s the implementation.

class String
  def to_exemel(options={})
    log "stupid phonetic alias called"
    to_xml(options)
  end

I told you, it doesn’t make any sense. What I want to point out is, the method #to_exemel delegates its arguments to the #to_xml method, which we already tested thoroughly.

Expect the Unexpected!

Testing the logging makes sense, I already use mocking here, as I mock the #log method. More on that in a minute.

1
2
3
4
5
6
describe "#to_exemel" do
  it "delegates to #to_xml" do
    String.any_instance.expects(:log)
 
    @string.to_exemel
  end

However, testing all the behaviour of #to_xml again doesn’t. Here, I found out that mocking is cool, too.

1
2
3
4
5
6
7
8
describe "#to_exemel" do
  it "delegates to #to_xml" do
    @string.
      expects(:to_xml).
      with(:uppercase => false)
 
    @string.to_exemel(:uppercase => false)
  end

First, we define expectations: In the ongoing test case, the #to_xml method must be called on the @string instance along with the specified options hash (line 3-5).

I then call the actual method which is subject of our test. The method will be run – and the mocking framework internally checks, if the #to_xml method is really invoked the way we want it (line 7). If it doesn’t, the test will fail!

I Never Knew It’s Called Behaviour Verification!

What we do here is behaviour verification – we no longer have an assertion checking the final string state (we could do that additionally) but set up an expectation, which changes the workflow of our test slightly.

  • I saved a lot of lines of test code since I do not assert all of #to_xml’s features in the #to_exemel method, again. This is cool.
  • Nevertheless, after mocking my test case includes a lot of knowledge about internal implementation. The test now’s aware that #to_exemel forwards to #to_xml. Changing this implementation detail within the class will break the expectation tests, although the second method might still work from the public perspective.

It seems to be a matter of careful choice when to use mocking, and when not. I for myself still lack the experience to make smart assumptions here. However, I can call now myself a Mocker according to Martin Fowler’s great post, which you should definitely read if you haven’t, yet!

Mocking frameworks?

I found mocha to be a very simple to use mocking framework integrating seamless into MiniTest. Never peeked at the source, though. RSpec comes with a powerful mocking functionality as well, which most people might know, use and appreciate.

Outsights?

The example was stupid, I hope I still could point out the difference between status verification and behaviour verification in this short post. Let me know what you think about it. Good nite, and Mock’n‘Roll!

The 4th episode discusses partial updates of widgets.

  • Using the event instance to transport payload data between widgets.
  • Updating the page by sending back arbitrary JavaScript and markup from trigger states.
  • Extracting partials to separate widget views.
  • Using #render in both views and states for DRY code.

BTW, please feel free to send me feedback or requests for future episodes – I appreciate!

Is it a good sign when a minor release doesn’t yield any stunning new features? When there’s nothing breathtaking to talk about? I guess with Cells it is – the gem finally seems to get into what it should have been 6 years ago: a mature view components framework for Rails.

The 3.7 release, again, lost code – it’s goal was getting rid of the #options hang-over which succeeded. No more state in your cell, except if you choose to do so.

Here’s what changed.

Rails 3.x

Well, needless to say that 3.7 still runs with Rails 3.0 and 3.1. We were able to incorporate a couple of changes into Rails 3.1 to make Cells’ life even easier. Thanks, José for being such a patient maintainer and happy birthday to you ;-)

Caching Inheritance and Conditionals

Arthur Gunn brought us the :if option for caching. So, if you ever needed conditional caching in your cell, here it is.

class CommentsCell < Cell::Base
  cache :show, 
    :if => proc { |cell, opts| opts[:enable_cache] }

To pass in the required options, I’d use #render_cell.

render_cell(:comments, :show, :enable_cache => false)

See how easy it is to bypass (or enable) caching using :if? Also, don’t forget that the second block parameter is the options passed to #render_cell, which brings us to the next core change.

BTW, as a nice extension and in good OOP manners cpb made the cache configurations inheritable. A cell derived from CommentsCell will automatically inherit the cache setting for #show – no need for redundancy.

No more Options!

Luckily, we were able to remove the #options behaviour from Cells – it added unnecessary state, and we try to avoid internal state wherever possible (unlike the Rails core). Where you used to access the magic options hash in a state method you now use explicit state-args.

class CommentsCell < Cell::Base
  def show(user, comments)
    @user, @comments = user, comments
    render
  end

Since the method expects arguments (“state-args”), here’s how you’d pass them into.

render_cell(:comments, :show, user, @comments)

Any additional argument after the state name (2nd argument) is passed to the state. The rest is up to you.

If you want the old behaviour with the options hash that was “simply there”, just include the Deprecations module.

class CommentsCell < Cell::Base
  include Deprecations
 
  def show
    @user = options.first

Test your View Assigns

Another small addition is the #view_assigns method in Cell::TestCase. This works just like in conventional controller test (both Test::Unit and RSpec).

it "should assign correct values" do
  render_cell(:comments, :show)
  assert_equal @user_1, view_assigns[:user]

The view_assigns hash captures all instance variables that were assigned in the rendering cycle. Some people may like that – I don’t. However, here it is.

Have fun with Cells! ;-)

Released Apotomo 1.2

I just released Apotomo 1.2 today. Yeah. People screaming, clapping, hooting, going nuts, I can hear it. Ok, this release is nothing special, but it fixes a severe bug. No, it wasn’t just a bug, it was more, it was a design flaw!

What’s new?

Nothing. I already said that. However, in the last release we added some option that allowed the following.

  responds_to_event :click, :passing => :root

The :passing option makes it easier to attach event handlers to other widgets, for instance, :root. This worked fine on a 2-level setup, but having deeper widget trees, this failed silently.

The problem – in short – was that the parent widget sometimes wasn’t available yet when the child set up its event handlers. The fix: The constructor Widget.new now requires the parent widget as the first argument. Makes things way simpler and explicit.

What can I do with that?

Well, you now can safely use the :passing option anywhere. You can also use root and parent in your has_widgets blocks now. They will be what you expect.

class CommentsWidget < Apotomo::Widget
  has_widgets do |me|
    me.root # => returns the real root
    me.parent # => well, yeah...

All in all, the new constructor makes the Apotomo core a lot cleaner and more understandable.

What changed?

Be warned that widget doesn’t return a real widget instance anymore (line 3). Don’t be worried, you have plenty of ways do to what you want.

1
2
3
4
5
6
7
8
has_widgets do |root|
  root << widget(:comments) # This still works.
  widget(:comments).markup! # This doesn't.
 
  root[:comments].markup! # This works, of course.
 
  comments = CommentsWidget(root, :comments) # works.
  comments.markup! # yepp, works.

Remember, you’re free to use the real constructor in a has_widgets block (line 7) if you need to grab the created instance for whatever reason. You could also use the block for that.

  has_widgets do |root|
    root << widget(:comments) do |comments|
      comments.markup!
    end

In short, the << widget(..) syntax now is a DSL construction, what happens internally is a call to the actual constructor. Easy.

The second big change is that we got rid of the after_add hook. Since widgets receive their parent explicitely in the constructor, there’s no need for a hook after adding a widget. Use the after_initialize hook for that.

Check the CHANGELOG for further notes and let me know if the changes work for you.

Kevin- thanks for donating ;-) LOVE to Austin!

When I started using Rails years ago I found helpers extremely cool. I could call a method in a view and it would help me by doing something. The method was simply there, no need to worry about its source and how to access it, just call it.

I got older, wiser, and more opinionated. I still like the concept of helpers – of methods. However, the way helpers are implemented in Rails sucks. Also, having object-disoriented functions in your view brings us back to the years where OOP still had to be invented.

In this post I’d like to discuss why I dislike Rails helpers and how to get out of that misery.

What’s a helper?

In Rails, a helper is a function.

<h2>
  Hello, <%= capitalize @user.name %>
</h2>

Here, the #capitalize method helps me capitalizing the username, which is freaking awesome. As this is pretty simple behaviour, let’s call helpers like this utility methods. They modify the input parameter, compute something or escape strings. Pretty straight-forward.

As a second example, I’d like to show a more complex helper.

<div id="sidebar">
  <%= render_news_for @user %>
</div>

This helper will iterate through news items for a particular user and render markup, maybe using several partials. Since it actively renders templates, let’s call this a view component.

Why are helpers shit?

At first sight, using helpers rocks. Capitalizing a string works like a charm – I simply call a function and it happens.

However, looking at the first helper I can identify several drawbacks.

module StringHelper
  def capitalize(string)
    string.capitalize
  end
  • Helpers in Rails are modules, which do not allow inheritance. If I’d need a foreign method I’d have to include another module into the helper module. Not a big deal.
  • Using the #capitalize methods happens without a receiver. The method is globally available in the view since Rails somehow mixes the helper into the view. So, what happens if I have two #capitalize methods in two different helpers mixed in the same view? I don’t have a clue. Do you?

Before getting to solutions, let me discuss another issue with helpers: Another real problem is the implementation in Rails – how these functions are made available to the view.

Helpers in Rails

Again, I’m not talking about how #form_for or #url_for are written internally, I’m talking about how these methods get into the view.

In Rails 3, all helpers are mixed into the view automatically, you still can insert additional modules using the controller’s helper facilities.

class HomeController < ApplicationController
  helper StringHelper

It’s not that the implementation as-it is bad code or something, it is the idea of magically mixing methods into the view instance to make them globally available. This adds complexity to the Rails core, namely around 280 LOCs. Just to mix some methods into the view.

Helpers are shit.

I desperately tried to demonstrate the major disadvantages of helpers in Rails. To summarize.

  1. I like utility methods. There is nothing wrong with having those little “helpers” in your view. What I don’t like is that they are called without an obvious receiver – they look and feel like functions. This is wrong.
  2. The way Rails mixes helpers into the view is error-prone and sucks. Following a slightly different approach there’s no need for all that complexity.
  3. Complex helpers suck. I do believe in view components and the need for those but they shouldn’t be rendering helper methods.

Moaning is fine, but let’s see how things could be changed.

Solution 1: Push Utility Methods into Decorators.

Luckily, a bunch of people feel uncomfy about the current helper architecture. My friend Steve Klabnik wrote a nice article about Jeff Casimir’s draper gem which introduces the Decorator pattern into Rails’ view layer.

Basically, the draper gem wraps existing model instances and provides utility (“helper”) methods on the decorated instance. Here’s an example.

class ArticleDecorator < ApplicationDecorator
  decorates :article
 
  def published_at
    model.published_at.strftime("%A, %B %e")
  end

Now that we defined the Decorator we can use it to wrap the actual model.

@article = ArticleDecorator.decorate(Article.find(1))

The wrapped model can then be used in the view.

<li>
  <%= @article.published_at %>
</li>

The interesting point is that we call the utility helper on the wrapped model which clearly states a receiver. No need for a homeless, global helper function. This way, we can have cleanly separated, domain-focused helpers for models. Decorators also allow inheritance and all other OOP features, since they are just objects.

Decorators are a solid technique when it comes to – well – decorating models. What can we do if there’s no matching model, for instance, when we need to call #url_for?

Solution 2: Use the Controller Instance as View Context

To learn more about that we should peek at the rendering cycle in Rails. What happens when a controller renders a template?

  1. An ActionView instance is created (this will be the “context”).
  2. The controller manages a magical module that contains all helper methods. This module is now mixed into the ActionView instance to make helpers available. I already discussed the need for hundreds of lines of code in order to achieve this “knowledge transfer” from the controller to the view.
  3. Next, instance variables from the controller are copied to the view instance as well.

These are 3 completely useless steps. Completely. Every template engine, whether it be Rails’ internal or tilt requires a so called view context whenever a template is rendered. Both instance variables and methods (that is, helper calls) used within the template are looked up on this view context instance.

Now, there is absolutely no reason for having a separate ActionView instance as view context! We can simply use the controller instance as context object and everything would work. No need to copy over variables, no need to transfer “helpers” to the view instance.

“Helpers” would be modules mixed into the controller – and that’s it.

class HomeController < ApplicationController
  include UrlMethods
 
  def show
    @link = link_to(home_url)

Notice how we can use the mixed-in “helper” methods in the controller instance – we simply included them.

<a href="<%= home_path %>">

The cool thing is we can also use the utility methods in the view which will be invoked on the controller instance, again. No magic copying, just modules.

The Cells project currently is experimenting with this approach and things work out fine. Will blog.

I can hear people now moan about too many mixed-in methods in their ActionController – and they are right! Again, this is due to Rails’ monolithic view/controller design. If one single controller is responsible for rendering an entire web page, then this controller has a lot of responsibilities – too many. That’s why we should use Cells to split up the view into components, which is discussed next.

Solution 3: Use View Components instead of Complex Helpers.

Helpers that compute data and render partials are scary. Often, there is too much concerns in the little helper.

def render_news_for(user)
  items = user.find_news
  render "shared/news", :items => items
end

Let’s assume the _news partial should be reusable throughout your application, needs some special helper function #sanitize and does caching.

<% cache do
  <%- for item in items %>
    <%= sanitize item.text %>
  <% end %>
<% end %>

Several problems here.

  • Every controller has to take care of requiring the special SanitizerHelper for the partial.
  • Caching happens by using helpers, again, which is no good .

Moving the partial and its behaviour into a cell would cleanly separate concerns. The cell could be used as view context and thus provide utility methods itself.

class NewsCell < Cell::Base
  cache :show
 
  def show(items)
    @items = items
    render
  end
 
  def sanitize(string)
    # ...
  end

This creates a reusable view component with a defined scope. Intentionally, I keep the cells discussion briefly as this would break the mold.

Combining Decorators and Cells

Using draper’s decorators within cells is what I figure a fantastic option. Where the decorator cleanly wraps the model object and provides utility methods for tweaking model data the cell separates the concern into a reusable view component, provides a limited scope and generic helper methods (like #url_for), and even caching!

I really don’t care whether draper, cells, or whatever replaces helpers – all I want is less magic code, more object-orientation and rock-solid software. This was a long post – gimme some feedback in the comments section or tweet me