The mysteries of size, length and count

ActiveRecord Association and ActiveRecord NamedScope have subtle differences in the way they respond to size, length and count (based on whether records are eager loaded or not) that sometimes leads to some weird results and one can easily land up spending some time debugging these issues.

For more details on this behaviour see 

http://www.wuputah.com/2010/05/24/count-size-and-length-associations-vs-named-scopes/

http://blog.hasmanythrough.com/2008/2/27/count-length-size

So when you want the actual count always call the .all method or do an explicit reload and then call any of the three methods. It helps rely on Array or the collection of reloaded results to give the right result rather than interfering with eager loading, unsaved records and other such stuff. 

 

Advertisements

My experiences with page caching

Lately I have been working on a legacy rails project which had page caching in place. Here are a few points I think are takeaways for me from my experience with it:

1) Page caching is useful on pages which have more or less content related to same resource. If you have multiple kind of unrelated content loading on the page which expire at different times, then the page cache may not be of much use. And you may be clearing out the entire cache for that page unnecessarily when one piece gets updated thus affecting your performance.

2) When page caching comes into picture you can’t have user specific code in the server side code for those pages. Particularly, beware of putting in cookie checking code on the server side. It should probably not be there anyways, but yeah if you have it for some reason, do not forget that you are using page caching. One may argue that why would one use page caching for user specific content anyways, but on pages where extremely minimal stuff is user specific, it is very easy to forget that there is page caching in place. And then you will land up having pages cached in a state based on the first viewer of that url and all other users would see that view. 😦 

Ofcourse you can have javascript to handle your dynamic content.

3)  Do not depend only on ui interfaces to clean up your page cache. Admins who don’t understand it completely will keep clearing your cache every now and then and your pages would perform poorly. Have sweepers for observing content and deleting the corresponding cached pages automatically (which is the natural way for page caching invalidation 🙂 ) rather than admins taking a guess that this particular page cache needs to be cleared when I update this content.

Page caching can lead to a lot of performance boost if the above points are kept in mind since then the time required for the request to process would be just the time required to send back the html. And extremely expensive requests would start serving almost in the same time as normal requests.  

For more details on page caching and dynamic content on cached pages see 

http://railscasts.com/episodes/89-page-caching

http://railscasts.com/episodes/169-dynamic-page-caching

http://railscasts.com/episodes/89-page-caching-revised

http://railscasts.com/episodes/169-dynamic-page-caching-revised

Disable browser cache for cucumber scenarios

Some time back, we faced this issue where we had setup cache control headers for certain actions in our rails app. Now when the cucumber scenarios for these actions ran, for scenarios in the same feature when the browser did not go off, the cached results would show up and our build would fail.

So here’s a quick tip to disable browser cache (for firefox) for cucumber. In your env.rb where you initialize the selenium driver, you need to put in some settings for the profile that gets used for your browser.

Capybara.register_driver :selenium do |app|

    profile = Selenium::WebDriver::Firefox::Profile.new

    profile[“browser.cache.disk.enable”] = false

    profile[“browser.cache.memory.enable”] = false

    Capybara::Driver::Selenium.new(app, :profile => profile, :http_client => WebDriver::Remote::Http::Curb)

end

 

For details on these two properties of firefox see 

 

observe_field in rails

There used to be this method observe_field in rails upto v2.3.8 under ActionView::Helpers::PrototypeHelper. To give more details – here is the snipper from apidock

observe_field(field_id, options = {}) public

Observes the field with the DOM ID specified by field_id and calls a callback when its contents have changed. The default callback is an Ajax call. By default the value of the observed field is sent as a parameter with the Ajax call.

You need to specify url for the ajax call / a javascript function that you want to execute on the change of the field. Additional options give you flexibility to specify how frequently the action is supposed to take place, options to specify more parameters to the ajax call. 
The use case for this is something like selecting from a dropdown, and updating some content on the page based on the selection. 

However the caveat here is, you cannot do something like the jQuery live functionality. If you have more select boxes coming up later after the page has already loaded, your ajax calls won’t happen on selecting something from the new dropdown. 

Secondly this seems to work only for the change event on fields although on dom elements I would like to have reused the same method for multiple other events like ‘click’, ‘mouseover’, and so many more.

In addition, there is an observe_form method that can help out a bit with the 1st problem by observing all fields within the form for changes, however with dynamic elements (not in the original source of the form) coming up it again fails. (Jquery has made life so much easier and natural rather than trying out weird solutions to do stuff like this.)

So whats up with this method now?

This method has been deprecated. In fact the PrototypeHelper has seen a lot of change. Legacy prototype helpers are available as a plugin now. https://github.com/rails/prototype_legacy_helper in favour of making Rails 3 agnostic of javascript frameworks.

Ofcourse, jQuery can handle the above scenarios with much more flexibility and cleaner code. 

