Need some tips for applying patches

I am working with a legacy database that does not always follow the
conventions for table names, primary key and foreign key column names,
and join table names.

This is no problem in my application code because Rails allows me to
override the defaults. However it is making unit testing next to
impossible because fixtures will still try and insert data into the
wrong tables.

Changing the database schema is not an option at this point as the
database is already deployed to a production environment and has been
for some time.

The problem and solution are described here:
http://dev.rubyonrails.org/ticket/1911

I eagerly downloaded the patches and tried to apply them (I list the
steps below). The patches failed, and unit tests that worked previously
(the ones involving tables that followed the naming convention) failed.
So in other words, broken rails. I went back to a clean trunk and those
tests passed again.

Everything I did was sort of haphazard and based on guesswork. It
doesn’t seem like there is any definitive source for information on the
patching process. Here are my general questions:

The URL above lists a number of patches. Do I need to install them
cumulatively starting from the earliest one, or can I just install the
most recent one?
I tried both and both failed and left rails in a broken state until I
started again with a clean trunk.

What is the process for incorporating these patches into release and
development versions of Rails? Is there one? I checked out the latest
stable branch and the fix was not there.

So that brings up the next question, is there a particular version of
rails that I need to run these patches against? If that version is older
than what I already have, won’t I be losing newer functionality and
fixes?

How do I deal with patches that fail? What do I do with reject files?

Once I have successfully applied a patch to a checked-out Rails trunk,
assuming I can do so, how do I make that my new system-wide Rails,
replacing the one under /usr/local/lib/ruby/…?

Sorry for the annoying questions that are probably second nature to all
you patchers out there but completely opaque to me.

For the record, here is what I tried and failed to do.
This is based on the following article:
http://sean.treadway.info/articles/2005/06/23/patch-your-rails-trunk

mkdir rails_tmp
cd rails_tmp
svn co http://dev.rubyonrails.org/svn/rails/branches/stable
cd stable/activerecord
curl
http://dev.rubyonrails.org/attachment/ticket/1911/more_flexible_fixture_architecture.patch?format=raw
| patch -p0

Here is the output of the last command:

% Total % Received % Xferd Average Speed Time Time Time
Current
Dload Upload Total Spent Left
Speed
100 21717 100 21717 0 0 27745 0 --:–:-- --:–:-- --:–:–
99912
patching file test/fixtures_test.rb
Hunk #1 succeeded at 108 (offset 40 lines).
Hunk #2 succeeded at 107 with fuzz 2.
Hunk #3 FAILED at 218.
1 out of 3 hunks FAILED – saving rejects to file
test/fixtures_test.rb.rej
patching file test/fixtures/topics2.yml
patching file lib/active_record/fixtures.rb
Hunk #1 succeeded at 9 with fuzz 2 (offset 7 lines).
Hunk #2 FAILED at 240.
Hunk #3 FAILED at 477.
Hunk #4 succeeded at 612 (offset 11 lines).
Hunk #5 succeeded at 625 (offset 7 lines).
2 out of 5 hunks FAILED – saving rejects to file
lib/active_record/fixtures.rb.rej

Hope someone can help me make sense of this. If I can’t get this to
work, I am facing one of two equally dismal prospects: 1) developing my
rails app without unit testing (I don’t really consider this an option)
and 2) going back to java, struts, hibernate, spring, and all
that…

Thanks
DT

Hi !

2005/12/16, Dan T. [email protected]:

Hunk #1 succeeded at 108 (offset 40 lines).
Hunk #2 succeeded at 107 with fuzz 2.
Hunk #3 FAILED at 218.
1 out of 3 hunks FAILED – saving rejects to file
test/fixtures_test.rb.rej

You have failed hunks, so of course the patch becomes invalid. I
haven’t looked at the patches themselves, but Duane’s comments seem to
imply that 3b is the latest patch to use:
http://dev.rubyonrails.org/attachment/ticket/1911/more_flexible_fixture_architecture-3b.patch

The best way to apply this patch, since it fails on HEAD, would be to
update your working copy to a version from around that time, patch
against it, and then update to HEAD. Maybe that’ll get you going.

If update generates conflicts, then the best way for you to get that
patch applied would be to update it so that it applies cleanly, and
then ask on rails-core about a review.

The sequence of commands should look something like this:

svn update --revision “{2005-10-11}”
patch -p0 | curl …
svn update
svn status

Hope that helps !

On Dec 17, 2005, at 3:06 PM, Dan T. wrote:

against it, and then update to HEAD. Maybe that’ll get you going.
And, will I have to do this every time I want to upgrade rails? In
other
words, will this patch ever be incorporated into the stable trunk and
eventually a release version of rails?

Hi Dan,

I’m the author of ticket #1911. I talked with Jeremy K. back at
RubyConf about applying the patch to the trunk, but at the time he
was working on a similar patch that would have encorporated much of
the same functionality. He wanted to combine his work with mine, but
then later gave up the effort because he didn’t want to postpone the
1.0 release. I’m not sure where things stand now that 1.0 is out.

With regard to your more immediate questions, in order to make your
application work on a patched version of rails, all you have to do is
put the patched version of everything in RAILS_ROOT/vendor/rails.
When your application boots up, it’ll go looking for rails first in
that directory and revert to gem rails upon failure.

