Category: Ruby

All things ruby (the programming language)

Rails models with attributes that shouldn’t be updated

Situation
A Ruby on Rails project I’m working on during my day-time job (as if I have a night-time one) has a couple of tables with fields that are changed by external processes. (note: it’s a legacy oracle database that’s had some slight mods where possible to make it more Rails-y). The bulk of fields in these tables however contain data that can be changed using a Rails interface I’ve build. These not to be updated fields need to be initialized when writing a new record and should be read (to be displayed) as normal fields.

So what’s the problem then?
Normally you’d just issue an update to only modify the needed fields, but at the moment ActiveRecord can only alter records by doing a read followed by an update of all fields (please correct me if I’m wrong).

This poses the problem that some fields might be changed by an external process after the read and before the write, resulting in ActiveRecord writing the old data back to the table. (resulting in a whole bunch of unwanted, very evil things of which I really don’t even want to think about fixing)

Solution
I found a workaround by overriding update_attributes in my model as
follows:


def update_attributes(attributes)
@attributes.delete('fieldthatshouldnotbechanged1')
@attributes.delete('fieldthatshouldnotbechanged2')
@attributes.delete('fieldthatshouldnotbechanged3')
super(attributes)
end

This effectively deletes the fields from the hash that’s used to construct the update statement. You’ll see in your development.log that the issued update statement doesn’t contain the deleted fields anymore.

I only tried it with update_attributes since that’s what I used to update the fields.

I hope this doesn’t cause any unwanted issues, but if it does I’ll post about it here.

Switch between Rails controller and view in Komodo

Yesterday I tried radrails, which is quite nice for a free tool. Being a Komodo fan however (thanks to my employer for paying the license) the only obvious advantage for me would be being able to switch between controller and corresponding view.

Because I was getting a bit jealous of this feature in Textmate/RadRails/… I cooked up a way to do the same in Komodo.

