Order Matters! 2

Posted by Matt Williams

The order in which operations occur can often make a difference in Ruby:
1
2
3
4
5
6
7
8
9

$ irb
>> 5 * "a"
TypeError: String can't be coerced into Fixnum
  from (irb):1:in `*'
  from (irb):1
>> "a" * 5
=> "aaaaa"
>> 

The reason is quite simple — everything in Ruby is an object. The '*' behaves differently when applied to different objects (and, in fact, can be overridden). So, because the '*' method as implemented for Fixnum expects a number as its argument, and a String isn't a number, it complains. By the same token, the behaviour of '*' for String is for the string to repeat itself as many times as the argument specifies, it works.

glassfish

Posted by Matt Williams

I've had a jruby rails app deployed to jboss for quite some time now. For grins and giggles I decided to try it under Glassfish today. After I deleted the old WEB-INF and .war file which were created by goldspike, it worked very easily. I'm surprised and tempted to replace the existing jboss install with glassfish, provided it has similar throughput. The footprint is definitely smaller and it is much easier.

You can find more about using glassfish with jruby at the jruby wiki.

Gems Server

Posted by Matt Williams

Ever wonder how to view information about:
  • What ruby gems are installed?
  • Documentation for each gem?

rubygems has a built-in server which you can use to peruse the rdocs for a gem. To use it, type gem server at a prompt and then point your browser to href://localhost:8808.

It's pretty nifty.

Ruport Graphs

Posted by Matt Williams

ruport comes with an extension, ruport-util which adds, among other things, the ability to create graphs from reports. However, it's hardcoded to do line graphs. This is a code snippet which will (for png and jpg graphs, the others should follow) allow you to create other types -- it's just bar graphs, but the others would follow....

Frozen

Posted by Matt Williams

You only see what your eyes want to see
How can life be what you want it to be
You're frozen... -- Madonna

The way to ensure that your production rails apps don't get messed up should the provider update gems is to freeze them. Moreover, it's a good idea to embed the gems/plugins needed for a particular application; it makes distribution of different versions easier, not to mention that you know exactly with which resources your code is working.

To freeze rails, you can either do a rake rails:freeze:gems, which uses the installed gems to freeze, or rake rails:freeze:edge which freezes off of the rails subversion repository. The last one allows you to specify a version to which to freeze. When it's time to thaw, rake rails:unfreeze will remove the frozen rails installation.

To embed gems in your application, use Gems On Rails, which will place gems into vendor/gems.

Lots of Gems

Posted by Matt Williams

This isn't much of a tip, per se, but it's something I ran into today.

The way to having multiple rubygem repositories is to set the GEM_PATH environmental variable. This will allow you to use gems from more than one location -- something useful on shared servers.

Next, to figure out how to specify the version of rubygems you're using -- I've tried GEM_HOME and RUBY_LIB and my PATH, but it's not working properly on the shared host. More once I figure that one out.

Boxy Layouts

Posted by Matt Williams

This is a quick note on two ways of placing boxes around elements in the form.

The first is to use blueprintcss-rails(http://code.google.com/p/blueprintcss-rails/), a plugin which uses the Blueprint CSS framework, and add a box class to the elements.

The second is a little more involved (although more flexible). It requires installing Shaded Border, and adding the following methods to applicationhelper.js:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

  def add_to_options(options,option,value)
    if options.nil?
      options={ }
    end
    if options[option].nil?
      options[option] = value
    else
      options[option] = "#{options[option]} #{value}"
    end
    options
  end


  def boxed_layout(boxid = 'boxy_box_box', content_or_options_with_block = nil, options = nil, &block)
    e=""
    if block_given?
       options = content_or_options_with_block if content_or_options_with_block.is_a?(Hash)
      options=add_to_options(options, :id, boxid)
       content = capture(&block)
       e = concat(content_tag(:div,content,add_to_options(options,:class,"sb")),block.binding)
    else
      content = content_or_options_with_block
      options=add_to_options(options, :id, boxid)
      e = content_tag(:div, content, add_to_options(options,:class,"sb"))
    end
    e << javascript_tag("border.render('#{boxid}')")
    e
  end
I'll make a plugin shortly.

acts_as_treemap issues

Posted by Matt Williams

In preparing for my presentation at Codemash, I discovered that the acts_as_treemap plugin is missing a method -- ruby-treemap has changed and as a result, it needs a accessor methods for bounds.

Modifying plugins for Rails 2.0

Posted by Matt Williams

I found myself having to modify one of my plugins, pretty_accessible_form recently; end_form_tag is no longer in rails. As the plugin draws forms, I needed to explicitly output </form>. I know that for most people there's use in no longer having the end_form_tag since it is added automatically, but there's a lot of plugins which might be broken as a result.

Useful Blogs II: Presentation Matters

Posted by Matt Williams

And some links to specific articles:

Useful Blogs I: Web Development and Design

Posted by Matt Williams

Here's a list of some blogs I've found useful:

map_by_method

Posted by Matt Williams

If you have a collection of objects, such as an array of students, and you want to quickly and easily capture their names, you can use: students.map_by_name which will return the names of the students as an array. This is a ruby gem and you can find more information about it at: map_by_method

Find or Create

Posted by Matt Williams

I found myself recently typing code like:
1
2

foo = Bar.find(:first, :conditions => {:name => "Fred"}) || Bar.new(:name => "Fred")
As it turns out, there's a rails method for this: Model.find_or_create_by_COLUMN, where COLUMN is the name of the column.

(Not) Helpful Helpers

Posted by Matt Williams

In Rails 2.0.x, application.rb has a:

1
2

helper :all
which has the effect of including all the helpers. In general, this is helpful. However, if you want to have different behaviour in different controllers, this can cause problems, because only one behaviour will be available for all controllers. And the behaviour seems linked to the default load order (alphabetical) -- that said, if you have two controllers FooController and BarController, then the helpers will be loaded in the following order:
  1. ApplicationHelper
  2. BarHelper
  3. FooHelper

So, if you expect to have different behaviours in Foo and Bar, you'll be disappointed. The behaviours override each other, leaving a single behaviour across the application. In order to fix this, remove or comment out the declaration in application.rb.

cheat

Posted by Matt Williams

Cheaters never win, or do they?