Skip to content

Rails, nested attributes and before_save callbacks

I had a Project model with a many ProjectWell (as in oil) association. Taking advantage of the accepts_nested_attributes, I was able to persist both Project and ProjectWell attributes through a single web form.

Now, the ProjectWell had fields that I wanted to calculate and assign on each ProjectWell save. Naturally a before_save operation (within an observer or such) would’ve been sufficient. The main requirement I had was to have all ProjectWell callbacks fired regardless of the Dirty state of the ProjectWell object.

Given Project p with an associated ProjectWell p_well (both already exist in the database):

This will NOT update the ProjectWell (p_well) object in the database, and hence will NOT fire any of the required callbacks. The main reason is that the p_well attributes didn’t change. The name attribute is the same as the one already in persisted.

My next attempt was to try to disable the partial_updates for ActiveRecord. In an initializer, I’ve placed this configuration:

What this does was disable selective attribute updates for ProjectWells (and all other objects). In other words; it updates all ProjectWell attributes, regardless of whether or not those particular attributes have changed. But this happens ONLY when ActiveRecord detects at least ONE changed attributes.

In my case, there were no changes in any of the attributes, which made Rails skip the update operation altogether.

My work around was to ‘simulate’ an attribute change, in one of the attributes, even if it hasn’t really changed by the user.

A first attempt was to create a virtual (non-persisted) attribute in the model (attr_accessor :force_save). Unfortunately, it changes to the attribute (corresponding to its default value) didn’t trigger Rails dirty check.

A second attempt was by using ‘_will_change!’ dynamic method. The method can force Rails into registering the corresponding attribute as a changed one.

This threw an undefined method error of ‘force_save_will_change!’.

The _will_change! method is only available for DB persisted attributes (defined in the corresponding table).

My next attempt made by selecting a non-virtual attribute to use the will_change! against.

This resolved the issue by always setting the ProjectWell state to dirty update an update to name attribute, regardless if the previous name was the same as the new one.

Now, when executing the update_attributes – passing in the name attribute (whether with a name change or not) will fire off the save operation and consequently the before_save callback

Note: Setting ‘autosave’ and ‘touch’ on the relative association declaration didn’t help.

Any other way of doing this?

Stack: Rails 3.1.0, JRuby 1.63, activerecord-oracle_enhanced-adapter 1.4, Windows XP

Posted in Ruby.

FactoryGirl with Oracle enhanced adapter – an attribute of name ‘id’ is not assigned

My question and answer are also posted on StackOverflow

I have an Oracle test table with ID column that is not a primary key, not an autoincrement and with no sequence defined. It only has NOT NULL defined. The corresponding structure in development schema is an Oracle View rather than a table with a primary key defined against the ID column.

My factory definition looks like:

These tests fails

I’ve added attr_accessible :id to my model (just in case), but with no luck.

I’ve also defined id= method in my model def id= id; @id = id; end. The call is made to the method and @id is written, but looks like it is overwritten later in the callstack (between FactoryGirl and ActiveRecord).

Other attributes are normally assigned.

After a bit of digging – I found the I found the culprit:

The write method in ActiveRecord::AttributeMethods::Write module has the line:

It means that if the attribute name to be set has the name of ‘id’, pick the primary_key as the name of the attribute to assign the new value to. And since in my test table there is no primary_key returned by the oracle_enhanced_adapter (rightfully), the whole write operation is skipped.

My solution was to override the write method (only when running tests) skipping that line so that the id is written to.

Posted in Ruby.

Test Oracle Database Views with Rails

Testing Rails with a legacy oracle schema as a backend is always a challenge (fun?).

Rails relies no schema.rb to create its test database. The problem is that using the latest activerecord-oracle_enhanced-adapter (1.4.0), the application is unaware of the database views.

So, I’ve decided to create those DB views (development) as DB tables (test).

The script can run as a db:test:prepare rake task or as being explicitly required somewhere at the beginning of the test_helper. And of course, this is just the initial working concept – it can be greatly improved.

JRuby 1.6.3
Rails 3.1
activerecord-oracle_enhanced-adapter 1.4.0

Posted in Ruby.

Die IE7. Die.

or NAME attribute.

Why the heck a method with called “getElementByID” return NAME matches?!

Here’s the story:

Two elements with different IDs, with one of the IDs matching the name of the other.

Posted in Web.

Rails – disable timezone conversions

In order to globally disable the use of TimeZone conversions for your (legacy?) application – here’s the proper configurations:

In config/application.rb (or config/environment.rb depending on Rails version):

Posted in Ruby.

Heroku timezone adjustment

Setting up timezone on Heroku instance using heroku gem (command line)

Heroku apparently accepts zoneinfo timezones.

Posted in Ruby.

Contents Invalid public key / Fingerprint can’t be blank

Getting the above error message trying to deploy to Heroku (Windows, PuTTY keygen).

Turns out the public/private key files saved through putty aren’t of a valid OpenSSH format (expected by Heroku). You can still use Putty Keygen by copying the text generated under “Public key for pasting into OpenSSH authorized_key file” (save it to your *.pub)

I’m inching towards my first Mac. Windows is a frustration after the other.

UPDATE: working with Heroku/Git/SSH on a windows machine is a royal pain. One step closer to a MaxBook.

Follow these if you’re stuck:

My setup so far is “Putty Keygen, Putty, Pageant, Git GUI”

Posted in Ruby, Web.

NoMethodError: undefined method `eq’ for nil:NilClass

JRuby 1.5.2
Rails 3.0
activerecord-jdbc-adapter 0.9.7

This issue arises when setting table name with a schema name prefix. For those in the know – this is a must-have if you’re connecting to oracle using a non-owner username (activerecord-jdbc-adapter).

Now – tracking this down led to

The @@tables include table names as read from the connection (sans schema name). The comparison with the name always yields false resulting in an instantiation of an empty Header (with no attributes). Hence – alias_table[<attr>] always returned nil and nil.eq is undefined.

Anyways – as a work around (sorry: non tested monkey patch):

in your apps lib folder (provided that it’s auto-loaded) – create the arel_ext.rb

Reported on activerecord-jdbc-adapter list:

Posted in Java, Ruby.

Java for the forever beginner (II)

If your JSP code is almost 2/3rd pure Java code, then you’re doing something wrong.  One easy way of knowing Java code from HTML/Snippets is to look at the PALE GREEN (see image for color tone). If the pale green is more than the white – then you must be joking.

If you move the green parts to become white on their own java files; Your future self will thank you for it.

Or at least you won’t get cursed.

Posted in Java, Web.

Java for the forever beginner (I)

If a stylesheet link tag for a ‘default.css’ file is repeated in 10 different files; when it’s only a SINGLE PAGE WEB APPLICATION – you’re doing something wrong.

Posted in Java, Web.