How can this work in Komodo ?
When calling external commands (via the Toolbox) in Komodo you can give path + linenumber of current file being edited (amongst others) as parameters. You can start the Komodo binary passing a filename + linenumber, and Komodo is nice enough not to start itself twice or load the same file twice when doing this.
The ‘figuring out what controller/action we’re in and calling the corresponding view‘-part (and vice versa) is handled by a little ruby script. (which could probably be much tighter, but I’m still a ‘ruby nuby’ and if I have to clean it up before publishing it’ll probably never leave my personal Toolbox… so be thankfull I have enough guts and ego to dare publish my dirty code 😉

How to install this script in the Komodo toolbox ?

  • Save the script below (let’s call it ‘open_ctrl_view.rb’) wherever you like to save such things.
    Remember to chmod +x it to make it executable!
  • In open_ctrl_view.rb : Edit the path to your komodo installation, or just put ‘komodo’ if komodo is in your search path.
    Edit the shebang to point to the correct ruby version if necessary.
  • In komodo: add new command in toolbox. As command, enter ‘open_ctrl_view.rb %F %L’ (include full path to whre you saved open_ctrl_view.rb if necessary)
    %F will insert the full path and %L the current line of the file being edited
  • Run in: ‘Command Output Tab’ (default option) and I marked ‘Do not open output pane’ below. If necessary you can always switch to the output pane manually if something went wrong.

Add key binding if necessary (warning: this is a bit buggy in Komodo 3.5.2 but should be fixed in 3.5.3)

Windows users: Probably the same as above, except no need for chmod’ing, and you’ll probably need ‘ruby open_ctrl_view.rb %F %L’ instead as command.
Mac users: Aren’t you using Textmate ?

The script (open_ctrl_view.rb)
No guarantees are made. Your head might explode, ladadi ladada, etc.
I was going to include it as text in this post, but even enclosed in the proper tags it looks all funny, so download it here.

Closing comments…
If you make nice enhancements: let me know! (what about a similar script that loads the model your cursor is positioned on ? Komodo can also send the word your cursor is on as a parameter)

Conditional partials in Ruby on Rails

Have you ever wanted to include a partial in Ruby on Rails only if the partial file actually exists ? This can be handy e.g. if you want to be able to include a special menu (as a partial) for some controller actions based on the action name (controller.action_name) but don’t want to make a dummy partial for every action (which is normally needed since Rails will throw an error if it can’t find a partial).

The following example will render a partial contained in the file _.rhtml only if this file exists:

def render_menupartial
render_partial(controller.action_name) if FileTest.exist?(File.join(RAILS_ROOT, 'app', 'views',controller.controller_name,'_'+controller.action_name+'.rhtml'))
end

remember to call this from your view (or probably layout) like < %= render_menupartial %> instead of < % render_menupartial %>.

I know: basic stuff, but since I already used this basic functionality quite often I’m sure someone out there will find this useful.

Ruby/OCI8, Oracle and ORA-12705

After installing the Ruby/OCI8 module on a Windows XP installation where sqlplus is working fine I got the following error when testing the connection in irb:


irb(main):012:0> cn = OCI8.new("username","password","database")
OCIError: ORA-12705: invalid or unknown NLS parameter value specified
from c:/ruby/lib/ruby/site_ruby/1.8/oci8.rb:158:in `begin'
from c:/ruby/lib/ruby/site_ruby/1.8/oci8.rb:158:in `initialize'
from c:/ruby/lib/ruby/site_ruby/1.8/oci8.rb:158:in `do_ocicall'
from c:/ruby/lib/ruby/site_ruby/1.8/oci8.rb:158:in `initialize'
from (irb):12:in `new'
from (irb):12
from :0

This one really took me several hours of google-hunting, finding 0 direct solutions. I was almost throwing my hat in the ring when I finally found the solution.

The Problem
In this case the ‘NLS parameter’ I was having a problem with turned out to be NLS_LANG.

This parameter is supposedly set during installation (I can’t remember choosing this, but this must be the only Oracle client installation I’ve ever done on MS Windows). The ORA-12705 error was cause by my client Ruby/OCI8 sending an incompatible NLS_LANG language parameter when connecting with this specific Oracle db.
Sqlplus, enterprise manager,… were all working fine.

Where is NLS_LANG stored on the client ?
The value was in my case stored in 3 different locations in the windows registry, always in a key ‘NLS_LANG’, once at HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE, and 2 more times in sub-keys of this location. Just do a search in regedit for ‘NLS_LANG’ and you’ll find the culprits. 1 of these NLS_LANG had the value ‘NA’, the other 2 were ‘DUTCH_BELGIUM.WE8MSWIN1252’.

If you want to test if this is the source of your issue, then apparently you can override this value using an ‘NS_LANG’ environment variable. To test this, just do ‘set NLS_LANG = ‘ in your dosbox before starting irb.

How do I know what language the Oracle db expects ?
Open a connection to the db with sqlplus (or whatever it is you’re using) and issue the following:

SQL> select USERENV('LANGUAGE') FROM DUAL;

Result:

USERENV('LANGUAGE')
----------------------------------------------------
AMERICAN_AMERICA.WE8ISO8859P1

To view all NLS parameters, issue:

select * from NLS_DATABASE_PARAMETERS;

When doing ‘set NLS_LANG=AMERICAN_AMERICA.WE8ISO8859P1’ before starting irb, connecting to the db went fine.

Will this work with rails ?
I tried ‘set’ting NLS_LANG before starting webrick, but to no avail. I really had to change registry values for rails to work when running onder webrick.
I guess (hope) it will be the same when running under a more production-level server too.

What if I need to connect to several different db’s which expect different language settings ?
God knows.
I’d start by trying to set all NLS_LANG registry entries to ‘NA’. If that doesn’t work, I’d try to find out if it’s possible to set this as a parameter when connecting. But how you would do this in Rails: ???

Please let me know if you find out!

installing fxruby on ubuntu

Did you get the following error on your ubuntu 5.10 when installing fxruby (or probably any other gem) via rubygems:

Building native extensions. This could take a while...
extconf.rb:4:in `require': no such file to load -- mkmf (LoadError)
from extconf.rb:4

then you probably need to install the ruby1.8-dev package.

Komodo with Ruby support

By the way… I started looking into ruby a while ago (after checking out what all the fuss concerning ‘Ruby on Rails’ was all about and being pleasantly surprised by both Rails and Ruby).

Now, seeing that Activestate Komodo is my favorite tool for both perl and php (it even works on both windows AND linux… and even mac os x, but I don’t use os x (yet)), I was pleasantly surprised (again) to see the next version would have ruby support.

Check the beta/alpha here.

FXRuby – require keeps returning false

You installed the fxruby gem, installed the FOX GUI library, checked dependencies, compiled and rechecked everything several times again, breaking your head why the ‘quick sanity check’ (require ‘fox14’) as suggested on http://www.fxruby.org/doc/gems.html keeps returning ‘false’ ?

Well, instead of:

require 'rubygems'
require 'fox14'

try this:

require 'rubygems'
require_gem 'fxruby'

Supposedly both should work, but somehow only the ‘require_gem’ way works for me.

…I hope this saves some people some headaches…