Uncategorized

Caching In Cells: API Change In 3.10.

Monday, March 10th, 2014

The caching layer in Cells just got an update. By using the new uber gem we could generalize the processing of options resulting in a more streamlined experience for you.

What Changed?

For those of you already using Cells’ caching, please update your code when updating to 3.10!

Blocks do not receive the cell instance as the first argument anymore – instead, they’re executed in the cell instance context.

And, the best: There’s no deprecation for this!

What used to be this…

class CartCell < Cell::Rails
  cache :show do |cell, options|
    cell.md5
  end

…you have to change to the following.

class CartCell < Cell::Rails
  cache :show do |options|
    md5
  end

Note how we simply got rid of the first block parameter.

Caching In Cells.

Cells allow you to cache per state. It’s simple: the rendered result of a state method is cached and expired as you configure it.

To cache forever, don’t configure anything

class CartCell < Cell::Rails
  cache :show
 
  def show
    render
  end

This will run #show only once, after that the rendered view comes from the cache.

Static Cache Options.

Note that you can pass arbitrary options through to your cache store. Symbols are evaluated as instance methods, callable objects (e.g. lambdas) are evaluated in the cell instance context allowing you to call instance methods and access instance variables.

cache :show, :expires_in => 10.minutes

This is passed right to the underlying store.

Dynamic Options.

If you need arbitrary dynamic options evaluated at render-time, use a lambda.

cache :show, :tags => lambda { |*args| tagged_as }

In case you don’t like blocks, use instance methods instead.

class CartCell < Cell::Rails
  cache :show, :tags => :cache_tags
 
  def cache_tags(*args)
    ["updated", "revisited"]
  end

Those evaluated options along with their key are simply passed to the cache store.

Building Your Own Cache Key.

You can expand the state’s cache key by appending a versioner block to the ::cache call. This way you can expire state caches yourself.

cache :show do |options|
  options[:items].md5
end

The block’s return value is appended to the state key, resulting in the following key.

 "cells/cart/show/0ecb1360644ce665a4ef"

Using Arguments.

Sometimes the context is needed when computing a cache key. Remember that all state-args are passed to the block/method.

Suppose we pass the current cart object into the render_cell call.

render_cell(:cart, :show, Cart.current)

This cart instance will be available for your cache maths.

class CartCell < Cell::Rails
 
  cache :show, tags: lambda { |cart| cart.tags }

Cells simply passes all state-args to your code making it very flexible.

A Note On Fragment Caching

Fragment caching is not implemented in Cells per design – Cells tries to move caching to the class layer enforcing an object-oriented design rather than cluttering your views with caching blocks.

If you need to cache a part of your view, implement that as another cell state.

Better Nesting in API Documents With Representable 1.7.6

Sunday, March 2nd, 2014

The recent 1.7.6 release of Representable brings a really helpful feature to all the Roar and Representable users: Better nesting for flat hierarchies.

Simpler Nesting In Documents

Sometimes an API requires you to nest a group of attributes into a separate section.

Imagine the following document.

{"title": "Roxanne",
 "details":
   {"track": 3,
    "length": "4:10"}
}

Both track and length are nested under a details key. Now, this is the required document structure. However, it doesn’t really fit into your model scope, as both nested keys are properties of the outer Song object.

song.title  #=> "Roxanne"
song.track  #=> 3
song.length #=> "4:10"

In earlier versions of Roar/representable you had to provide a 1-to-1 mapping of your object to your document. This usually ended up in something clumsy like this.

class Song < ActiveRecord::Base
  # .. original code
 
  def details
    OpenStruct.new(
      track:  track
      length: length
    )
  end

It got even worse when parsing this nested document was to be accomplished! I’ll spare you the details here.

More Than DSL Sugar: nested

Let’s experience the enjoyment of the new ::nested feature instead.

class SongRepresenter
  include Representable::JSON
 
  property :title
 
  nested :details do
    property :track
    property :length
  end
end

Life can be so easy. This simple change will advise representable to expect those two fellas track and length to be on the outer object, but it’ll still render them into a details: section.

And, even better, this will also parse the document and set the nested attributes on the song instance.

song.extend(SongRepresenter).from_json %{
  {"title": "Roxanne",
   "details":
     {"track": 3,
      "length": "4:10"}
  }
}
 
song.track #=> 3

