Displaying articles with tag

Rails 1.1 - why not "update"?

Posted by admin, Tue Mar 28 06:37:54 UTC 2006


Rails 1.1: RJS, Active Record++, respond_to, integration tests, and 500 other things!

Upgrading from 1.0

So with such a massive update, upgrading is going to be hell, right? Wrong! We’ve gone to painstaking lengths to ensure that upgrading from 1.0 will be as easy as pie. Here goes the steps:

* Update to Rails 1.1:
gem install rails—include-dependencies
* Update JavaScripts for RJS:
rake rails:update


Not so much. I could NOT get the gem install command to complete successfully. And… why the heck use “install” anyway, when there is an “update”, and I have Rails 1.0 installed already?


So, I tried:
<br />gem update rails -y<br />

And it worked. Perfectly. First time.

0 comments | Filed Under: | Tags:

Setting up ContinuousBuilder with SVN

Posted by admin, Mon Mar 13 10:39:04 UTC 2006

Ok, that was really annoying. Setting up a new build server just should not take as long as this did.

What is ContinuousBuilder you ask? Good question. If I had not bought the beta-book Rails Recipes, I would never have heard of it. A Google search on the topic brings up… yup, you guessed it, the source code for ContinuousBuilder, and nothing else. ContinuousBuilder is a plugin for Rails, that is a very (very) simple continuous integration implementation. You can install it in your Rails app by using:
ruby script/plugin install continuous_builder
If you read the accompanying README.txt, you’ll know about as much as I did when I started. On to the meaty stuff. Couple of things about ContinuousBuilder and Subversion you should know before you start…
  • ContinuousBuilder will not send email to you on success. So when everything is working, you get no feedback. And when it is really, really broken, you get… no feedback. This is not good, especially when you are setting up ContinuousBuilder for the first time. And, with a small team, I prefer to get emails for every commit, just so I know the build really is working. The answer was simple. First, in test_build.rake, I added a deliver_success call: [code lang=”ruby”] case build.run when :failed ContinuousBuilder::Notifier.deliver_failure(build, notice_options) when :revived ContinuousBuilder::Notifier.deliver_revival(build, notice_options) when :broken ContinuousBuilder::Notifier.deliver_broken(build, notice_options) when :unchanged, :succesful # Smile, be happy, it’s all good ContinuousBuilder::Notifier.deliver_success(build, notice_options) end [/code] Then, in the continuous_builder.rb file, under Notifier, I added a success method [code lang=”ruby”] def success(build, options, sent_at = Time.now) @subject = “[#{options[:application_name]}] Build working (##{build.checkout.current_revision})” @body = [ build.checkout.last_commit_message, build.output ].join(“nn”) @recipients, @from, @sent_on = options[:recipients], options[:sender], sent_at end [/code]

    Now I get messages for every commit, good or bad.

  • In Subversion, when your post-commit hook is not working, you get ZERO feedback for what is wrong. This is can be quite a time waster. But I finally found this nugget in the Subversion FAQ, that helps solve that problem:
    subversion: Subversion FAQ
    Why aren’t my repository hooks working?They’re supposed to invoke external programs, but the invocations never seem to happen.

    Before Subversion calls a hook script, it removes all variables - including $PATH on Unix, and PATH on Windows - from the environment. Therefore, your script can only run another program if you spell out that program’s absolute name.

    Debugging tips:

    If you’re using Linux or Unix, try running the script “by hand”, by following these steps:

    1. Use “su”, “sudo”, or something similar, to become the user who normally would run the script. This might be httpd or www-data, for example, if you’re using Apache; it might be a user like svn if you’re running svnserve and a special Subversion user exists. This will make clear any permissions problems that the script might have. 2. Invoke the script with an empty environment by using the the “env” program. Here’s an example for the post-commit hook:

    $ env – ./post-commit /var/lib/svn-repos 1234

    Note the first argument to “env” is a dash; that’s what ensures the environment is empty. 3. Check your console for errors.
In my case, step #2 was very informative, and I discovered that I needed some Oracle environment to be set up (ORACLE_HOME, LD_LIBRARY_PATH) because our build server is mimicking our test and production servers which use Oracle.

I hope that more people discover and use this very simple continuous integration plugin. It looks promising, but it needs a little more polish.

1 comment | Filed Under: | Tags:

TextMate has built in Subversion? Really?

Posted by admin, Thu Mar 02 08:56:01 UTC 2006

Sometimes, it’s the little things that trip you up. I’m using my new CoreDuo iMac, and some of the tools I use on my Powerbook are not available on the Intel machine. No problem, I’m flexible.

