Sneaking a peak at Rails 4
October 15, 2012 § Leave a comment
This weekend I decided to have a go at making an app with edge Rails, aka Rails 4.0.0.beta. I hunted around for a summary of the cool new stuff and didn’t really find one. So, here is the interesting things I hit upon, more or less in the order I hit upon them:
Getting started:
The first thing to do was to get `rails new` to generate a new app. After a little googling, it seems like the easiest way to do this is as follows:
* git clone git://github.com/rails/rails.git
* cd rails
* bundle install
* railties/bin/rails new ../path/to/your_new_app –dev
So essentially, we get the latest in the rails repo, install its dependencies, and then run `rails new` from the binary in the repo. It’s important we pass the `–dev` flag so as to get the Gemfile pointing some Rails’ dependencies at you local copy of Rails. More info on this can be found in this ticket.
Routing concerns:
This is cool. While I didn’t really need to use it for what I was doing I figured little could go wrong with gratuitous use of beta features, so I went right ahead. Essentially, we are able to define a resource that can then become a “concern” of another resource. Something like this:
concern :hookable do
resources :hooks
end
resources :app, concerns: :hookable
Running `rake routes` shows us something like what can be seen in this gist (damn you wordpress.com): https://gist.github.com/3886049
As you can see, adding the “concern” to another resource, adding hookable to app in this case, creates all the correct routes for the nested resource. Any resource can be “hookable”! The routing concerns Readme uses the example of adding comments to a few different resources. I’m sure you can see how this coud be really useful in keeping your routes sane in certain situations.
Turbolinks:
Turbolinks are an extension of the same idea as pjax, but this time applied to the whole page. When following a link, rails will update the body tag of the current page with the HTML for the new page, leaving everything else intact in an effort to reduce page load times. Turbolinks are enabled by default, and I did notice them doing their thing while developing my app. I don’t really have much to say on them right now. I think they made the page load feel snappier, but with such a basic page it’s hard to say. I didn’t do any benchmarking, and I’d imagine the performance benefits will vary depending on your situation.
Testing:
I found this interesting. Gone are unit tests. Gone are functional tests. These have been replaced by model and controller tests. I think that makes much more sense.
Our new test directory looks a little like this after generating a couple of resources:
test/
├── controllers
│ ├── apps_controller_test.rb
│ └── hooks_controller_test.rb
├── fixtures
│ ├── apps.yml
│ └── hooks.yml
├── helpers
│ ├── apps_helper_test.rb
│ └── hooks_helper_test.rb
├── integration
├── mailers
├── models
│ ├── app_test.rb
│ └── hook_test.rb
├── performance
│ └── browsing_test.rb
└── test_helper.rb
Strong Parameters / Mass-assignment
Previously, there have been a number of ways to deal with mass-assignment. Rails 4 standardises this (rightly or wrongly) with Strong Parameters, which has been merged into rails core. Now, defining attr_accessable in our model will lead to an error a bit like this one: RuntimeError (`attr_accessible` is extracted out of Rails into a gem. Please use new recommended protection model for params or add `protected_attributes` to your Gemfile to use old one.)
. Strong parameters are the recommended way, so let’s have a go:
# controllers/apps_controller.rb
def create
@app = App.new(app_params)
if @app.save
redirect_to app_path(@app), notice: 'Created'
else
render :new, alert: 'Failed'
end
end
private
def app_params
params.require(:app).permit(:title, :password)
end
The assignment logic is encapsulated in a private method in the controller, and we use this to permit certain values in the params hash for the object we’re interested in. You can read more in the project’s Readme, but note this is now part of Rails core.
Queueing
Rails 4 ships with a simple queuing module. I think this is a greatly anticipated feature, and may folks have written more eloquently on the feature that I have. The gist of it is a job is a class that responds to run
, and we push this onto the queue like this:
Rails.queue.push(SomeClassThatRespondsToRun.new)
I couldn’t find a generator for creating a job class, so I’m not overly sure of the convention that we’re supposed to follow, but I created a jobs
directory under app
and popped a MyJob
class in there. Here’s a simplified example:
class MyJob
= id
def initialize(id)
@id
end
def run
Thing.find(@id).heavy_lifting!
end
end
And we call it with:
Rails.queue.push(MyJob.new(@thing.id))
Rails will spawn a worker process and process our queue in the background from there. For an interesting look into how Rails.queue
is implemented, and the source is enlightening too.
Conclusion
I’m liking Rails 4! On balance I think things are moving in the right direction. We’re getting built-in support for stuff that happens in almost every project i.e. queuing, the new test directory structure makes more sense, to me at least, and anything to help make routing easier is something I’ll always appreciate.
I’m looking forward to dipping in to the source a little more, and following the development to the 4.0 release. I can’t wait!
Leave a Reply