It’s incredible how this new feature simplified our process to connect to the new Australian Post API – and, frankly, I feel a bit embarrassed I didn’t provide you guys with this feature earlier.

Deep Nesting

The new nested method turned out to be extremely useful for deeply nested “throw-away documents” that don’t need to be persistent.

For instance, here is a typical response from the Auspost API.

{"CreateArticleResponse":{
  "ArticleErrors":{
    "BusinessExceptions":{
      "NoOfErrors":1,
      "BusinessException":{
        "Code":102,"Description":"Internal Error, failed to process request to source"
      }
    }
  }
}}

To get to the actual error message, I need a 4-level deep hash access. The representer code before ::nested would look terrible – you’d spend half an hour on creating an object graph that maps to this document. Sucks.

Here’s how it looks now.

class ErrorsRepresenter
  include Representable::JSON
 
  self.representation_wrap = :CreateArticleResponse
 
  nested :ArticleErrors do
    nested :BusinessExceptions do
      nested :BusinessException do
        property :Description
      end
    end
  end
end

This is all defensive declarative code. If one of the keys is not found in the incoming document, representable will simply stop parsing that property.

To actually retrieve the error description I simply use a Struct.

err = Struct.new(:Description).new
 
err.extend(ErrorsRepresenter).
  from_json('{"CreateArticleResponse":{ ..')
 
err.Description #=> "Internal Error, ..."

What I love about this is: This code won’t break if the parsed document does not contain any of the nested attributes. err.Documents will simply return nil.

Imagining the nightmare I’d have conditionally parsing a 4-level deep hash I really feel like this is a good feature.

Internals.

A fair side note. Internally, a nested block is implemented using a Decorator, even if you’re using a module representer for the original document. This doesn’t really affect you, however, if you add methods to the nested representer, make sure to use the right reference when you wanna access the model.

class SongRepresenter
  include Representable::JSON
 
  property :title
 
  nested :details do
    property :track
    property :length
 
    define_method :track do
      represented.track.to_f
    end
  end
end

Note that I use represented instead of self in the helper method.

Let me know what you think.

Roar Got Better Http Support!

Saturday, March 1st, 2014

Morning everyone! The latest Roar 0.12.3 release comes along with some long-awaited features and I wonder why it took me so long.

I added some functionality to the client layer of Roar. As you might recall, Roar allows representers to be used both for backends and on the client side.

Roar’s Client Layer

Let’s run quickly through how to build a REST client with Roar.

As always, we need a representer to specify the exchanged document.

module SongRepresenter
  include Roar::Representer::JSON
 
  property :title
end

Next, I write a simple client class that consumes from the existing PunkrockAPI™. Please excuse my use of OpenStruct, but I’m lazy. And… aren’t lazy programmers the better programmers?

class Song < OpenStruct
  include Roar::Representer::JSON
  include SongRepresenter
 
  include Roar::Representer::Feature::HttpVerbs
end

We’ll discuss what happens here in a second.

Simpler HTTP API.

Here’s how you use that client, first.

song = Song.new
song.get(uri: "http://songs/roxanne", 
          as: "application/json")
 
song.title #=> "Roxanne"

The HttpVerbs module adds verbs to the client model. In this example, I use #get to retrieve the document from the specified URL, parse it and assign properties to the object. Since we also mixed in SongRepresenter, the client knows about the document’s structure and the attributes.

Note the new API for #get, #post, etc. You now use keys to specify arguments, no positional arguments anymore. No need to panic, we added a soft transition with deprecations.

HTTPS Support!

Let’s assume the PunkrockAPI™ goes SSL, requiring your client to use a HTTPS connection. This was a pain so far, check out how it works now.

song.get(uri: "https://songs/roxanne", 
          as: "application/json")

Exactly – you don’t have to do anything besides specifying https:// as the protocol, Roar does the “REST” for you.

Basic Authentication

To make it even harder, the API wants you to authenticate beforehand. Basic auth was a feature missing for a long time in Roar. Here it comes.

song.get(       uri: "https://songs/roxanne", 
                 as: "application/json",
         basic_auth: ["nick", "secret password"])

Pass in necessary credentials with the basic_auth: option. Done.

Configuring The Request.

The verbs now allow you to mess around with the Request object, too. It is yielded to the block before the request is sent.

song.get(...) do |req|
  req.add_field("Cookie", "Yummy")
end

Couldn’t be simpler to create a cookie, change the Accept: header or whatever. The yielded object is a request instance from the NetHTTP implementation (unless you’re using Faraday).

Too High-Level!

Sometimes the verbs might be too high-level, too smart, doing to much. You’re free to use the underlying @Transport@ methods instead. They just do a raw HTTP request.

res = song.http.get_uri(uri: "http://songs/roxanne")
res.body #=> '{"title": "Roxanne"}'

More Soon!

These minor additions have helped a lot in my current project to communicate with the Auspost API. Stay tuned for a major update of Roar. We’re planning better defaults, full Faraday support, simpler nesting, and more.

New Experimental Feature in Cells: View Models

Wednesday, October 23rd, 2013

The cells gem has been around for almost 7 years now. With more than 300.000 downloads within 3 years it has gained some traction in the Rails community. Many projects are using it heavily to write reusable widgets, testable partials or just to have well-encapsulated view components.

We felt it was time to breath some fresh air and take this mature project a step further.

View Models?

Cells still works the same way as it used to work. Relax, you can still use render_cell as before.

However, we now got a second “dialect” in version 3.9.0. The new view models in cells addresses two issues that have been around for longer.

A streamlined DSL makes it easier to work with the cell instance itself. This is extremely helpful now that view models keep helper methods on the instance level.

Let’s see how that all works in an example.

1
2
3
4
5
6
7
8
9
class SongCell < Cell::Rails
  include Cell::Rails::ViewModel
 
  property :title
 
  def show
    render
  end
end

Mix in the ViewModel feature and get a new semantic for your cell. First, check how a view model is created.

class DashboardController < ApplicationController
  def index
    song  = Song.find(1) # <Song: title: Roxanne>
 
    @cell = cell(:song, song)
  end

Cell instances are created in the controller. This could also happen in the view – if you really want that. Note that the second argument is the decorated model that this cell represents.

Decorating Models – Step 1.

Attributes declared with ::property (line 4) will automatically be delegated to the cell’s model. So, the following call works without any additional code.

@cell.title #=> "Roxanne"

But more on that later.

View rendering still happens by using #render – exactly as in the “old dialect”. That’ll invoke the existing rendering with all the nice things like view inheritance, caching, etc.

The DSL looks a bit different, thou.

@cell.show #=> invokes show state

This line will call the #show method (“state”) which in turn renders app/cells/song/show.haml.

Helpers Are Instance Methods.

We should look at the rendered view to understand what changed in terms of helpers and their scope.

1
2
3
4
5
6
7
/ app/cells/song/show.haml
 
%h1 #{title}
 
This song is awesome!
 
= link_to "Permalink", song_url(model)

Four helpers are used in this view. It is important to understand that all helpers in a view model view are invoked in the cell instance context.

Now, what does that mean?

Well, the call to title (line 3) is not called in some strange module, it is simply invoked on the cell, as we did earlier when doing @cell.title.

The same happens with link_to and song_url: The view model automatically provides the URL helpers on the instance.

The model method is another view model “helper”, an instance method, returning the decorated object (line 7).

Decorating Models – Step 2.

This might look confusing at first glance, but imagine how simple it becomes to write your own “helper” now.

Why not extract the entire #link_to line to a separate, testable method?

class SongCell < Cell::Rails
  # ..
 
  def permalink
    link_to "Permalink", song_url(model)
  end
end

You can just move the entire line to the cell class and it’ll work.

Testing Helpers.

Not that you suddenly get benefits like encapsulation and inheritance, no, also your testing is greatly improved for your new “helper”.

it "renders #self_link" do
  cell(:song, song).permalink.
    should eq "<a href.."
end

This doesn’t fake an environment as Rails helper tests do. It executes the same code in the same environment as in production.

Using Existing Helpers.

To use one of Rails’ numerous helpers, you include the modules into your cell class.

1
2
3
4
class SongCell < Cell::Rails
  include TagHelper
  # ..
end

You can then use the methods in your view – or in your instance methods.

Again, the magical copying of methods into your view doesn’t happen anymore. The view model instance will be the view’s context itself.

Pollution.

I can hear people complaining about stuffing all those helper methods in the the poor cell class. But let me ask you? Do you really feel comfortable pushing your helpers into a scopeless, not object-oriented module that gets mixed into the view somewhere in the stack and hopefully doesn’t collide namespaces?