So if you are upgrading a legacy project which has usages of observe_field, it would be advisable to go for jQuery and keep it clean, simple and working 🙂

Rails: Multiple validations on single condition

Came across this scenario, where we needed multiple validations to kick in on the same logical condition. It landed in repeating the condition for all the validation statements. But stumbled upon this option.

with_options :if => :email_notification_required? do |condition|

    condition.validates_presence of   :email_recipient_name

    condition.validates_length_of   :email_recipient_name, :maximum => 255, :allow_blank => true

    condition.validates_presence of   :email_address

    condition.validates_length of   :email_address, :maximum => 255

end

(The italicized fields are specific to the example. )

So all the validations in the block kick in only if the boolean method email_notification_required returns a true.

This may not always be the way to go, there may be indications that probably this is not the right place for all those validations, perhaps they can be moved out, but nonetheless, its an option you may need sometime.

Faking Ubuntu to seem and look like Windows :)

Ubuntu lovers would deem this completely unnecessary. But I had to do it so that my parents could continue working with a fast working (or lets say working!!) OS that doesn’t ask too many questions and yet has the look and feel that they are accustomed to. 

  • So I googled for what the world is doing on these lines and this is what I found –  http://ubuntu.online02.com/xpgnome. Very simple stuff in there. This worked for me perfectly, and haven’t faced any trouble yet. It also comes with a restore settings option, just in case.
  • Next I needed to deal with a weird problem that Ubuntu 9.10 has. To use DSL connections for the Internet, it is necessary to run the pppoeconf command. And every time you start the machine, you must use sudo pon dsl-provider. This seems fine for people used to command line utilities but for my parents its just some weird stuff that they want to have abstraction from. So again, created a launcher which has the icon like the network connection one in windows. And in the launcher simply wrote some shell script commands to get the job done.

echo password
sudo -S pon dsl-provider (-S being there to make use of the password just echoed out) 
And for notification purposes, to let you know that the connection is actually done, I used gxmessage utility.

  • Installed wine to get hold of some typical Windows software that my parents are used to like Notepad.

Did some more similar stuff and the machine was ready for use. Minimal effort, minimal learning curve for parents and the job is done! 

SimplyHelpful

SimplyHelpful was a plugin used in legacy rails apps for generating the right dom id, css classes for records. For more info read http://juixe.com/techknow/index.php/2007/04/03/simply-helpful-rails-plugin/. However, Simplyhelpful is now in rails. So you will no longer need the plugin. And methods like dom_id are available out of the box now. Just get the scoping correct.

 

To give a specific example, for the dom_id method, usages may have been in helpers or views, and in that case you may get errors where Rails starts looking for dom_id method under ActionView. You will have to fix this. You need the RecordIdentifier module of ActionController.

 

 

 

Getting started on Rails upgrade (Rails 1 to Rails 2)

There are plugins now to upgrade from rails 2 to rails 3 (For details look at https://github.com/rails/rails_upgrade). However for rails 1 to rails 3 its a huge jump. So its most advisable to go from rails 1 to rails 2. And then use the plugin to help with the rest of the upgrade.

So when we started off with this task, we found a great post here http://marklunds.com/articles/one/409. It gives a great starting point to get the ball rolling. 

Few things you need to keep in mind, 

1) Steps 1, 2, 3 mentioned in the post above may not be needed if you are not planning to vendorize rails. 

2) Its best to introduce bundler at a point you deem comfortable since that can help you out with managing gem dependencies very comfortably. You can follow the steps given in http://gembundler.com/rails23.html to make bundler work with rails 2.

3) Also when you are looking for corresponding gems or plugins for rails 2, it would be helpful to investigate more into what the plugin/gem actually does since quite a few gem/plugin behaviours got integrated into rails later or new better plugins got introduced for them.

At the same time, if you can’t find options, just investigate more into the errors you get after migrating to rails 2, and try to solve them. It may be as simple as using ActiveSupport::Inflector instead of Inflector, moving inflections to the right place, etc. 

At every point keep referring apidock, guides.rubyonrails.org, rdoc for reference on which methods are deprecated and what are their corresponding alternatives now.

 

 

Rails upgrade

Recently I have been working on upgrading a legacy app from Rails 1.2.6 to 2.3.11. No doubt it has been a difficult task primarily because

  • It demands good knowledge of how things worked in the old Rails, how they do now
  • lack of enough documentation on Rails 1.2.6 currently available on the web.
  • Usage of gems and plugins which are no longer supported anymore.
  • And life can just become worse if you have custom plugins.

Nonetheless, whatever help I received from the web prompted me to start off with this series. As Matz says Ruby community is a good community, I think its important for us to continue the tradition by giving back to the community in the form of sharing anything that can help people out there.

I will keep posting anything interesting or anything that took me a lot of pain to solve in this series, in short my learnings.