So… SCPlugin for Finder – not working. Look for alternate Subversion GUI… eventually concede  that TextMate is cheap and has support built in, so I break down and buy it (finally) and … hmmm.

Why are all the Subversion menu items disabled. Puzzle. Puzzle. (think Grinch here, people). Read the manual. Nothing. Read the FAQ. Nothing. Google search the mailing lists. Nothing. Puzzle. Puzzle.

Ok. Bright idea time. Maybe TextMate HAS Subversion support, but it isn’t installed by default. Read up on bundles in the manual. Figure out how to download the Subversion bundle. Do it. Restart TextMate. Works!

Why was this so hard? Because everything I read stated that TextMate had “built-in” Subversion support. It just did not occur to me that meant – “built-in-but-you-have-to-download-and-install-it-separately”. Maybe stuff like this should be up front in the manual?!

0 comments | Filed Under: | Tags:

ar_fixtures - great stuff, when it works

Posted by admin, Thu Mar 02 07:20:39 UTC 2006



Dump or Slurp YAML Reference Data (and Fixtures) | Ruby on Rails for Newbies

Dump or Slurp YAML Reference Data (and Fixtures)


And one more problem with ar_fixtures. We were using it to dump data out of an Oracle test database, to transfer to MySQL. Two of the columns failed to “dump” properly. A column defined in Oracle as “NUMBER” failed to export. As did another column defined as “NUMBER”. Instead of the numeric data expected, we got a bunch of : !ruby/object{}

1 comment | Filed Under: | Tags:

Importing Legacy Data ... Just for the fun of it

Posted by admin, Thu Mar 02 02:18:18 UTC 2006

java.net: Agile Legacies: Using Iterative Methods to Import Legacy Data

Indeed, importing legacy data is a crucial part of most software projects. It is also a task that rarely evokes a great deal of enthusiasm among developers. And yet it is of vital importance for the end user. These old databases often contain years of valuable business records that the user needs to access from the new application.
This is an interesting article. Since I’ve been working with Ruby for the past few months, I was reading this through my Ruby glasses ;-) and decided it was interesting to note that although Ruby on Rails developers tend to be focused on new development with new databases, there are built-in features of Rails that are particularly well suited to solving the problem of importing legacy data. ActiveRecord makes referencing existing data seem like a walk in the park. And the Migrations stuff is really tailor-made for the task of massaging databases and their contents into new forms.

The great part about this is that you can use Ruby to do it, because it’s usually a “one-shot” sort of task, and the code will not be an integral part of the production system, so who cares what language you use to accomplish this goal? So, if you are a Java programmer, and you’d like to take Ruby out for a spin in a “real world” kind of way, think of using it for your next legacy data migration task. Who knows? You might even have fun doing it…

0 comments | Filed Under: | Tags:

don't use :conditions with auto_complete_for

Posted by admin, Mon Feb 13 08:14:15 UTC 2006

Despite what the documentation might lead you to believe…


By default, auto_complete_for limits the results to 10 entries, and sorts by the given field.

auto_complete_for takes a third parameter, an options hash to the find method used to search for the records:


do not attempt to look up the “options” hash from the find method and expect all the options to work as advertised.  Especially do not use the :conditions option.  If you do, your auto-complete will be silently but completely broken.

We discovered this in a pair-programming session this morning.  Over the past week, my partner and I had individually attempted to customize a particular auto-complete_for in order to limit the returned values to a specific subset. To give you a simple “fer-instance”, lets talk about 2 tables, people and houses.  Houses belong to people.  But not all people have houses.  We needed an auto-complete on people that would limit the values returned to people who own houses.

Once again, the ability to look at the source (thanks RDoc) came to the rescue.  We eventually figured out that using :conditions would override the auto_complete_for :conditions.  So we just created our own customized auto_complete_for method for this case.

If anyone has a better solution, I’d be happy to learn about it.

0 comments | Filed Under: | Tags:

Beware multiple database access summary times

Posted by admin, Mon Feb 06 05:25:24 UTC 2006

This is a bug I have reported on the Rails Trac. Basically, our Rails application is connecting to 2 databases, but the action summary time at the end only accounts for the time spent in queries to the local (development) database, and leaves out all the time spent in queries to the second (read-only) database that resides on another machine.

The problem manifested on the production server, where you don’t get the individual query times in the log. This misled us into searching for a different problem completely, and wasted a lot of time.