You can test it on a development version just as easily. Webrick (or
lighttpd/apache in dev mode) will also prefer vendor/rails over the
gems. Usually, to get it set up right, I just do an “svn co http://
dev.rubyonrails.org/svn/rails/branches/stable .” while inside vendor/
rails. It sounds like you’ll want to use a -R switch, however, to
get a previous revision (instead of the HEAD). E.g. “svn co -R
[revision #] [url same as above]”

To answer your last question, you won’t have to do this each time you
upgrade, since you can easily do an “svn update” command inside the
rails directory to grab the latest code from the subversion
repository. However, there is one caveat: if any changes are made to
the fixture code that conflict with my patch, you’ll have problems.
I doubt that will happen, however, if you’re connected to the stable
branch (basically, version 1.0 of rails, plus any minor bug fixes
that they may have to add in the near future).

Duane J.
(canadaduane)
http://blog.inquirylabs.com/

Francois B. wrote:

You have failed hunks, so of course the patch becomes invalid. I
haven’t looked at the patches themselves, but Duane’s comments seem to
imply that 3b is the latest patch to use:
http://dev.rubyonrails.org/attachment/ticket/1911/more_flexible_fixture_architecture-3b.patch

The best way to apply this patch, since it fails on HEAD, would be to
update your working copy to a version from around that time, patch
against it, and then update to HEAD. Maybe that’ll get you going.

That worked. The patch succeeded. Thank you very much.

Now for more dumb questions:

What do I now do with the patched trunk to make it my working copy of
rails?

Also how do I test it out before I do so?

And, will I have to do this every time I want to upgrade rails? In other
words, will this patch ever be incorporated into the stable trunk and
eventually a release version of rails?

Thank you.
D

Duane J. wrote:

Hi Dan,

[…]

With regard to your more immediate questions, in order to make your
application work on a patched version of rails, all you have to do is
put the patched version of everything in RAILS_ROOT/vendor/rails.
When your application boots up, it’ll go looking for rails first in
that directory and revert to gem rails upon failure.

Thanks, this is very helpful. But I’m not sure where my RAILS_ROOT
directory is.
Ruby is installed in /usr/local/lib/ruby. I tried putting the patched
stuff in /usr/local/lib/ruby/vendor/rails and then modified one of my
tests to use the new “fixture” method. The test failed saying that the
method could not be found. So I guess that was the wrong place.

I also tried
/usr/local/lib/ruby/gems/1.8/gems/rails-1.0.0/vendor/rails
and that didn’t work either. Where is the correct place?

Thanks very much.
D

Dan T. wrote:

Thanks, this is very helpful. But I’m not sure where my RAILS_ROOT
directory is.

I’d still like to know the answer to this, but in the meantime I solved
the problem with microsurgery–backing up the gems/…/activerecord
directory and then replacing the files that were altered by the patch.
It works–I can now call the fixture method and specify an alternate
table name. However (we are OT now), the file_name parameter seems to be
ignored. If the fixture name does not match an existing YAML file, it
reports an error. Conversely, you can define file_name to be a
nonexistent file and no error happens.
Example:
(topics2.yml exists, foo.yml does not)
fixture :topics2, :table_name => “topics”, :file_name => “foo” # this
works
fixture :foo, :table_name => “topics”, :file_name => “topics2” # this
fails

I can probably live with this, since my main issue was table names, and
I can still control the name of fixture files using the symbol passed to
fixture. But it’s annoying. Does it work for you? If so, maybe my
problem is a result of the way I set things up.

Thanks to all of you for putting up with my obscure newbie questions.
D

David R. wrote:

Hi, Dan. In this case, the RAILS_ROOT isn’t related to the ‘rails’
executable – it refers to the top level directory of the application
you’re trying to run on a specific version of Rails. It’s the same
directory that contains app, log, script, etc.

Thanks. That worked. Of course I am still having the problem described a
couple posts earlier in which the patched code isn’t working as
expected, but perhaps that’s a topic for another thread.
Thanks again.

Hi, Dan. In this case, the RAILS_ROOT isn’t related to the ‘rails’
executable – it refers to the top level directory of the application
you’re trying to run on a specific version of Rails. It’s the same
directory that contains app, log, script, etc. At that same level
should be a directory called ‘vendor’; checkout the Rails version you
want into that directory according to Duane’s instructions and you
should be good to go.

If this seems like a bit of a chicken-and-egg problem, that’s only
because it kind of is. :slight_smile:

Hope this helps,
David

Dan,

I took a look at the code in activerecord/lib/active_record/
fixtures.rb and didn’t see any reference to a file_name attribute.
The closest thing I could find is fixture_path, but I think that just
lets you specify a directory where you’ve stored your fixtures. I
think it still expects the files on that path to be named after your
table/models.

You can take a look at Peak Obsession
Fixtures.html for the RDoc documentation, but you may need to dig
into the code to prove (or disprove) this for yourself.

David

Duane J. wrote:

Dan, to answer your question–don’t use the ‘file_name’ option as it
is deprecated.

Thanks for the answer. I was confused because the example code on the
patch page still uses it. Thanks for the updated info.

On Dec 19, 2005, at 2:41 PM, David R. wrote:

Fixtures.html for the RDoc documentation, but you may need to dig
into the code to prove (or disprove) this for yourself.

David

He’s referring to the modifications applied by the patch from ticket
#1911.

Dan said:

this
fails

Dan, to answer your question–don’t use the ‘file_name’ option as it
is deprecated. An earlier version of the patch did not make a useful
assumption: that the file name is almost always the same as the
fixture name. In the patch you’ve applied, the file name is actually
the same as your fixture. For example:

To use foo.yml:

fixture :foo, :table_name => “topics”

To use other.yml:

fixture :other, :table_name => “topics”

If you have a rare situation where the table name and fixture name
doesn’t match, then you can do something like this:

Using foo.yml, but referring to it as bar in our test code:

fixture :foo, :table_name => “topics”, :group_name => “bar”

Now, bar[:my_fixture_name] will be used in your test code instead of
foo[:my_fixture_name].

Hope that helps,
Duane J.
(canadaduane)
http://blog.inquirylabs.com/