Archive for the 'Ruby on Rails' Category

class_table_inheritance with acts_as_taggable

Friday, August 24th, 2007

If I have:

The problem is that:

returns all the Products tagged with ‘test’ rather than all Subproducts. So I tried:

but that does the same thing. The problem boils down to the find_tagged_with! method using acts_as_taggable_options[:taggable_type] which is defined as class_name_of_active_record_descendant elsewhere in the acts_as_taggable plugin. The solution is to rewrite find_tagged_with! to :

This should work even for classes that aren’t using class table inheritance since it’ll just use the class name.

Refs: http://wiki.rubyonrails.org/rails/pages/ActsAsTaggablePluginHowto

Class table inheritance problems

Thursday, August 23rd, 2007

I’ve successfully implemented class table inheritance but came across a problem for one instance. I’m using this to simplify my database structure. I have one model that I’m using it for that has no additional properties other than the stuff its inheriting. I’m doing this to keep everything consistent with the architecture. For instance:

So anvils just inherits all the data from products and doesn’t really add to it. The problem occurs when trying to save a modified anvil record. I end up with an error in the SQL because it’s trying to do something like:

But there aren’t any local attributes to update on the anvils table. I could redo that one structure to not use class table inheritance but that would cause more of a headache than its worth. I could try to hack a solution using the class table inheritance plugin but that didn’t sound fun either. The easiest solution, and I’m not really proud to admit this, was to simply add a junk tinyint(1) column to the anvils table. That way when the update sql runs it won’t cause a syntax error.

I was looking for a way to do anvil.parent.save or something similar but couldn’t find a way to do that. That’d be a much better solution so if anyone figures that out please let me know.

Class table inheritance in Ruby on Rails

Friday, August 3rd, 2007

In my previous post I wrote about trying to get class table inheritance working in Rails. I passed by the hack and went with the plugin which ended up not really working right. I revisited the class table inheritance hack and actually got it working. I pretty much just dumped that code into a plugin so all you have to do is:

spaghetti.rb

noodle.rb

One thing that did trip me up at first was that the spaghettis table can’t have an ‘id’ column for a primary key or you end up with some strange stack overflow errors. The noodles table also needs a ‘type’ varchar column to store the class names of the rows its storing. Even pagination works when you explicitly state what tables you’re conditions are using as in:

Download the class_table_inheritance plugin

Inheritance in Ruby on Rails

Friday, August 3rd, 2007

I have a Rails project I’m working on that seems to be best suited for class table inheritance. Conceptually it will greatly simplify the database and reduce tons of code. There will be a performance hit due to the extra joins. I think that will be manageable though and the simplification of the entire site architecture will make it well worth it. The problem is that class table inheritance isn’t currently implemented in Ruby on Rails and requires a hack to make it work. I’m weary about implementing this hack mostly for long term maintainability since its such a crucial aspect of the site’s architecture. Ideally, class table inheritance will eventually be built into the Rails core but who knows when that’ll happen.

Then I found the inherits_from plugin which made me a bit more comfortable so I tried it out. It works in a very primitive way so long as I’m not using any conditions in my find commands. For instance if I had a product that stored a name and a car table which is going to inherit everything from the products table:

car.name works fine and it would be great if that’s the only way I ever needed to use it. The problem is when I try to toss some conditions into the mix that are conditions against the parent model. So if my products table also had color and I wanted to do something like:

It doesn’t work because its not doing a join but rather 2 separate queries. 1 query for the car table to get the product_id and the other on the products table. Using:

Doesn’t work either. The solution? One option is to extend ‘find’ to make it recognize when its supposed to do a join instead of 2 queries. I’m not looking forward to hacking that mess up cause it opens a big can of worms. For example, how would it handle pagination with conditions as well? I’m not using the plugin. After my getting to that point with the plugin I decided to take another look at the first hack I linked to and see how much effort it really is going to take to get this thing working. I might just end up scrapping class table inheritance altogether and accept the big messy database structure and code redundancy that will ensue.

nil.[] error when using Rails migrations

Thursday, August 2nd, 2007

I just had a little trouble with Rails migrations. I was trying to add a column to a database table in the migration using:

The syntax seems ok at first glance but it resulted in the following error:

The type_to_sql should have given it away to me but I overlooked it at first and spun my wheels trying to figure out what was wrong. As it turned out :int is not right and I need to use :integer instead.

The success of Webster's Classroom

Thursday, August 2nd, 2007

Over this past summer I’ve been working on a project for my wife Laura. She’s the technology teacher at school and needed an easy way for her teachers to create their own classroom webpage. Before Webster’s Classroom she had to manually create every teacher’s page and ftp it to a county server downtown. Needless to say, no one had websites.

Webster's Classroom 1.0

We created an easy way for teachers to do this by using Webster’s Classroom. Best of all, we’re offering it to teachers absolutely FREE. Laura got a warm reception from her peers when she demonstrated our software during the first few days of school. A number of teachers have already used our software to setup their own customized classroom webpage and appear enthusiastic about using it throughout the year. We have many plans for additional features in the next year. So far we are getting very positive feedback on the site and we are excited to add new features to the site. We will be aggressively marketing it at the software matures over the coming months and I’ll be sure to post updates every so often on it.

Safari and Firefox multipart form submission differences

Monday, July 30th, 2007

I just stumbled on a strange difference between submitting multiparts forms via Firefox and Safari. When a file isn’t selected and the form is submitted, Firefox sends the variable name with an empty string as the value. Safari doesn’t send the variable at all. This caused an unexpected problem in Rails when I was checking if the variable was an empty string or not. I honest would prefer to check if the variable is nil or not and if its not nil I’d know the file was sent. I checked for an empty string because Firefox sends the variable. Not my code has to also check if its nil and if not then check if the filename is not an empty string. Lame.

Tagging in Rails and the confrontational rubyonrails irc channel

Tuesday, June 19th, 2007

Once upon a time, the Rails community was pretty open and friendly and one could easily visit the rubyonrails irc channel at freenode to get a ton of help. Its still possible to get help from the irc channel these days but you have to be ready to put up with people who aren’t too friendly. Its filled with geeks who automatically assume you’re an idiot and will treat you as such. I just spent a few minutes in the channel probing about why there’s no consistent taggable plugin. There is the acts_as_taggable gem, the acts_as_taggable plugin, the acts_as_taggable_on_steroids plugin, and even the has_many_polymorphs. The problem is that apparently the acts_as_taggable gem and plugin are deprecated but the other two don’t offer any useful functions. You have to make them all yourself. Neither are much use as a plugin as of this writing. Both require you to write a bunch of your own basic methods like related tags. Another problem is that neither has a friendly RDoc type api published anywhere. As it was so kindly pointed out to me on the rubyonrails irc channel, I am just being an idiot and could easily just read the source code to find out all the methods and what they do. The Rails community, at least in irc, has really degenerated over the past few years and from the looks of the current state of tagging in Rails, so has the code and documentation that is produced.

I’m still undecided on which direction I should head. I’ve already got a half-baked solution using the act_as_taggable plugin so I’m leaning towards just adding the few extra methods I need to it. Its either that or rewrite my tagging code another way which will be deprecated in a few months anyway. A decent tagging plugin for Rails is a void waiting to be filled. Any takers?

Parsing CSV files sent via form post in Ruby on Rails

Thursday, May 31st, 2007

I’m not sure why it took me a while to figure this out but it did. The Ruby CSV documentation is really weak and really only explains how to read from a file. I googled around and couldn’t find anyone else talking about how to parse a CSV file sent via a form post (StringIO). I didn’t want to save it to a temp file just so I could follow the CSV docs examples. Here’s what I eventually got to work. Its so short and simple I feel silly for not figuring it out sooner.


parsed_file = CSV::Reader.parse(params[:dump][:file])
parsed_file.each do |row|
p row[0]
end

Monitary precision of a Ruby float

Wednesday, May 16th, 2007

I looked around and couldn’t seem to find a way to easily change the precision of a Ruby Float object to 2 decimals so I can use it as a dollar amount. I feel bad about posting this because I borrowed some of the code from another site but lost the link to it. Instead of extending the Float class I just wrote a function to do it for me. It takes a Float object and returns string. I returned a string instead of a Float because I’m using it in the view and outputting the result anyway. Anyway, here’s the helper function.


def monetize(number)
splitnum = number.to_s.split(".")[0]
scale = number.to_s.split(".")[1][0..1]
while scale.length < 2
scale = scale + '0'
end
"#{splitnum}.#{scale}"
end