Reform gives you a new abstraction layer for handling forms without hard-wiring them to your database. It just went 0.2 bringing you nesting to easily create forms for has_one and has_many relationships.

Composition Forms.

In earlier versions, reform could automatically build a composition object to handle forms for multiple, unrelated objects.

class SongForm < Reform::Form
  include Reform::Form::Composition
 
  property :title,       on: :song
  property :written_by, on: :artist
end

This still works, however, the DSL module got replaced by Composition, which you must include to make reform understand what this on: option is about.

SongForm.new(
  song:   Song.find(1), 
  artist: Artist.find(2))

When creating a composite form you still need to pass in the separate objects using a hash.

One-To-One Relationships.

Technically, every kind of model relations could be handled with this Composition trick. Nevertheless, the new reform makes it super easy to compose forms of multiple associated models.

Say we had the following database configuration.

class Song < ActiveRecord::Base
  has_one :artist
end

A classic 1-to-1 association! Yay!

Although I’m using ActiveRecord to demonstrate reform’s new goodies, it is important to understand that this gem doesn’t speak a single word of ActiveRecord – it uses public readers and writers, only.

To create a form to handle fields for both Song and Artist you can now define nested forms.

class SongWithArtistForm < Reform::Form
  property :title
 
  property :artist do
    property :name
    property :gender
 
    validates :name, presence: true
  end
end

See how you can now pass a block to property and simply create another form class inline? Awesome, isn’t it?

(Tech note: the new inline representer feature in representable 1.6 made it extremely easy to implement nesting in reform).

Render The Association Form.

Now, check out how this form is instantiated.

@form = SongWithArtistForm.new(Song.find(1))

As you’re not using the composition feature, all you do is pass in a single model.

song = Song.find(1)
song.artist
#=> <0x999#Artist name: "Paul Gilbert" gender: "m">

Since you have a nested setup, this model is required to respond to #artist, which in turn must expose readers for name and gender.

That should save you some work when creating the form.

Even cooler: rendering the form using Rails’ (nested) form helpers now works out-of-the-box – without inheriting all the flaws from accepts_nested_attributes code.

= form_for @form do |f|
  = f.text_field :title
 
  = fields_for :artist do |a|
    = a.text_field :name
    = a.text_field :gender

This just works, so you don’t have to worry about rendering the proper markup – the most annoying part when writing forms in my opinion.

Validating And Processing.

All you need to do now is passing the submitted data to reform.

@form.validate(params[:song])

This will run all validations from the form, even the nested one from the artist form.

Error messages – in case of bull data – can be rendered using the common steps.

- @form.errors.full_messages.each do |msg|
  %li
    = msg

Using the block-less #save will push submitted and validated data to all objects automatically.

@form.save
 
#=> @form.song.title       = "Beachparty"
#   @form.song.artist.name = "No Fun At All"

As before, you can do the saving manually: #save will yield the nested input.

@form.save do |data, hash|
  data.artist.name
  #=> "No Fun At All"
 
  hash[:artist][:name]
  #=> "No Fun At All"
 
  Artist.create(hash[:artist])
end

Here, it’s up to you how to process the nested data. Reform just makes sure things are correctly nested.

One-To-Many Relationships.

You thought that’s it? No way, we also got support for nested collections.

class Album < ActiveRecord::Base
  has_many :songs
end

Mapping this association in your form is pretty straight-forward.

class AlbumForm < Reform::Form
  property :name
 
  collection :songs do
    property :title
  end
end

Creating the form works just like the has_one example.

@form = AlbumForm.new(Album.new(
  songs: [Song.new, Song.new]
)

Here, it is important the Album#songs returns a collection of objects.

Rendering, validating and displaying errors works likewise.

You can use fields_for and Rails will render the form collection. You could also go manually through the collection.

= @form.songs.each_with_index do |f, i|
  = text_field_tag "title_#{i}" ..

Currently, it’s your job to keep the number of forms visible on the page in sync with the forms created internally. That is why I pass in two new Song instances to Album, as this will make two nested song forms appear after rendering.

If this feels inconvenient, we’re open for suggestions.

When saving sane data, you get a collection of data for the song forms.

@form.save do |data, hash|
  data.songs[0].title
  #=> "Sanity"
 
  hash[:artist][:songs][0][:title]
  #=> "Sanity"
end

From Here.

The new nesting feature was requested by many users and we’re really happy to release this version of reform. There will surely be issues with certain use cases and we can’t wait for your feedback!

It has been a while since I last blogged about representable – Ruby’s mapping gem that helps you rendering and parsing representations. To be precise, it has been more than 4 ½ months of reflecting, testing and refactoring, and I am happy to finally announce great new features.

Inline Representers

When nesting representations, you have to tell representable about which nested representer to use.

module AlbumRepresenter
  include Representable::JSON
 
  property :title
  collection :songs, extend: SongRepresenter
end

This happens using the :extend option. While this provides a great modularity for the SongRepresenter, it can feel clumsy when you don’t intend to reuse it anywhere else.

You can now define it inline.

module AlbumRepresenter
  include Representable::JSON
 
  property :title
 
  collection :songs do
    property :name
    property :track
  end
end

Just pass the nested representer in a block.

Note that you still have to supply :class when you use the representer for parsing.

  collection :songs, class: Song do
    property :name
  end

And, even better, you can still use :extend with the inline declaration to inherit from a base module.

  property :cover_song, extend: SongRepresenter do
    property :original_composer
  end

This will inherit SongRepresenter’s properties into the inline block.

Inline representers work with both ::property and of course ::collection.

PUT Semantics: Sync Models When Parsing

Representers can also parse documents and create nested objects.

Let’s use the representer we just discussed.

module AlbumRepresenter
  include Representable::JSON
 
  collection :songs, class: Song do
    property :title
  end
end

Now, representable gives us parsing for free, as long as we provide the :class option.

album = Album.new.extend(AlbumRepresenter)
album.from_json('{songs: [{title: "Eruption"}]}')
 
album.songs.first.title #=> "Eruption"

Internally, what happens is that representable will create a Song instance for each element in the collection.

It does the following per parsed song.

Song.new.extend(SongRepresenter).
  from_json('{title: ..}')

What if you wanna update an existing Song instead of creating a new? Representable now comes with :parse_strategy which allows exactly that.

module AlbumRepresenter
  include Representable::JSON
 
  collection :songs, parse_strategy: :sync Song do
    property :title
  end
end

As we provide :sync, representable will no longer create an object but call from_json on the existing item.

album = Album.find(1)
album.songs.first #=> #<Song:0x999 title: "Panama">

Note that the Album instance contains one song already.

album.extend(AlbumRepresenter).
  from_json('{songs: [{title: "Eruption"}]}')
 
album.songs.first #=> #<Song:0x999 title: "Eruption">

What happened is that representable used the existing song instance when parsing, resulting in the song being renamed from “Panama” to “Eruption”. Both great songs.

This behaviour roughly implements PUT semantics in a REST service when updating an existing resource. And it works with properties and collections.

Predictable Coercion

You can use the virtus gem with representable to have coercion when representing objects.

module SongRepresenter
  include Representable::JSON
  include Representable::Coercion
 
  property :title, type: String
  property :track, type: Integer

We used to mix in Virtus directly into the represented object, which gave us virtus’ accessors for free, but that also resulted in unpredictable behaviour due to virtus’ dynamic nature.

Coercion is now handled in a separate object and only happens inside to_/from_ invocations. Also, you have to add accessors to your properties manually.

class Song
  attr_accessor :title, :track
end

This is a bit more work for you but greatly reduces confusion in the representable gem (and virtus) and makes it predictable – which is what a good gem should be.

What Happened On The Inside?

The Binding class got way to big and static, I had to copy+paste code to make those features work, so I extracted ObjectDeserializer and its brother ObjectSerializer, and some more classes.

Also, a lot of methods from the Representable module itself got moved into a separate Mapper class.

This makes the entire architecture a lot more cleaner, simpler to follow through and easier to replace parts of it. The refactoring of representable will be a part of my upcoming talk at Rubyshift in the Ukraine this year.

You should come, it’s an awesome conf!

Update!

I totally forgot, so I have to add it now: Representable 1.7 also allows overriding properties in inheriting representers.

module CoverSongRepresenter
  include Representable::JSON
 
  # defines property :title
  include SongRepresenter
 
  # overrides that definition.
  property :title, as: :known_as
end

As you can see, consecutively calling property :title will override the former definition. That’s exactly how “proper” inheritance with methods work.

Today I released nit, which is my attempt to provide a small and simple wrapper around git that helps me (and you!) save typing and optimizes git workflows. So I can focus on stuff that really matters.

It’s All About Status!

I found it particularly annoying when I commit and add files with git since I usually copy+pasted the file names manually to git commit which involves keyboard and mouse and so on and so on.

Here’s how nit does it.

$ nit

I just call the blank nit command in my working directory.

# On branch master
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be..
#   (use "git checkout -- <file>..." to discard cha..
#
#   modified:   on_stage.rb  [a]
#   modified:   staged.rb  [b]
#
# Untracked files:
#   (use "git add <file>..." to include in what will..
#
#   brandnew.rb  [c]
#   new.rb  [d]

This is a shortcut to git status with some additional information: The status screen renders a file index for each file which can be used on the command-line.

Indexes per default are characters on the right-hand side of the filename.

#   modified:   on_stage.rb  [a]

This can be configured, in case you prefer digits or want the index to prepend the filename.

Commiting And Adding Files.

Now, having those file indexes you naturally don’t need to provide the entire file name anymore. Just give nit the indexes.

$ nit commit a c

This will interpolate the indexes and run

git add on_stage.rb
git add brandnew.rb
git commit

Note that adding files is obsolete. With nit, you just commit files and it will add them automatically.

The following will do the same, using nit’s auto-expansion and index splitting.

$ nit co ac

Actually, you can use any git command via nit, it will just do the index interpolation.

$ nit diff ac

Ignoring Files.

Often I find myself having +10 files modified and the git status screen gets confusing. This happens especially when refactoring bigger chunks of code.

Mostly, I work on, say, 3-4 files at a time and want to incrementally commit changes in this “file group” while the rest of the modified or added files get in my way.

# On branch master
# ..
#
#   modified:   on_stage.rb  [a]
#   modified:   staged.rb  [b]
#   modified:   lib/new.rb  [c]
#   modified:   TODO  [d]
#   modified:   CHANGES  [e]
#   modified:   lib/new/more.rb  [f]
#   modified:   lib/new/less.rb  [g]
#   modified:   test/new_test.rb  [h]

I could use git stash to hide the changes I’ve made to the other files. After 20 minutes, I will have forgotten the stash, my changes, and I lose parts of my refactoring. Sucks.

Nit allows you to ignore files. They are simply no longer considered in the nit status screen.

$ nit ignore abdeh
$ nit
 
# On branch master
# ..
#
#   modified:   lib/new.rb  [a]
#   modified:   lib/new/more.rb  [b]
#   modified:   lib/new/less.rb  [c]
#
# Ignored files: 5

I found this really helpful as I really just see the files I am working on at that very moment. And – nit reminds me that there’s still other files invisible.

Pushing And Pulling.

And, once I’m happy I just do

nit push

This will find out the current branch and push to origin.

git push origin master

Works for both push and pull.

Summary.

I am aware of the fact that git comes with many of those functions. I just don’t want to remember all the internals, how to configure git, how to change my shell prompt, aliasing git commands, how to use `git commit -p` and so on.

Nit simply reflects many steps of my personal everyday workflow. It really helps me typing less whilst allowing me to keep my hands to the keyboard and away from the mouse and my pants.

No longer must I copy file names but use indexes!

The character indexing makes it super easy to look at the screen while typing.

Ignoring files helps me focusing on my current task, which can be a 5 minute refactoring, without the pain of stashing-and-forgetting.

From Here And On.

The next versions of nit will allow extending the tool with your own commands – either as gems or in a .nit directory. Also, I have several other, breathtaking features planned.

If you want more, just let me know.

And now, give it a go.

gem install nit

Hooks Got Better.

The hooks gem is a very simple way to add callbacks to your objects. It’s less complex than ActiveSupport::Callbacks and allows passing arbitrary data to the callbacks. That’s 3x callbacks in one paragraph.

1
2
3
4
5
6
7
8
9
10
class Uploader
  include Hooks
 
  define_hook :after_save
 
  def save
    @file.save
    run_hook(:after_save, @file)
  end
end

It works by defining a hook (line 4) and calling it wherever you need it (line 8). Note that you can pass arguments to #run_hook which propagates those to the callbacks.

Adding Callbacks.

Now a hook is useless without callbacks.

class Uploader
  # ..
 
  after_save :check
  after_save { |file| file.compress }
  after_save { |file| file.resize }
 
  def check(file)
    valid_upload?(file)
  end

Whenever you run the :after_save hook, it will execute #check, then the two blocks in the order they were added. So far so good.

Stop It!

My friend Fred Wu had the idea to allow halting the callback chain. This might be handy in our case when the check detects a poor file.

  def check(file)
    valid_upload?(file) # returns true or false.
  end

In order to tell hooks to stop executing further callbacks we need to configure our hook.

  define_hook :after_save, halts_on_falsey: true

This will – surprisingly – suppress execution of the two callbacks when #check returns a falsey value.

Return Values Do Matter.

Another nice feature is that #run_hook returns a list of return values from the callbacks.

results = run_hook(:after_save, @file) 
#=> [true, 1024.kb, "200x300"]

Extremely useful if you don’t want to store callback results in a global (brrr) variable. And, just to maximize awesomeness, the results know if the chain was halted or not.

results.halted? #=> false

This gives you a flexible way for an orthogonal callback architecture with a very clean implementation.

Party on, Wayne!

Just recently, we released roar-rails 0.1.0. Hooray. While making it run smoothly with Rails 4, we made ::represents a little bit smarter: representer names are infered better and now support namespaces.

Represents.

You can use roar-rails without configuring it.

class SongsController < ApplicationController
  include Roar::Rails::ControllerAdditions
 
  def show
    song = Song.find(params[:id])
 
    respond_with song #=> SongRepresenter
  end
end

In respond_with, roar-rails will use the passed model’s class to infer the representer name. When rendering a collection, however, the controller name is the base for computation, resulting in a pluralized SongsRepresenter.

Namespacing.

This convention worked well but led to some confusion when controllers were namespaced. Whatever, in 0.1, the representer will always be namespaced (if your controller is namespaced, of course).

module V1
  class SongsController < ApplicationController
  end
end

Both rendering and consuming will infer V1::SongRepresenter and V1::SongsRepresenter by convention. This might break your existing code, as entity representers weren’t namespaced automatically.

Roar-rails only adds namespaces when it infers representer names. That means, when you explicitly specify a name, it will use this and don’t do any maths leaving it up to you.

Configuration Over Convention.

If you’re unhappy with roar-rails’ conventions, you can tell it to behave appropriate with represents.

module V1
  class SongsController < ApplicationController
    represents :json, Song
 
    def show
      respond_with Evergreen.find(1)
    end
  end
end

This will always use V1::Song as the base and not check the rendered or parsed model’s class, resulting in SongRepresenter even you passed in an Evergreen instance.

class SongsController < ApplicationController
  represents :json, entity:     V2::SongRepresenter,
                     collection: V1::SongsRepresenter

Using the :entity and :collection options you can fine-tune which representer to choose. Note that you don’t have to specify both, e.g. if you’re not interested in collections. Who needs collections, anyway?

If you want to compute the representer ad-hoc at run-time, use :represent_with.

respond_with @song, 
  :represent_with => V1::EvergreenRepresenter

Consumption.

Note that the techniques described above work both ways, for respond_with rendering and consume! to parse incoming documents.

module V1
  class SongsController < ApplicationController
    def create
      consume! @song = Evergreen.new
      #=> V1::EvergreenRepresenter
    end

I hope this slightly changed behaviour (spelled the english way as I am in Australia now) gives you a convenient way for using namespaces.

To cut a long story short: Working on a nested form we decided not to go with nested_attributes. In fact, we wanted a form with validations, rendering and processing completely decoupled from the model. I mean, why would a form wanna know about the database layout?

So we, that is one of my lovely co-workers Garrett Heinlen and myself, came up with Reform – a framework-agnostic, anti-database form object.

What Does It Look Like?

Let’s assume for now our form was to create a song request for a radio station – for whatever reason this implies creating both a row in the songs and in the artists table. We use an ActiveRecord example here, however, reform is not database-dependent at all.

class SongRequestForm < Reform::Form
  include DSL
 
  property :title,  on: :song
  property :name,   on: :artist
 
  validates :name, :title, presence: true
end

As you can see, this is pretty straight-forward. Define the layout and throw in some validations.

What Is The Difference?

The form doesn’t know anything about your database. All you do is specifying what fields you want and where to map those. Also, note we’re using ActiveModel’s validations in the class and thus have per-form validations that don’t get in the way in our models.

For a better understanding, here’s how you would instantiate your reform.

@form = SongRequestForm.new(song:   Song.new, 
                             artist: Artist.new)

This would usually happen in your controller action.

Basically, from the key-object hash Reform will create a Composition object that simply delegates accessors to the underlying objects. How does it know how to do that? Well, you just defined it!

  property :title,  on: :song

Calls to #title or #title= will be delegated.

  @form.title #=> @form.song.title

Note that this doesn’t involve any database-magic – it is simple delegation based on your specification.

Rendering.

This simple trick makes it super-easy to use that form with Rails’ form helpers, simple_form or whatever form rendering you fancy.

= simple_form_for @form do |f|
 
  = f.input :name
  = f.input :title

I don’t cover the details here but the form object will even expose the necessary ActiveModel-compliant methods when you tell it to do so.

Processing Evil Input.

Now how do we update our form with incoming data, process it, validate it and display possible errors?

if @form.validate(params[:song_request])

The form comes with a #validate method which accepts a hash of data. Validations you defined will be run and form.errors will return potential errors from your confusing input.

Speaking of confusing: You no longer need attr_accessible or strong_parameters anymore. Why is that? Well, again, you defined the form layout earlier!!! Therefore, the form knows its fields and will simply ignore unsolicited input.

Another sweet feature is that the form will display the user’s input in the fields after a validation – without even touching your models.

@form.title => "Sunlit Nights" # from model.
@form.validate(title: "Scarified")
@form.title => "Scarified" # from user input.

Saving Safe Input.

When you decided that the input is alright you can let Reform save the data.

if @form.validate(title: "Scarified")
  @form.save # @form.song.title = "Scarified"

It will pass the incoming data to the respective models. This is nice, but often you want more control. That’s where a block to #save kicks in.

@form.save do |data, nested|
  data.title #=> "Scarified"
  nested[:song] #=> {title: "Scarified}

The block yields two handy arguments. The first data is a plain list of the incoming and validated data (currently implemented as an OpenStruct instance).

The second nested is a hash keyed following your mapping instructions from earlier – remember, the calls to ::property?

Makes it really easy to use ActiveRecord’s magic without the horror.

@form.save do |data, nested|
  Song.find(params[:id]).update(
    nested[:song]
  )

Why Another Form Object?

I read several blog posts that were really inspiring, however, they were either implementing a create form or an edit form, only. Also, we didn’t like the hard-core ActiveRecord wiring.

Reform gives you all the goodies like validation, parameter filtering and even rendering in a dedicated class. That keeps your UI logic where it should be. Hell yes, forms are part of your UI and shouldn’t be configured in your database models.

In addition to that, Reform gives you all the flexibility to change internals. If you don’t like the automatically created Composition object, use your own. If you don’t like the representable based mapper, make your own. It’s just 100 lines of code so far. Give it a try!

Until today, extend was the only way to inject a representer into a model to render or consume representations. Many people criticised this approach as it adds methods to an object which should rather be treated immutuable. Besides that, using extend seems to affect the performance due to caching invalidation.

song = Song.find(1)
song.extend(SongRepresenter).to_json

As a result, people who actually liked the representer idea declined using it because they were worried about extend. No longer should this keep you from using roar and representable!

Use Decorator Over Extend.

A minor refactoring brought us Representable::Decorator.

class SongRepresenter < Representable::Decorator
  include Representable::JSON
 
  property :title
  property :track
end

Instead of a module, derive a class that exposes the very same DSL that you know from the “old” module representers. BTW, you can also include representer modules into Decorator classes.

SongRepresenter.new(song).to_json

Just pass the represented object into the constructor and let representable do the work. Your models won’t get hurt anymore – promised!

Use the :decorator option where you used :extend in a nested setup.

class AlbumRepresenter < Representable::Decorator
  include Representable::JSON
 
  collection :songs, decorator: SongRepresenter
end

In roar, you might use the Roar::Decorator base class. Pretty cool: roar-rails already supports decorators.

Speed Is Relative.

Several on-going discussions debate whether heavy usage of extend slows down your app. I did a quick benchmark myself where I render an Album instance containing 10,000 Song instances which results in 10,000 calls to extend when rendering the album.

Album.new(songs: 10000.times.collect { Song.new }).
  extend(AlbumRepresenter).
  to_json

I did the same with a Decorator class.

alb = Album.new(songs: 10000.times.collect { Song.new })
AlbumDecorator.new(alb).to_json

Here are the results. I leave it up to you to judge these metrics.

# time with extend   : 0.780000
# time with decorate : 0.600000

It looks as if Decorator is faster – go figure! ;)

Using Decorator With Hypermedia.

There’s a tiny pitfall when using a decorator on a hypermedia-consuming object in roar.

class SongRepresenter < Roar::Decorator
  include Roar::Representer::JSON::HAL
  include Roar::Decorator::HypermediaConsumer
 
  property :title
  link(:self) { song_url(self }
end

Be sure to include the Roar::Decorator::HypermediaConsumer module which will propagate parsed links to the represented object by calling it’s link= writer. You have to provide that as well.

class Song
  attr_accessor :links
end

Now, consuming an incoming representation will set links on the client object.

SongRepresenter.new(song).from_json("..hypermedia json")
 
song.links[:self] #=> "http:songs/1"

Conclusion

Go and use decorators and tell us how you like it. Never shall anyone anymore complain about dirty extendings!

A recent release of representable made it very easy to pass user options like the current_user into the representer.

Basically, you can do things like

@song.to_json(current_user: current_user)

and use those dynamic user options in your representer.

module SongRepresenter
  include Representable::JSON
 
  property :rating, getter: lambda { |opts| 
    opts[:current_user].rate(self) }
end

See how you can inject data from outside?

User Options In Roar-Rails.

This now also works with roar-rails, too! Update to 0.0.13 and feel the ease of passing options to #respond_with.

class SongsController < ApplicationController
  def show
    respond_with @song, user: current_user
  end

As usual, this works both ways, for rendering and parsing. #consume! also accepts options now.

class SongsController < ApplicationController
  def create
    consume! Song.new, user: current_user
  end

Injecting dynamic runtime data into your representers is no longer a pain in roar-rails Several people already reported how useful this new feature is. Thanks!

Overriding Read And Write In Representable.

In representable 1.3.5 we got two new options :reader and :writer for overriding the compilation of the document and parsing a property from an incoming document.

Using the :writer option gives you access to the entire compiled document (e.g. a hash or a Nokogiri::Node). The lambda also has access to the user options, if there were any passed.

property :title, writer: lambda do |doc, args| 
  doc["title"] = title || original_title
end

As you can see it’s up to you as the lambda author to fill in the necessary fragments into the document – representable won’t do it for you when using the :writer option.

This is especially helpful when you need to decide the document key – like "title" – at runtime.

The same works for parsing using :reader!

property :title, reader: lambda do |doc, args| 
  self.title = doc["title"] || doc["name"]
end

Here, it’s your job to assign whatever property you extract from the incoming document. Useful when a property needs to be computed from different fields.

Those features were requested from users in the growing roar/representable community. Thanks for the feedback!

After decades of struggling with myself, and after a fantastic RubyConf Australia with lots of love I finally managed to give cells users support for a global (brrr) #content_for helper.

Using It.

The new helper is added by including the cells-capture gem into your Gemfile.

gem 'cells-capture'

Cells need to declare explicitly that they want #content_for to access the global buffer by including Cell::Rails::Capture. This is meant to remind users that they’re kinda breaking their encapsulation (although it feels handy, I admit).

class BassistCell < Cell::Rails
  include Cell::Rails::Capture
 
  def show
    render
  end
end

You can now use the helper in your views – it will append passed content to the global buffer.

%div
  - content_for :javascripts
    $('#pick').append("Yo!")

Now What Is Your Problem?

We want cells users to have maximum comfortability, that is why the new helper is here. However, there are two problems with this approach.

  • You’re changing state of a global variable from a well-encapsulated cell.
  • A cached cell will mess up the global as you expect the cell to append something but it actually doesn’t (remember, there’s a cache hit).

Especially the latter is a problem: Imagine you’re rendering a page with a cached cell: the JavaScript of this component will be lost as the #content_for block is never called! This is a well-known problem in traditional Rails views where people call #content_for in a #cache block.

A Way Out?

A more explicit way of collection JavaScript from view components could help.

render_cell(:bassist, :play) do |cell|
  content_for(:global_js, cell.js)
end

Here, instead of calling #content_for in the cell’s view, you dedicate an additional method to it responsible for rendering the JavaScript (or any other content).

class BassistCell < Cell::Rails
  cache :play
 
  def play
    render # usually, content_for happens here.
  end
 
  def js
    render # this could be a JS template
  end
end

The content of the #js view will be added to the :global_js buffer. The cool thing: It will be invoked even when #play is cached!

Anyway, let us know how you use it and enjoy.

Yo, just a quick heads-up on some great new features in the recent representable release.

Options From The Outer World

Often you might need to “inject” objects into your representer, like the current_user or a parameter from that very request.

module SongRepresenter
  include Representable::JSON
 
  property :rating
end
 
class Song
  attr_accessor :current_user
 
  def rating
    current_user.rate(self)
  end
end

This was a bit clumsy as people first had to set an instance variable in the represented object and then call the rendering or parsing.

song.current_user = current_user
song.extend(SongRepresenter).to_json

Setting instance variables changes the state of the object which can lead to problems. Changing state is dangerous. It’s better to do it functional by passing around the values. That is why representable now allows you to pass an options hash into the render and parse method. Hooray.

song.to_json(current_user: current_user)

Now, to process this user when rendering we got the brand-new and long-awaited `:getter` option.

module SongRepresenter
  include Representable::JSON
 
  property :rating, getter: lambda { |opts| 
    opts[:current_user].rate(self) }
end

Given this option representable will no longer call the #rating reader but the block. The lambda is executed in the represented object’s context (song) allowing us to pass the song into the user’s #rate method. And the coolest: we get the user options from the outside as the block argument!

The same works for parsing using the :setter option!

property :rating, setter: lambda { |val, opts|
  opts[:current_user].rate_song(self, val) }

Here we get two block parameters: the actual parsed value for that property and the user options hash.

What Else?

The options are also passed to :if directives!

module SongRepresenter
  include Representable::JSON
 
  property :rating, if: lambda { |opts| 
    opts[:current_user].has_rating? }
end

An additional benefit: if you don’t want to write accessor methods for your properties, you can use :setter and :getter blocks even if you’re not interested in passing around user options.

property :rating, getter: lambda { |*| @rating.to_i }

And, naturally, the user options are passed down the object tree to nested properties. Cool stuff.