Also, a cell typically embraces a small part of your UI. As this has a well-defined functionality you’d not mix in all helpers but only those you need. That reduces the number of “polluting” methods.

Another point against pollution is: When including a helper, it should ideally import the public helper methods, only. The internals and private methods should be in separate classes.

Actually, the only helper that does this is the FormHelper that delegates #form_for to the FormBuilder class.

Please, blame Rails’ helper implementation for the pollution, not me ;)

What About Real Decorators?

Don’t use a view model where you just need a simple helper. Use a decorator gem like draper to decorate your model (and push that into the cell, if you like).

Use a cell view model when there’s rendering of markup involved. Cells help to clean up Rails hard-wired partial mess and allow clean testing of the encapsulated widgets.

Use a cell view model when the decorations are needed for a special widget, only, and not across your application.

And use a view model if you found the #render_cell to clumsy and you wanted to invoke different methods on the cell instance.

From Here…

The experimental view model feature is an attempt to move view logic – or, helpers – into an object-oriented space while reducing its complexity.

You still got all of cells core behaviour like rendering views, nesting, inheritance across code and view level, OOP caching. Anyhow, you get an easy way to wire helper methods into your views without falling back into a procedural programming style from the 60s.

There will be problems with the way Rails helpers are programmed, and hopefully we can fix those finally making helpers predictable.

Give it a go, we can’t wait to hear your opinions about this new approach!

Running Multiple MySQL Servers With Different Versions On The Same Machine.

Monday, October 14th, 2013

Today I was urged to install MySQL 5.1 to run a “new” Rails project. Since I refused to uninstall my existing 5.5 I found a way of running two separate instances on my machine using MySQL-Sandbox.

Frankly, it was a pain in the ass and MySQL-Sandbox saved my day. Here is what I did on my Ubuntu machine – conceptually, this should work for other Linuxes, OSX, etc, as well.

MySQL-Sandbox?

This little tool helps you by installing and pre-configuring a separate MySQL instance. It also provides scripts for administrating your servers. It is great.

Download The Binary.

Download the binary tarball from the MySQL download site. I downloaded mysql-5.1.72-linux-i686-glibc23.tar.gz.

Install Sandbox.

I had to install some Ubuntu packages as listed on this helpful post. However, this might not be necessary on OSX.

$ sudo apt-get install build-essential libaio1 libaio-dev

Then, install the sandbox tool.

sudo cpan sandbox

Create Your Sandbox.

The make_sandbox command will now install and configure a brand-new MySQL setup in a separate directory. I ran the following command.

make_sandbox mysql-5.1.72-linux-i686-glibc23.tar.gz

This installs mysql 5.1.72 into /home/nick/sandboxes/msb_5_1_72. Changing into that directory you can simply configure and spin up the server.

Configuring MySQL.

Your configuration file now lives in msb_5_1_72/my.sandbox.cnf and is ready to be edited – which wasn’t necessary as I was happy with the settings.

The only interesting directive to me was the port.

port               = 5172

Starting The Server.

The msb_5_1_72 directory comes with handy administration scripts, so within that dir I just ran the start command.

msb_5_1_72$ ./start

Using The Server.

This runs a completely isolated MySQL 5.1 instance on port 5172 while letting my 5.5 alive on the standard port! Awesome!!!

Now, to connect to that server you just have to provide the port number in your client.

Note: On Linux, you also need to provide the --host with 127.0.0.1 as described here. Don’t say I didn’t warn you.

mysqladmin -u root --host=127.0.0.1 --port=5172 
  -p msandbox password

The original root password is msandbox, so go change this. Everything else works just like your “global” installation.

And, In Rails?

My database.yml looks like this.

development:
  adapter: mysql
  database: blog
  username: "root"
  password: ""
  host: 127.0.0.1
  port: 5172

Thanks to Giuseppe Maxia for this helpful tool.

Reform 0.2 Released – With has_one And has_many Support!

Monday, September 16th, 2013

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!

Representable 1.7 Is Out With Syncing Support, Inline Representers And More!

Saturday, August 31st, 2013

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.

Nit Improves Your Git Workflow.

Monday, August 12th, 2013

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.

Sunday, May 26th, 2013

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!

Roar-Rails 0.1 Released – Namespacing Done Right.

Monday, May 20th, 2013

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.