Friday, June 26, 2009
Tracking value changes in ActiveRecord objects
http://ryandaigle.com/articles/2008/3/31/what-s-new-in-edge-rails-dirty-objects
This can be useful if validation varies based upon the prior state of the the object, etc.
Rails Time Zone Support
http://mad.ly/2008/04/09/rails-21-time-zone-support-an-overview/
Thursday, June 11, 2009
Ext JS with Rails
One of the first steps described in the Ext tutorials is just getting a page set up referencing the javascript libraries: http://extjs.com/learn/Tutorial:HTML_Page_Setup
Unfortunately, that example didn't work in rails. However, taking some suggestions from here, putting this in the head of a rails layout seems to work:
<%= stylesheet_link_tag '../javascripts/ext/resources/css/ext-all' %>
<%= javascript_include_tag 'ext/adapter/prototype/prototype.js' %>
<%= javascript_include_tag 'ext/adapter/prototype/effects.js' %>
<%= javascript_include_tag 'ext/adapter/prototype/ext-prototype-adapter.js' %>
<%= javascript_include_tag 'ext/adapter/ext/ext-base.js' %>
<%= javascript_include_tag 'ext/ext-core.js' %>
<%= javascript_include_tag 'ext/ext-all.js' %>
script type="text/javascript" (took off the <>'s from this line for posting)
Ext.BLANK_IMAGE_URL = "../javascripts/ext/resources/images/default/s.gif";
Ext.onReady(function() {
console.info('finally!');
});
/script (took off the <>'s from this line too)
This is basically what's in their tutorial html page, but with extra include tags... It assumes that, as they suggest, you unzip extjs under the rails public/javascripts directory. For the example above, the directory was just named 'ext'.
With that in place (the onReady can be removed), a page using that layout can do something like this:
<%= link_to_function 'Ext Test',
"Ext.MessageBox.show({title: 'Ext Box',
msg: 'Ok?',
buttons: Ext.MessageBox.OK})" %>
(Note: this was Rails 2.2.2 with ExtJS 2.2.1)
Monday, May 4, 2009
More on Saving Dates to Oracle
However, in the process of determining which setter method to use, it looks at the skip_time_zone_conversion_for_attributes list, which controls whether to do the timezone conversion or just generate the standard setter method for the attribute. You can just add a line to your active record class, like this:
skip_time_zone_conversion_for_attributes << :my_date_attribute_name
With that line added, the date remains a date, and everything in the persistence layer is happy.
As I mentioned, I haven't tried it yet, but the new oracle enhanced adapter looks like the way to go. I thought I'd post this anyway, in case it's of use to anyone else -- there doesn't seem to be much written about "skip time zone conversion", and it might be useful in other situations...
Friday, May 1, 2009
Saving Dates to Oracle with JRuby / Rails
Date attributes that were set in a view worked fine, but those that were set programmatically were getting saved with the time -- the time being offset from midnight based upon my timezone. I messed with the timezone setting ("config.timezone =" in environment.rb), but everything seemed to be working fine except this. It works if you set the attribute to a string value (i.e., '2009-05-01'), like the view / controller code does, but that's a pain.
So, digging through the activerecord extensions in jdbc_oracle.rb, I found that it tries to guess the type based upon whether there are values for hours, minutes, or seconds in the ActiveSupport::TimeWithZone objects that get sent through. The ones coming from the view had no hours, minutes, nor seconds, but the ones that had been set in the code (originally set to Date.today, for example) were getting converted into TimeWithZone objects that were midnight on the specified date, then adjusted for the timezone, turning the date part into the prior date. (I didn't dig through the rails code to find out where/how/why that conversion is taking place, but that might yield a better solution -- if any body knows, please share!) Since rails uses TimeWithZone objects, that seemed like a reasonable place to look.
Looking at the doc for TimeWithZone, it says that you shouldn't ever create instances directly, you should use TimeZone methods instead, via the Time.zone instance. The TimeZone methods include "today", "local", "parse" etc -- nice! So I tried each of those:
- a = Time.zone.today
- b = Time.zone.local(2009, 5, 1)
- c = Time.zone.parse('2009-05-01')
So, until I have time to dig through rails to see if there's a way to avoid the time zone conversion (besides setting the attribute to a string), I'll start using the TimeZone methods, with this little patch stuck in the config/initializers/ directory:
class ActiveSupport::TimeZone
def today
today = Date.today
self.local(today.year, today.month, today.day)
end
end
Again, if anyone has another suggestion, please share. Also, I'm not sure if this is JRuby-specific, but I don't have time to test that right now either...
(Note: running rails 2.2.2 w/ jruby 1.1.5 and activerecord-jdbc-adapter 0.9)
Tuesday, April 21, 2009
Rails 2 Functional Tests with HTTP Basic Authentication
Wednesday, March 25, 2009
Warbler deployment to development environment
Wednesday, March 11, 2009
Multiple Gem Repositories
Thursday, February 26, 2009
HowToUseMultipleGemRepositories -- Rescued!
HowToUseMultipleGemRepositories
The gem utility is a handy way to manage software components in Ruby. When using Rails, though, you can sometimes find yourself in a position where gems might start to look like a handicap!
- Perhaps you are installing a Rails application on a managed host account and it needs a gem which the system administrator does not support.
- Perhaps you’re a system administrator and you want to allow individual users to add their own gems, without polluting the global collection you provide centrally.
- Perhaps you just want individual Rails applications to have their individual requirements kept separate from each other to avoid Ruby’s own equivalent of DLL Hell…!
As it happens, it’s entirely possible to support more than one physical gem repository. The key to this is the GEM_PATH
environment variable. While the GEM_HOME
environment variable is relatively well known, not so many people have heard of GEM_PATH
. Below I’ll describe how to use this to configure and initialise a new gem repository, then logically, but not physically combine that new collection with other existing repositories which Ruby code will treat as one large, combined set of available gems.
1. Decide on locations
1.1. A new gem installation
You’ll need to install a new copy of the gem utility, at least temporarily. Create an empty ‘geminstall’ directory to hold the gem installation itself – e.g.:
mkdir /home/username/ruby/geminstall
1.2. Location of the new repository
Create an empty directory to hold the gem repository (that is, the location where any gems you install will actually live) and set GEM_HOME to this location – e.g. assuming a bash
shell:
mkdir /home/username/ruby/gems export GEM_HOME=/home/username/ruby/gems
2. Initialise the new repository
2.1. Get the gem installation package
Download the gem installation package from:
http://rubyforge.org/frs/?group_id=126
At the time of writing 0.9.0 is the latest version; using wget
you might do this:
wget
http://rubyforge.org/frs/download.php/11289/rubygems-0.9.0.tgz
2.2. Unpack into a temporary directory
Create a directory for temporary use and unpack the archive into it. For example:
mkdir /home/username/temp mv rubygems-0.9.0.tgz /home/username/temp cd /home/username/temp tar -z -x -f rubygems-0.9.0.tgz
2.3. Look at the unpacked contents
Change into the unpacked directory so you can see the CHANGES
, README
etc. files. E.g.:
cd rubygems-0.9.0 ls
2.4. Ask the setup program to install everything, make sureGEM_HOME is set to the gems directory from step 1.2
Issue the following command:
ruby setup.rb all --prefix=/home/username/ruby/geminstall
…replacing /home/username/ruby/geminstall
with the path to the ‘geminstall’ directory that you created in step 1.1 (and not the one you created in step 1.2!). The command should finish up by saying something like Successfully built Rubygem
, with a bit more information on what it built afterwards. If not, look for error messages and see if you can figure out what went wrong (e.g. perhaps there were no write permission in the gem installation or repository directories, or maybe you have an incorrectly set GEM_HOME
– double-check it with echo $GEM_HOME
).
NOTE: If you already have rubygems installed, make sure the version you are installing matches the version you have installed (or upgrade your existing rubygems first). Otherwise you may run into strange errors due to mismatched files.
2.5. Make sure it worked!
You should find new directories along the lines of bin
and lib
in the directory you created in step 1.1. You should also find new directories along the lines of cache
, doc
, gems
andspecifications
in the directory you created in step 1.2. This is your new gem repository, now initialised and ready for further use.
NOTE: If you receive the message “/gem:9:in `require’: no such file to load — rubygems”, you will have to set the RUBYLIB environment variable to point to the ‘lib’ directory inside your gem install directory, like so: export RUBYLIB=/home/username/ruby/geminstall/lib
2.6. Don’t already have gem
installed?
If you don’t already have gem installed on your system you will want to add the path to the directory specified in step 1.1 with /bin
on the end to your PATH
environment variable. E.g.:
export PATH=$PATH:/home/username/ruby/geminstall/bin
2.7. Do already have gem
installed?
If you do already have a copy of gem on the system, now would be a good time to delete the ‘geminstall’ directory you created in step 1.1, along with its contents. You don’t need the second copy of the gem package, you only need the ‘gems’ repository directory. So:
rm -rf /home/username/ruby/geminstall
…taking care to provide the full path to the location of the unwanted new gem installation (geminstall) from step 1.1, not the path to the new gems repository from step 1.2.
3. Examining the repository contents
3.1. What do the GEM_...
variables do?
While environment variable GEM_HOME
controls where gem will write things, variable GEM_PATH
controls from where gem
and requirements in Ruby scripts will read.
3.2. Querying the default repository
If you issue the command gem query
with GEM_PATH
unset you’ll see the list of gems installed in your system default repository, if you have one, not your new repository.
3.3. Querying your new repository
Set GEM_PATH
to the ‘gems’ directory you created in step 1.2 then query the repository again:
export GEM_PATH=/home/username/ruby/gems gem query
This time you should just now see one gem – the sources installed as part of repository initialisation in step 2.4.
3.4. GEM_PATH
is the key when reading
So, GEM_PATH
is the key to supporting multiple repositories. To treat multiple physical repositories as one big logical gem collection, set the variable to a colon-separated (semi-colon on windows) list of repository locations. For example, if you have a system-wide default repository at/lib/ruby/gems/1.8
you can get Ruby to search your new repository first, then the system one, using:
export GEM_PATH=/home/username/ruby/gems:/lib/ruby/gems/1.8
If you have two or more of the same gems with the same version, the one in whichever repository appears first in the path will be used. It shouldn’t ever matter, though, as if they’ve the same version number they ought to be identical anyway.
3.5. PATH
to gem binaries
You need to add the new gem repositories bin sub-folder to the PATH environment variable in front of the default gems repository bin path otherwise any new gems installed in this repository will not have their bin wrappers in the path and you will not be able to run them as you normally would from the command line. For example, if you installed a gem like piston in this new repository a small shell script or batch file will be put in the repositories bin folder so that you can launch the piston script by simply typing ‘piston’, but the shell script or batch file will not be found if the bin folder is not in the path.
4. Modifying the new repository’s contents
4.1. GEM_HOME
for writing, GEM_PATH
for reading!
Always ensure that environment variable GEM_HOME
points to the
repository you are interested in before running the gem
command to modify a repository, or any other commands that modify the contents of a repository. This is very important! If the variable is unset, you’ll operate on the system’s default gem repository.
4.2. Business as usual
Once you’ve set GEM_HOME
to point to the right place, just use gem
in the usual fashion to delete or add new gems – see the RubyGems Manuals for more information.
If you want to make a quick repository change and just temporarily set the location, gem
supports various command line switches to help. For example:
gem install [gem-name] --install-dir=/path/to/repository
…will do what the command implies. Depending on how you work this might be a better method than setting the environment variable. However, if you take the environment variable approach, there’s no danger of forgetting to specify the repository location on the command line and ending up accidentally attempting an operation in the wrong place. Again, see the RubyGems Manuals for more information on command line parameters.
5. Using the repositories in future
You will need to make sure GEM_PATH
is set up wherever you want Ruby programs, including Rails applications, to use multiple gem repositories. The best place to do this will vary depending on your system configuration. Use, say, your .bashrc
file or the Web server configuration file for Rails applications if it supports launching them with a configured private set of environment variables.
That’s it – all done. Remember to set GEM_HOME
when adding or removing items; remember to setGEM_PATH
when reading from one or more repositories. Now you can keep your gem collections compartmentalised if you wish, provide individual repositories for individual users, or if you’re on a rather limited managed hosting service, have a good chance of being able to add your own gems to a private collection without needing to go to the system administrator.
Note
If you are attempting to do a local-only install of multiple dependent gems, you need to cd to the directory containing the gems.
Tuesday, February 24, 2009
Linux Search
Friday, February 6, 2009
Jruby Ubuntu TimeZone Problem
Both boxes are running Ubuntu Intrepid Ibex (8.10). On both machines, the jruby app was set up in its own account, with its own copy of java and jruby. The same versions of java and jruby were used; in fact, the downloads (jdk-6u10-linux-x64.bin and jruby-bin-1.1.5.tar) were copied from the old machine to the new.
The only difference I found was that the new machine (which I inherited, but is faster) has java 1.6.0_0 installed in /usr/bin. However, the account set up for the jruby app has JAVA_HOME and the PATH set so that java 1.6.0_10 is being used on both machines.
Thanks to Vladimir Sizikov (and others), I found a solution. This bug report started me on the right path, and this one almost gave me the fix. On the second one, Vladimir said "Once I replace /etc/localtime with proper America/New_York file, everything gets back to normal", so I copied the /etc/localtime file from the old box to the new. Still the same problem...
In another one of Vladimir's posts, he suggested this code, which shows the problem:
- jruby -rjava -e "p org.joda.time.DateTimeZone.getDefault.getID; p java.util.TimeZone.getDefault.getID"
After more hunting (using the SystemV timezone clue), I found this post, which suggested "change /etc/localtime to a symbolic link again", so I got rid of the localtime file and created a link to /usr/share/zoneinfo/CST6CDT, and that worked! However, it really wasn't the link that made the difference -- I copied the CST6CDT file from zoneinfo instead of linking to it, and that also worked.
So, since the localtime file from the old machine works there, but doesn't work on the new machine, and using the localtime file from zoneinfo does work on the new machine, there's still something else going on that I don't understand. But since it's working...
Tuesday, January 27, 2009
Vim Settings for Ruby
filetype on " Enable filetype detection
filetype indent on " Enable filetype-specific indenting
filetype plugin on " Enable filetype-specific plugins
set ic " Case insensitive search
set hls " Highlight search
set showmatch " Show matching brackets
set expandtab
set autoindent
set tabstop=2
set shiftwidth=2
set softtabstop=2
Sunday, January 25, 2009
Rails on Ubuntu Intrepid Ibex
- zlib1g-dev
- libzlib-ruby
- libssl0.9.8
- libssl-dev
- libopenssl-ruby
- cd ext/openssl
- ruby extconf.rb
- make
- make install
Wednesday, January 14, 2009
Ubuntu Package List: Available vs. Installed
dpkg -l : lists all installed packages (Can apt-cache do it?)
Also useful:
apt-get update : updates the local list of available packages
apt-cache search
Reference: http://www.debian.org/doc/manuals/apt-howto/index.en.html
Tuesday, January 13, 2009
Ruby Gem Repository Setup
MD5 Checksums (Ubuntu)
Then the md5 command is:
md5sum -c checksum_file
Monday, January 12, 2009
Building Ruby
- download the source
- tar xvzf ruby-1.8.5.tar.gz
- cd ruby-1.8.5
- ./configure --prefix=$HOME/ruby
- make
- make install
Friday, January 2, 2009
Thursday, January 1, 2009
Synergy: One keyboard to rule them all...
- Settings > Windows Firewall > Advanced (tab)
- Select connection, hit Settings button
- On that window, hit Add...
- Give it a name, add the IP for the linux box, and put in the synergy port (24800)