Here is the log from running in development mode, illustrating the problem very obviously.  Note that only the “conditions” table is in the local database, and all other tables are in the second database.
Processing WellListController#list (for 127.0.0.1 at 2006-02-06 11:32:28) [GET]
Parameters: {"action"=>"list", "controller"=>"well_list"}
Condition Load (0.001013)   SELECT * FROM conditions WHERE (conditions.search_id = 13)
OperatorCondition Columns (0.006002)   SHOW FIELDS FROM conditions
Well Columns (0.016398)
select column_name, data_type, data_default, nullable,
decode(data_type, 'NUMBER', data_precision,
'VARCHAR2', data_length,
null) as length,
decode(data_type, 'NUMBER', data_scale, null) as scale
from user_catalog cat, user_synonyms syn, all_tab_columns col
where cat.table_name = 'WELL'
and syn.synonym_name (+)= cat.table_name
and col.table_name = nvl(syn.table_name, cat.table_name)
and col.owner = nvl(syn.table_owner, user)
Well Count (0.019738)   SELECT COUNT(*) FROM well WHERE (OPERATOR IN ( SELECT BUSINESS_ASSOCIATE FROM BUSINESS_ASSOCIATE WHERE LOWER(BA_NAME) LIKE '%sh%'))
Well Load (0.054383)   select * from (select raw_sql_.*, rownum raw_rnum_ from (SELECT * FROM well WHERE (OPERATOR IN ( SELECT BUSINESS_ASSOCIATE FROM BUSINESS_ASSOCIATE WHERE LOWER(BA_NAME) LIKE '%sh%')) ) raw_sql_ where rownum < = 10) where raw_rnum_ > 0
Rendering  within layouts/application
Rendering well_list/list
RWellStatus Columns (0.010251)
select column_name, data_type, data_default, nullable,
decode(data_type, 'NUMBER', data_precision,
'VARCHAR2', data_length,
null) as length,
decode(data_type, 'NUMBER', data_scale, null) as scale
from user_catalog cat, user_synonyms syn, all_tab_columns col
where cat.table_name = 'R_WELL_STATUS'
and syn.synonym_name (+)= cat.table_name
and col.table_name = nvl(syn.table_name, cat.table_name)
and col.owner = nvl(syn.table_owner, user)
RWellStatus Load (0.014428)   select * from (select raw_sql_.*, rownum raw_rnum_ from (SELECT * FROM r_well_status WHERE (r_well_status.status = '00030000') ) raw_sql_ where rownum < = 1) where raw_rnum_ > 0
ProductionEntityWell Columns (0.007681)
select column_name, data_type, data_default, nullable,
decode(data_type, 'NUMBER', data_precision,
'VARCHAR2', data_length,
null) as length,
decode(data_type, 'NUMBER', data_scale, null) as scale
from user_catalog cat, user_synonyms syn, all_tab_columns col
where cat.table_name = 'PDEN_WELL'
and syn.synonym_name (+)= cat.table_name
and col.table_name = nvl(syn.table_name, cat.table_name)
and col.owner = nvl(syn.table_owner, user)
ProductionEntityWell Load (0.009062)   select * from (select raw_sql_.*, rownum raw_rnum_ from (SELECT * FROM pden_well WHERE (pden_well.UWI = '0555051107022') ) raw_sql_ where rownum < = 1) where raw_rnum_ > 0
RWellStatus Load (0.015663)   select * from (select raw_sql_.*, rownum raw_rnum_ from (SELECT * FROM r_well_status WHERE (r_well_status.status = '02010000') ) raw_sql_ where rownum < = 1) where raw_rnum_ > 0
ProductionEntityWell Load (0.009083)   select * from (select raw_sql_.*, rownum raw_rnum_ from (SELECT * FROM pden_well WHERE (pden_well.UWI = '0555051107023') ) raw_sql_ where rownum < = 1) where raw_rnum_ > 0
ProductionEntityWell Load (0.008181)   select * from (select raw_sql_.*, rownum raw_rnum_ from (SELECT * FROM pden_well WHERE (pden_well.UWI = '0555051111020') ) raw_sql_ where rownum < = 1) where raw_rnum_ > 0
RWellStatus Load (0.014005)   select * from (select raw_sql_.*, rownum raw_rnum_ from (SELECT * FROM r_well_status WHERE (r_well_status.status = '02100000') ) raw_sql_ where rownum < = 1) where raw_rnum_ > 0
ProductionEntityWell Load (0.010287)   select * from (select raw_sql_.*, rownum raw_rnum_ from (SELECT * FROM pden_well WHERE (pden_well.UWI = '0555051111022') ) raw_sql_ where rownum < = 1) where raw_rnum_ > 0
RWellStatus Load (0.008513)   select * from (select raw_sql_.*, rownum raw_rnum_ from (SELECT * FROM r_well_status WHERE (r_well_status.status = '00070000') ) raw_sql_ where rownum < = 1) where raw_rnum_ > 0
ProductionEntityWell Load (0.010116)   select * from (select raw_sql_.*, rownum raw_rnum_ from (SELECT * FROM pden_well WHERE (pden_well.UWI = '0555051112000') ) raw_sql_ where rownum < = 1) where raw_rnum_ > 0
ProductionEntityWell Load (0.014742)   select * from (select raw_sql_.*, rownum raw_rnum_ from (SELECT * FROM pden_well WHERE (pden_well.UWI = '0555051112002') ) raw_sql_ where rownum < = 1) where raw_rnum_ > 0
RWellStatus Load (0.014744)   select * from (select raw_sql_.*, rownum raw_rnum_ from (SELECT * FROM r_well_status WHERE (r_well_status.status = '06010300') ) raw_sql_ where rownum < = 1) where raw_rnum_ > 0
ProductionEntityWell Load (0.023254)   select * from (select raw_sql_.*, rownum raw_rnum_ from (SELECT * FROM pden_well WHERE (pden_well.UWI = '0555051606000') ) raw_sql_ where rownum < = 1) where raw_rnum_ > 0
RWellStatus Load (0.008389)   select * from (select raw_sql_.*, rownum raw_rnum_ from (SELECT * FROM r_well_status WHERE (r_well_status.status = '01110000') ) raw_sql_ where rownum < = 1) where raw_rnum_ > 0
ProductionEntityWell Load (0.024230)   select * from (select raw_sql_.*, rownum raw_rnum_ from (SELECT * FROM pden_well WHERE (pden_well.UWI = '0555051607000') ) raw_sql_ where rownum < = 1) where raw_rnum_ > 0
ProductionEntityWell Load (0.008161)   select * from (select raw_sql_.*, rownum raw_rnum_ from (SELECT * FROM pden_well WHERE (pden_well.UWI = '0555051608000') ) raw_sql_ where rownum < = 1) where raw_rnum_ > 0
ProductionEntityWell Load (0.011345)   select * from (select raw_sql_.*, rownum raw_rnum_ from (SELECT * FROM pden_well WHERE (pden_well.UWI = '0555051609000') ) raw_sql_ where rownum < = 1) where raw_rnum_ > 0
Rendered well_list/_list_table (16.23639)
Rendered shared/_header (0.00074)
Rendered shared/_navbar (0.00173)
Rendered shared/_footer (0.00083)
Completed in 21.23575 (0 reqs/sec) | Rendering: 16.32746 (76%) | DB: 0.02618 (0%) | 200 OK [http://localhost/well_list/list]

0 comments | Filed Under: | Tags:

Found an excellent Abstract Factory pattern example

Posted by admin, Tue Jan 31 09:16:25 UTC 2006

I was hunting for a decent example of the Abstract Factory Pattern for ruby, and eventually stumbled across this gem:

Modular Architectures with Ruby

Summary Any reasonably complex end-user application is going to require some sort of customization and enhancement for effective deployment. This article shows one way to create a modular architecture as a way of leaving the door open for advanced users or consultants who want to extend the functionality without modifying the source.

Now I just wish everyone who was writing about patterns in Ruby could do as excellent a job as Jack has done here.

0 comments | Filed Under: | Tags:

Oops. Good thing I only had one user.

Posted by admin, Fri Jan 27 11:33:05 UTC 2006

Dump or Slurp YAML Reference Data (and Fixtures) | Ruby on Rails for Newbies

Sometimes you need to save data and use it again when you deploy a server or continue a project on a different machine.I wrote a plugin for ActiveRecord that lets you do this easily.
I really liked the idea of this plugin, but it could be a little more robust.

Just make sure that the first thing you try is “User.dump_to_file”. I used the “User.to_fixture” first, then I tried the “User.load_from_file”. And I got a nice users fixture file (which wiped out my existing fixture file without asking), and then…

$ script/runner "User.load_from_file"/usr/local/lib/ruby/gems/1.8/gems/rails-1.0.0/lib/commands/runner.rb:27: ./script/../config/../vendor/plugins/ar_fixtures/lib/ar_fixtures.rb:12:in `initialize': No such file or directory - /Users/lori/rails/test/db/users.yml (Errno::ENOENT) from ./script/../config/../vendor/plugins/ar_fixtures/lib/ar_fixtures.rb:12:in `load_from_file' from (eval):1 from /usr/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:21:in `eval' from /usr/local/lib/ruby/gems/1.8/gems/rails-1.0.0/lib/commands/runner.rb:27 from /usr/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:21:in `require' from /usr/local/lib/ruby/gems/1.8/gems/activesupport-1.2.5/lib/active_support/dependencies.rb:214:in `require' from script/runner:3 Lo and behold, it wiped out my USERS table. Oops.

0 comments | Filed Under: | Tags: