9:52 AM EDT Tuesday, April 29 2008
A few days ago, Charles Nutter asserted that "people are not flocking to Ruby 1.9 in droves". I would consider myself one of those people. When I thought about Ruby 1.9, I just assumed they were tweaking the syntax a little but mostly working on a VM that would make Ruby faster. Mainly though, Ruby 1.9 is an unstable, development release, so it's really just for playing around with it. The intent is for 1.9 to drive development for Ruby 2.0, and have people flock to Ruby 2.0 once that is ready for prime time.
Another factor is that up until today, I didn't really know much about what is planning on being added to Ruby 1.9. There is a complete list of changes in Ruby 1.9, but it wasn't until I came across a slideshow by Bruce Williams that covers some of the changes in Ruby 1.9 that I took the time to download, install and try out a few new features. So I thought I would put together a blog entry of 5 of my favorite changes:
New Literal Syntax for Hashes
{:foo => 1, :bar => "two"} now becomes {foo: 1, bar: "two"}. This is probably minor, but I really like it. It's a little bit cleaner, although I'm sure Obie will be sad to see the hash rocket go. Actually, I'm sure the hash rocket will still be supported, it will just become no longer idiomatic.
New Proc literal
But fear not Obie, we lose one operator, the hash rocket, but gain another, the proc rocket. You can now define a proc like this:
double = ->(x) { x * 2 }
puts double.(5) # => 10
That can lead to some pretty crazy things, like this:
p = ->(n, name="it", &block) {
n.times{|i| block.call }
puts "I did #{it} #{n} times"
}
p.(3) do |i|
puts "#{i} is #{i.even? ? 'not ': ''}odd"
end
p.(3, "foo") do |i|
puts "#{i} is #{i.even? ? 'not ': ''}odd"
end
The difference being that you can now have default values for arguments to a Proc and also you can pass a Block to a Proc. I could see this being used in metaprogramming. You could probably do a lot of things with this instead of things that get done using class_eval now.
#Ruby 1.8
class Foo
end
Foo.class_eval <<-CODE
def bar(x,y=2)
puts "x => \#{x}, y => \#{y}"
end
CODE
#Ruby 1.9
class Foo
end
Foo.send(:define_method, :bar, ->(x, y=2) {
puts "x => #{x}, y => #{y}"
})
Not sure yet if that would be better, I guess we'll see.
Hashes preserve insert order
Say goodbye to using 2D arrays just because you want things to be in a certain order. This is very convenient, but I was always under the impression that this is the way it was for performance reasons. I'd like to hear more about this. Is this one of those things where 80% of the time you don't care about that level of performance because your hash is relatively small and the convenience of preserving sort order is a better benefit? Is there some kind of FastHash class that can be used for cases where you don't care about ordering and better performance is needed? Or is the performance of the insertion-order Hash good enough for all cases?
New Regular Expression Engine
The Oniguruma regular expression engine is used in Ruby 1.9. This engine supports many advanced regular expression features. I once looked into directly porting the Perl Markdown code into Ruby but quickly found out that wasn't possible given the limitations of the Ruby 1.8 regular expression engine, so it's nice to see Ruby will have a regular expression engine that is on par with that of any other language.
Object#tap and Symbol#to_proc
I lumped these together into one because they are both kind of the same thing. These are two language level features that have become idiomatic Ruby because they have been added in Rails. The downside has been that if you are not in Rails, you either don't have these, or you have to define them to use them. Now that is a problem no more and they are just going to be part of Ruby. Symbol#to_proc you should recognize and Object#tap is the same thing as returning.
Posted in
Technology |
Tags
Ruby |
3 Comments
6:30 PM EDT Wednesday, April 23 2008
The suggested way of checking if an ActiveRecord model has errors with RSpec is:
@something.errors.should be_empty
When that fails, you get a report that says:
expected empty? to return true, got false
That's not very helpful because it doesn't tell you what the errors are. If you do this:
@something.errors.full_messages.should == []
You get a more informative failure message:
expected: [],
got: ["Whatever can't be blank"] (using ==)
Posted in
Technology |
Tags
RSpec, Rails, Ruby |
3 Comments
12:11 PM EDT Monday, April 21 2008
I just stumbled upon a neat little Rails feature and figured I'd share with the world. I'm working on a Facebook application and I'm going through some of the examples in Developing Facebook Platform Applications with Rails. In chapter 4, one of the tasks is:
Let's add a boolean hit column to our attack model. I'll wait while you create that migration.
It doesn't tell you how to do that, which I like. This is a simple enough task the reader should be able to do in their own, no need to clutter up the book with the code.
So I set out to do that, but for whatever reason my mind is in a bit of a fog today. I don't what it is, I've been making an inordinate number of typos. So when my fingers went to type the command to generate the migration, I just instinctively did this:
script/generate migration add_hit_to_attack hit:boolean
I accidentally added the hit:boolean column specification as if this were a script/generate model Whatever command. But it turns out Rails is able to read my mind. I opened up the migration file that was generated and there was this:
class AddHitToAttack < ActiveRecord::Migration
def self.up
add_column :attacks, :hit, :boolean
end
def self.down
remove_column :attacks, :hit
end
end
The code to add the column was already there. I checked the docs and sure enough there is support for this naming convention:
You can name your migration in either of these formats to generate add/remove
column lines from supplied attributes: AddColumnsToTable or RemoveColumnsFromTable
Example:
`./script/generate migration AddSslFlag`
With 4 existing migrations, this creates the AddSslFlag migration in
db/migrate/005_add_ssl_flag.rb
`./script/generate migration AddTitleBodyToPost title:string body:text published:boolean`
This will create the AddTitleBodyToPost in db/migrate/005_add_title_body_to_post.rb with
this in the Up migration:
add_column :posts, :title, :string
add_column :posts, :body, :text
add_column :posts, :published, :boolean
And this in the Down migration:
remove_column :posts, :published
remove_column :posts, :body
remove_column :posts, :title
Posted in
Technology |
Tags
Rails, Migrations, Ruby |
0 Comments
4:39 PM EDT Saturday, April 19 2008
Ryan Bates, the author of Railscasts, just reached his 100th episode. Railscasts is a fantastic free resource for learning about Ruby on Rails. Congratulations, Ryan!
To celebrate his 100th episode, he's running a contest with some great prizes. The contest is to submit your own 5 Rails tips, much like Ryan did in Episode 100 of Railscasts. This blog post is my entry into that contest. I have posted 5 articles today which include tips on various aspects of Rails. They are:
Sending Liquid-based Email with Rails
Find out how to let the administrative users of your application update email templates.
Importing Data with Rails
Learn how to use Rails and object-oriented techniques to import data into your Rails app.
Serving Images Stored in the Database with Rails
See how to take advantage of Rails' page caching to serve images that are stored in your database.
Using ActiveRecord Composed Of
Make use of the composed_of feature in ActiveRecord to treat multiple fields within a model as one object.
Using Lowpro To Create Autotab using Unobtrusive JavaScript and Rails
Provide your users with an easy shortcut for entering in multi-field data types like phone numbers without filling up your views with lots of JavaScript code.
If you find these tips helpful, be sure to let Ryan know! :)
Posted in
Technology |
Tags
Railscasts, Rails, Ruby, 5RailsTips |
0 Comments
4:16 PM EDT Saturday, April 19 2008
In the last article, I showed how to use composed_of to create a class to handle phone numbers. In this article, I'll show how you can use Unobtrusive JavaScript to make a spiffy interface for entering phone numbers. So first, here's the code we want for phone numbers:
Phone Number
<% f.fields_for :phone_number do |pn| %>
(<%= pn.text_field :area_code, :size => 3, :class => "autotab" %>)
<%= pn.text_field :prefix, :size => 3, :class => "autotab" %>
-
<%= pn.text_field :line_number, :size => 4, :class => "autotab" %>
ext
<%= pn.text_field :extension, :size => 4 %>
<% end %>
This goes in the form view code for the users resource. What this does is render separate fields for each part of the phone number. If you've generated the scaffolding for the users resource, you should be able to stick this in there and be able to create users with phone numbers using this form.
So that's nice, but it would be neat if we could have the cursor automatically jump from one field to the next once the correct number of digits have been entered? We've already got the first step of that in there by putting the class "autotab" on each of the first 3 fields. That is as much code as we are going to add into the actual view. We are going to do the rest unobtrusively, some might even say, Ninja-style.
The first step is to download Lowpro and put it into your public/javascripts directly. Lowpro is a library that enhances Prototype to make unobtrusive JavaScript easier. Once you've got that, make sure to include the javascript libraries in your layout:
<%= javascript_include_tag :defaults, "lowpro", "autotab" %>
Autotab is a JavaScript file that we are going to create specifically for the purpose of providing the "autotab" functionality, which is the name I'm giving to the feature where the cursor will automatically move to the next field once the correct number of characters have been entered. The correct number of characters is determined from the size attribute of the input field. For staters, make sure you have firebug installed and enter in this code to public/javascripts/autotab.js:
Event.onReady(function() {
console.log("These are a few of my favorite things:");
$$('input.autotab').each(function(e){
console.log(e);
});
});
When you load the form, you should see the output in the firebug console, with the 3 inputs that have the autotab class. This doesn't do anything interesting at this point, but just shows the basis of how unobtrusive JavaScript works. There are no event handlers directly inline in the HTML code, instead some JavaScript code execute once the page has finished loading and adds functionality to DOM elements based on something like their CSS class.
So in order to introduce the functionality we want, we'll use Lowpro's addBehavior method, which attaches an event handler to elements that match a given CSS tag. Replace the contents of public/javascript/autotab.js with this:
Event.addBehavior({
'input.autotab:keyup' : function(e) {
if(e.keyCode != 9 && e.keyCode != 16) {
if(e.target.value.length == e.target.size) {
e.target.next().focus();
}
}
}
});
So once the page has loaded (or the DOM is "ready", I should say more correctly), this will attach this function to the keyup event handler of all of the elements on the page that match the CSS selector input.autotab. In the function, we first make sure the key being released isn't tab or shift. This is because if you are filling out the form and you press shift+tab to go back to the previous field, you don't want it to jump ahead, because you must want to edit that field if you are going back to it. After that if statement we just check to see if the length of the value in the input field matches its size. If it does, then we call next() on the target to get the next field, and call focus() to change the focus to that field.
Posted in
Technology |
Tags
Rails, CSS, Javascript, Ruby, Autotab, Unobtrusive, Lowpro |
0 Comments