Archive for the ‘Ruby’ Category
Thanks Ruby – Array zip fail no comments
After updating rails from 2.0.2 to 2.2.2 on the bit-tech CMS this week I discovered a bug that had cropped up in one of my controllers where I was calling zip to join a a has_many collection with a couple of arrays and iterate through them. The code that was working fine now did something like the following.
>> g.groups.zip([1,2], [3,4]) {|a,b,c| p a.inspect + ‘, ‘ + b.inspect + ‘, ‘ + c.inspect }
“[#<Group id: 1>, 1, 3], nil, nil”
“[#<Group id: 2>, 2, 4], nil, nil”
This is strange, I can no longer access the three elements of the array directly in the block. So I tried the following
>> g.groups.to_a.zip([1,2], [3,4]) {|a,b,c| p a.inspect + ‘, ‘ + b.inspect + ‘, ‘ + c.inspect }
“#<Group id: 1>, 1, 3″
“#<Group id: 2>, 2, 4″
As you can see this solved the problem, but I was confused why there was a difference so I executed…
>> g.groups.class
=> Array
Why when I cast it to an Array, from an Array, is it acting differently? Rails must have done something to the Array class that is returned by the has_many relationship.
Rails and AJAX no comments
Rails and rjs templates are the best thing ever!
Do a remote AJAX call from your page and in the linking controller’s view folder have a template called #{action_name}.rjs
In your rjs template you write code in ruby which is translated into javascript which can control your page content. So you can replace html, insert partials and do page effects.
RMagick no comments
I must have spent a good few hours scratching my head when I was trying to get RMagick to work on Mac OS X 10.4.8.
The problem I was encountering was that Ruby would exit with the error: “Bus error”. This nice handy message seems to be plaguing a lot of users.
The problem, as it transpired, was nothing to do with RMagick, but the installation of ImageMagick. I had followed a guide for obtaining all the dependencies for ImageMagick on OSX, but it turns out that there were more, despite ImageMagick compiling and installing without error.
To cut a long story short, the solution was to install ghostscript, something I had blindly missed as one of the dependencies to ImageMagick, and then recompile ImageMagick.
Rails & Keys no comments
Rails was designed with specific names for certain things. Your primary key columns in your database tables are one of these things. Rails expects your primary keys to be called `id`. This is all very well and good until you are building an app with an existing database where the keys are named randomly.
Thankfully there are some clever methods in ActiveRecord to allow you to tell your classes what the tables, primary and foreign keys are. Now comes the annoying part…
If the primary key on your `articles` table is called `articleId` you should be accessing the key using the full name and assigning it with `id`.
@article = Article.find(1) @article.articleId #=> 1 @article = Article.new @article.id = 1
More annoying is when you come to relationships. Say your articles are related to a category, so you’ve set up the relationship in your models and your category table has a primary key named `categoryId`. Seems sensible however now the code you see a lot of people writing won’t work. For example when you’re writing your edit form for your article you’d initially expect to be able to do this.
select("article", "category",
Category.find(:all).collect {|t| [t.categoryTitle, t.categoryId]},
:selected => @article.category)
However since the primary key of category is not `id` the code @article.category will return the object_id and not the primary key. Instead you might expect to do this.
select("article", "category",
Category.find(:all).collect {|t| [t.categoryTitle, t.categoryId]},
:selected => @article.category.categoryId)
Now however you’ve got a whole new bunch of problems. Firstly you can’t use this in a partial that you want to use in your new and edit actions. This is because when you have a new article the category object will be nil, similarly if you are editing a category that isn’t assigned to a category you will get the same error (nil doesn’t have the method categoryId). You might say, you do a conditional, but that introduces more code. You will also have problems when the value is sent back in the parameters, the model will be expecting an object and can’t handle the fact it gets a number.
The best way to do it is to forget the related object and concentrate on your foreign key, we must also change the field name to that of the foreign key in our article table.
select("article", "categoryId",
Category.find(:all).collect {|t| [t.categoryTitle, t.categoryId]},
:selected => @article.categoryId)
This code can now be used in our partial form.