By Developers, For Developers

Historical errata for Advanced Rails Recipes

PDF PgPaper PgTypeDescriptionFixed onComments
54TYPO

In the second sentence of the paragraph just after the class Student code listing:

" but as advanced programmer we know better" should be " but as advanced programmers, we know better"

2007-12-10
55TYPO

After the validates_ssn line at the top of the page:

“OK, so how we get there?” should be “OK, so how do we get there?”

2007-12-10
61TYPO

In the bio for Jay Fields:

“He am also very interested in maturing software design through software testing”

Change “am” to “is” and put a period at the end of the sentence.

2007-12-10
22TYPO

“So rather than polluting the EventsController, let’s just make resources a nested-resource of events…”

Should read:

“So rather than polluting the EventsController, let’s just make registrations a nested-resource of events…”

2007-12-10
9TYPO

In the first paragraph in section 1.2, third sentence, a word is missing. You have, “And they seem to a great deal of satisfaction …”. You probably wanted to say something like, “And they seem to derive a great deal of satisfaction …”.

2007-12-10
61TYPO

In the Problem paragraph, last sentence, you have the word “breath” when I think you want the word ’breathe".

2007-12-10
65TYPO

In the Discussion paragraph, you should use the plural of model so it reads, “… back into one of the models, …”.

2007-12-10
47TYPO

“Then we run the same query, but this time telling find_by_solr that we’re interesting in how many results are in the publisher facet…”

should read:

“Then we run the same query, but this time telling find_by_solr that we’re interested in how many results are in the publisher facet…”

2007-12-10
61TYPO

Last sentence in the summary of Jay Fields starts, “He am also..”, which is not correct English. That sentence also has no final punctuation.

2007-12-10
38TYPO

Toward the bottom of the page, about 6 lines up, you have, “<%= meta ”description“, meta_keywords “, when I think you wanted, ”<= meta ”keywords“, meta_keywords %>”.

2007-12-10
8088TYPO

“…that are gonna to hit an external…”
should be
“…that are going to hit an external…”

2007-12-10
21TYPO

Indeed, that URL is a resource is its own right
should probably be
Indeed, that URL is a resource in its own right

2007-12-10
119TYPO

“different” for “differently”, last non-code sentence on the page

2007-12-17
144TYPO

“Now all that’s left is building the application…” should be “Now all that’s left is buildin’ the application…”

2007-12-10
148OK

This example is not working for me. I’m running Rails 1.2.6. I can’t tell if the example above is buggy or not. See also dev.rubyonrails.org/ticket/8665

(Dave says: the book requires Rails 2.0)

2008-02-25
148OK

On Rails 1.2.6 I found that clean_logger.rb redefines format_message. As a result, format_message no longer pays attention to RecipesLogFormatter#call. I commented out a large chunk of clean_logger.rb and the logger formatting works like I expect now.

(David: This recipe is very specific to Rails 2.0.)

2008-02-25
92TYPO

Bottom paragraph:

“We’ll need a couple of tests thatrequire an event arranged a certain way.”

Need a space in “thatrequire”.

2007-12-13
21OK

The fragment “… Indeed, that URL is a resource is its own right: it uniquely identifies a collection of events” probably should read “… Indeed, that URL is a resource in its own …”

2007-12-17
109OK

Ryan Carver suggested this to me earlier this year: Once you have a constant list of things, you can use it in dropdowns as the recipe shows, but you can also use it in validations to ensure that only items from your list make it into the database.

After NAMES_ABBREVIATIONS is defined, I use something like this:

validates_inclusion_of :state_abbreviation, :in => NAMES_ABBREVIATIONS

Now your constant list is DRY, your view is DRY, and your validation is DRY.

2008-03-01
103TYPO

“The platform you’re deploy to acts as a kind”
should be
“The platform you’re deploying to acts as a kind”

2007-12-13
105TYPO

“www.example.com/8868”
should be
“www.example.com:8868”

2007-12-13
27TYPO

In the ‘Discussion’ section, first sentence, ‘… often not worth carry around the extra baggage…’, ‘carry’ should be ‘carrying’

2007-12-17
18TYPO

Last sentence on the page is missing a period: “…XML for mat conven-
tions of Rails”

2007-12-17
29TYPO

Some of the indenting shown in the console example is incorrect. i.e. “=> #<Mp3 id: 1, …> ” should not be indented, and neither should the following lines.

2007-12-17
61OK

In the bio for Jay Fields it says “He am” rather than “He is”.

2007-12-17
17SUGGEST

In the first full paragraph, the one starting with “That gives us some XML back.”:

I think the third sentence would read better without the “and”. That is:

To do that, it needs to send a hunk of XML to the
appropriate resource URL using the
corresponding HTTP verb.

Instead of:

To do that, it needs to send a hunk of XML to the
appropriate resource URL and using the
corresponding HTTP verb.

2007-12-17
22TYPO

“So rather than polluting the EventsController, let’s just make resources a
nested-resource of events by revising our routes.rb file: ”

I’m guessing you want to make registrations a nested-resource of events :-)

2007-12-17
61OK

In the last sentence under “Problem”, change “breath” to “breathe”.

2007-12-27
145TYPO

“You’ve no doubt has this…”
should be
“You’ve no doubt had this…”
or
“You’ve no doubt made this…”

2007-12-26
15TYPO

“And inside of our application we can use the events_url helper to generate
a URL for listing the event” should be something like, “And inside of our application we can use the events_url helper to generate
a URL for listing the events” or “…for the index action”.

2007-12-27
16SUGGEST

In the middle of the page, the paragraph, “And if we need to redirect to or link to an event, we just need the resource:
redirect_to(event) link_to(event.name, @event)”
was confusing to me—I didn’t see how it followed the previous paragraph or how it related to the discussion of HTTP verbs and browsers. Maybe a bit more context?

2007-12-27
16TYPO

I think, “Now let’s say we’d like to introduce this application to another, and have them speak XML” would read better as, “Now let’s say we’d like to introduce this application to another application, and have them speak XML to each other.”

2007-12-27
27TYPO

In the ‘Discussion’ section, second sentence, ‘Most important, by writing your own…’ should be, ‘Most importantly, by writing your own…’, I think.

2007-12-27
62OK

“He am also” should read “He is also” in the intro paragraph…

2007-12-31
15OK

Second line of the following command

script/generate scaffold event name:string description:text
price:decimal starts_at:datetime

is in blue rather than red

Mike says: This will be fixed during layout. It’s an artifact of the beta.

2008-02-25
276ERROR

MutliGeocoder class isn’t qualified, won’t work as shown.

Change:
>> here = MultiGeocoder.geocode(“9637 East County Line Road, Englewood, CO”)
>> there = MultiGeocoder.geocode(“9447 Park Meadows Dr, Lone Tree, CO”)

to

>> here = GeoKit::Geocoders::MultiGeocoder.geocode(“9637 East County Line Road, Englewood, CO”)
>> there = GeoKit::Geocoders::MultiGeocoder.geocode(“9447 Park Meadows Dr, Lone Tree, CO”)

2008-02-20
19SUGGEST

Vocab quibble (hi, Mike!): in “Here’s the output, which can be quite handy for debugging an onerous client:”, I would suggest replacing “onerous” with “ornery”. “Onerous” is usually associated with some sort of duty, and has a connotation of “wearisome”, or “burdensome”.

2008-02-20
18SUGGEST

event.rb seems to assume that we have frozen the rails gems to vendor/rails, which is not mentioned in the setup instructions. Is this assumed to be standard practice now? Also, event.rb assumes it lives in some directory one level below RAILS_ROOT (scripts, perhaps?), but that’s not mentioned either.

2008-02-25
14TYPO

Under Problem for RESTful routes, 2nd paragraph, 2nd line “you’d like create” should be “you’d like to create”

2008-02-20
140SUGGEST

It’s worth noting in the discussion that packet (and hence BackgrounDRb) is dependent on fork() and thus cannot be used on Windows platforms.

2008-02-21
68SUGGEST

Since Ryan is describing the entire solution that includes the RJS that adds and removes task elements in one fell swoop, there’s no need for the Project#new method to build three Tasks. (This was done in the Railscast because Ryan progressively improved the solution, starting with a static list of Tasks.)

2008-02-28
99SUGGEST

While I’ve found this chapter very useful (thanks) I think it would also be extremely helpful to include a section on updating an album cover (unlikely I know, but …).

How would you implement the update method to take into account a new album cover being chosen? What deletion routines/strategies (for the old/unwanted cover) would be involved & what issues might arise (concurrency, a call to that image at the same time it is deleted, etc).

2008-03-03
278OK

The recipe on rails logs file was interesting. What I’d like to see too is something on reading/manipulating web server files. For example, an addition to your recipe on allowing users their own domain - I’d like to be able to report on click through from the main to subdomain, & then on any refer from that subdomain to another site. The have a routine that packaged that up into a csv or graphical report.

Such a chapter might also address the strategies/choices involved - is it better to write to the database each time a sub/domain is accessed or use the web server log files?
Thanks.

2008-03-01
22ERROR

<%= button_to “Register” , event_registrations_path(:event_id => event) %>

It seems that this generates a link to the index method instead of the create method in RegistrationsController.

2008-02-28
24OK

<% form_tag session_path do -%>

should be

<% form_tag sessions_path do -%>

“new.html.erb” should be corrected, too.

Mike says:
Actually, it’s a singular resource (map.resource :session), so in the form tag you use the singular form.

2008-02-25
129ERROR

With Rails 2.02, the Pdf.find_for_pdf_generation call displayed endless Mysql errors: Mysql::Error: Lost connection until I added ActiveRecord::Base.allow_concurrency = true to the environment file

2008-03-01
70SUGGEST

It would be even more clear to show what the params hash looks like for existing tasks. At least, that’s what I think. :-)

2008-02-28
235TYPO

“our Rails app’s public directly” seems like it should say “our Rails app’s public directory”.

2008-02-20
34TYPO

Before rending an appropriate 404 response back to the
client, the FourOhFour….

rending should be rendering

2008-02-20
34ERROR

You are calling find_or_create_by and then save, thus creating an insert and an update SQL command if it is a new 404’ed route. find_or_initialize_by should be used instead.

2008-02-21
40TYPO

When describing how to install the acts_as_ferret plugin it says “script/plugin install script/plugin install ← svn://projects.jkraemer.net/acts_as_ferret/tags/stable”

“script/plugin install” is typed twice.

2008-02-20
131ERROR

The order of the operations in the capistrano task seems reversed. Currently the daemon is briefly started, and then stopped. I assume the line should have been:
after(:deploy) { stop_pdf_generator; start_pdf_generator }

2008-02-25
249TYPO

Last paragraph.

“Notice that we can chains tasks together:”

chains should be “chain”

2008-02-20
70ERROR

I’ve adapted the task example to add a date for the task to be completed by. My model has_one :image, so is using a multipart form.
Adding a date for the task seems to break the example completely . The server returns a 500 with the following error msg => Status: 500 Internal Server Error
Conflicting types for parameter containers. Expected an instance of Hash but found an instance of Array. This can be caused by colliding Array and Hash parameters like qs[]=value&qs[key]=value.

This error is caused on the create method. If I remove the date fields from the form, I can create a new task.

If I then replace the date fields (<%= task_form.date_select :task_date %>) in the view, I can update the original task with a date, but not add a new task with a date.

Any suggestions as to why this is failing for create but not update?

This can be fixed by manually specifying the :index option and setting it to an empty string if the task is new:

<%= task_form.date_select :completed_at, :index => (task.new_record? ? ’’ : nil) %>

2008-02-28
71SUGGEST

There is a user experience issue with this recipe, in that you have to delete blank Tasks, or they cause validation errors. Since the form starts with three tasks, if you only add one task to project, and leave the other two blank, you’ll get validation errors for the two blank tasks.

I think it would be better if the new_task_attributes=() method were to check incoming attribute sets, and if they are all blank, skip that set.

2008-02-28
72ERROR

I believe that this recipe makes it impossible to delete the last task from a project.

That is, if you create a project with three tasks, that works. Then you edit the project, and remove two of the tasks, that works too. But if you edit it again and try to remove the final task, that will not work. And if you have a project with three tasks (or five, 99, etc.), and delete all of them, none of the tasks will be removed.

The reason is that if there are no tasks on the form, if all have been removed, then the existing_task_attributes=() won’t fire, because there’s nothing in the form for existing_task_attributes[] to be assigned, which is what calls the method where the deletes are handled.

2008-02-28
70ERROR

Like Eddie, I am also getting a 500 Server Error on creates as soon as I add a date field to the task model/database/form, with the same Conflicting types error message:

Conflicting types for parameter containers. Expected an instance of Hash but found an instance of Array. …

This can be fixed by manually specifying the :index option and setting it to an empty string if the task is new:

<%= task_form.date_select :completed_at, :index => (task.new_record? ? ’’ : nil) %>

2008-02-28
13TYPO

“…for example, find the Mail tab at the edge of this page…” The tab is actually titled “E-mail”.

2008-02-20
97TYPO

Last paragraph, first sentence: “After configuring how the image gets processes” should be “…image gets processed”.

2008-02-20
93SUGGEST

The code for the update method in errata_controller.rb could stand a bit more explanation. The text describing the required change to the update method says to “add a new format.js block to respond_to to let the JavaScript request know that the update was successful.”

Looking at the respond_to section all we see is:

format.js { head :ok }

To a reader not as familiar with HTTP requests as DHH it would be helpful to explain why “head :ok” does the trick here.

Also, if the @erratum.update_attributes call fails, the newly added response is “head :unprocessable_entity”. This bears at least some explanation as well.

More explaining, less hand waving, please!

2008-03-01
133TYPO

second sentence of solution section. “Customers buy stuff throughout the day, and shop owners needs” should be “Customers buy stuff throughout the day, and shop owners need”. no “s” on “need”.

2008-02-20
117OK

For the field error highlighting to work with the ErrorHandlingFormBuilder, you have to create forms using an object rather than a string or symbol, i.e. form_for :person or form_for ‘person’ won’t work, even though you can normally create forms that way (I think there’s some instance_variable_get magic inside the form_for helper). Could the ErrorHandlingFormBuilder be improved slightly to cope with this?

Mike says:
It’s possible using instance_variable_get, but very ugly. Resource-based forms now use the @person convention (again), so I think it’s best to leave the recipe as-is.

2008-02-25
115SUGGEST

In recipe 22 the class ErrorHandlingFormBuilder handles the fields supported by ActionView::Helpers::FormBuilder but not the fields handled by ActionView::Helpers::FormOptionsHelper::FormBuilder. It would be nice if the recipe could be extended to support the options field.

2008-02-25
67SUGGEST

Recipe 14 for handling multiple objects in forms is excellent but there is an issue with it if the partial for the individual objects contains a check box. This will generate a hidden input tag that ends up in an attribute set of it on and will then cause problems when parsed by the new_attributes= virtual accessor.

I think its a Rails issue as much as anything but would be useful to have some advice on how to deal with this.

2008-02-28
99SUGGEST

in save_with_cover you may want to rescue ActiveRecord::RecordInvalid specifically otherwise it will mask unexpected exceptions that the programmer probably should know about.

2008-03-01
96SUGGEST

About “Here’s the migration for the Cover model:”. It would be handy to list the whole migration code file or maybe add a download link?

Cheers.

2008-02-21
90SUGGEST

Since RESTful routes are relatively new in Rails, the Wizard example could stand to be a bit more explicit about when things are done “auto-magically” thanks to a “map.resources” statement in config/routes.rb.

In the Wizard example the edit.html.erb code on p. 89 uses a simple form_for(@quiz) tag, and the text on p. 90 says that hitting either ‘Next’ or ‘Previous’ will call the update action.

From the code in edit.html.erb it’s obvious why ‘Previous’ calls :update but not so obvious why ‘Next’ does. It’s taken care of by the map.resources call so that an existing record will be posted to the :update action.

Pointing out this small yet important detail would be REALLY handy, especially for folks who are new to RESTful routes (and it would have saved me a few hours of trying to figure it out!).

2008-03-01
94SUGGEST

I think you need to stress the need for prior installation of the appropriate image manipulation software that RMagick et al wraps. I followed this tutorial having installed the MiniMagick gem, then spent quite a length of time until it occurred to me that I also had to install ImageMagick (perhaps this is commonly installed on other platforms, but it’s not on Windows).

2008-03-01
88TYPO

The script/console line to create a true/false question shown here:

>> TrueFalseQuestion.create(:text => “Do you like wasabi?”,
:tag => “q20”).

Should not end with a “.” since it causes IRB to continue onto the next line.

2008-02-21
72SUGGEST

Re: Recipe 14
When you do submit blank task fields in your project form, and the validation errors show up, there’s always one more than the number of blank tasks. It’s easy enough to modify the recipe so that it doesn’t spit out ANY blank task forms to start with, but that doesn’t prevent someone from submitting an empty one.

Would love to see this recipe refined a little bit more—even if it’s only in the discussion forum…..

2008-02-28
20OK

sort_by = (params[:order] == should be sort_by = (params[:order] = (assignment)

2008-02-25
20OK

oops disregard the =/== error it is correct the way it is

2008-02-25
20OK

I think asc makes more sense than desc for an events list.

2008-02-25
116SUGGEST

@template.content_tag(:p, label(field) + super(field, options))

The call to the super method will only work for the methods in ActionView::Helpers::FormBuilder with that signature (2 args). This means as soon as you try and use it with one of the other fields that has a different method signature like, “select”, “radio_button”, “country_select” etc it will break.

A more robust example would be very useful.

2008-03-03
234TYPO

“Behaviour” the British spelling of “Behavior”. Is David British? :) In any case, I think the book should use American English. It also helps searching the book — who wants to search for “behaviour” and “behavior” both to find BDD?

2008-02-28
15TYPO

2nd para in solution: “…generates a bunch of code: a controller with no less than seven actions…”. Should be: “…generates a bunch of code: a controller with no fewer than seven actions…”. (Sorry—I should have been a grammar teacher, I guess.)

2008-02-28
17TYPO

Second-to-last paragraph: “The action that sets up a collection of events, and how they’re rendered (the format) depends on what the client asks for.” This sounds awkward.
I think a better sentence is: “The action sets up a collection of events, and how they’re rendered (the format) depends on what the client asks for.”

2008-02-28
19TYPO

Last paragraph: “…not necessarily Rails specific.” -> “…not necessarily Rails-specific.”

2008-02-28
355SUGGEST

Some problems with the user domain/subdomain recipe. See my reply in the forum.

2008-02-29
1SUGGEST

I think the book is a bit weak in security recipes. Not that the two security recipes that are included are bad, just that I do find the book lacking in this areas. There are many more security recipes out there that warrant attention.

2008-02-29
22SUGGEST

I’ve read elsewhere that the responses from actions with params are not easily cachable. Therefore, if caching is important then, the collections are preferable.
If you can confirm this, then I think this is worth mentioning in your discussion of ‘adding your own restful actions’

2008-03-01
208TYPO

In receipie 38:

“We’ll stick with the default host and post (configurable via options to the starling command)”

I believe that post should be port.

2008-03-03
75SUGGEST

Please upgrade to the newest version of Sphinx and the Ultrasphinx plugin. I know the current version of the plugin is not compatible with the Sphinx search version(985) listed in the book. Also, the hpricot plugin is optional for the search to work, and only used by the recipe itself.

2008-03-04
132SUGGEST

Really, the current recipe for uploading an album cover (or any other photo) is only half-baked. You really need to provide the update technique as well. Yes, it’s complicated, but that’s exactly why this recipe leaves us hanging right now…

Mike says: This recipe has been expanded to handle updating, as well.

2008-03-04
137SUGGEST

Is it worth adding a further ‘Event.addBehaviour’ chunk of code that adds the parameter to PeoplePreview so that the changes happen one at a time.

Currently after you’ve added the ‘cleaned up’ version of PeoplePreview the code won’t work because you haven’t altered the addBehaviour call so that it passes the required parameter.

You do change it eventually (on p139) but only after you’ve gone through the delete person functionality. I think that is a bit confusing since you are making two changes at the same time.

Hope that is useful.

2008-03-07
248ERROR

Hello,
I just left this on the forum for the book before I realized it should perhaps go here. Sorry for the duplicate and please delete the one that is not appropriate.

I just tried the Shoulda Recipe (51) with Rails 2.0.2 and Postgres (8.1 on windows, 8.2 on Ubuntu) and I’m getting an error when I run the test.
I’m using a new rails application and the dev and test databases both work (I did a migration and ran rake db:test:prepare to make sure).
I’ve tried this with both the version of shoulda in the recipe and the current version. And the only file I’ve created is the perscribed test/unit/event_test.rb

Any ideas?

C:\\RailsDev\\shoulda_test>rake test
(in C:/RailsDev/shoulda_test)
C:/ruby/bin/ruby -Ilib;test “C:/ruby/lib/ruby/gems/1.8/gems/rake-0.8.1/lib/rake/
rake_test_loader.rb” “test/unit/event_test.rb”
./test/unit/event_test.rb:1: uninitialized constant Test (NameError) from C:/ruby/lib/ruby/gems/1.8/gems/rake-0.8.1/lib/rake/rake_test_loader.rb:5:in `load’ from C:/ruby/lib/ruby/gems/1.8/gems/rake-0.8.1/lib/rake/rake_test_loader.rb:5 from C:/ruby/lib/ruby/gems/1.8/gems/rake-0.8.1/lib/rake/rake_test_loader.rb:5:in `each’ from C:/ruby/lib/ruby/gems/1.8/gems/rake-0.8.1/lib/rake/rake_test_loader.rb:5
C:/ruby/bin/ruby -Ilib;test “C:/ruby/lib/ruby/gems/1.8/gems/rake-0.8.1/lib/rake/rake_test_loader.rb”
C:/ruby/bin/ruby -Ilib;test “C:/ruby/lib/ruby/gems/1.8/gems/rake-0.8.1/lib/rake/rake_test_loader.rb”
Errors running test:units!

2008-03-06
76ERROR

Using the gem version of rails, the rake doc:rails command fails if I haven’t first run a rake rails:freeze:gems.

Running script/generate scaffold fails if I have installed the Ultrasphinx plugin according to the start of the recipe, but haven’t yet configured it, which comes after the script/generate command in the recipe:

script/generate scaffold document title:string file_path:string category:string content:text
/Users/jared/Rails/sphinx-sandbox/vendor/plugins/ultrasphinx/lib/ultrasphinx/ultrasphinx.rb:29: Please create a ‘config/ultrasphinx/development.base’ or ‘config/ultrasphinx/default.base’ file in order to use Ultrasphinx in your development environment. (Ultrasphinx::ConfigurationError)

Finally, it might be worth a quick note somewhere in the recipe that since Sphinx indexes MySQL or PostgreSQL, using it with SQLite3 (the default in Rails 2.0.2 and newer) is probably not going to work.

2008-03-07
79ERROR

The code snippet for search.html.erb makes use of the will_paginate plugin, but the recipe does not specify installing it.

2008-03-07
192OK

Since you’re doing async receipts, I think it would be nice to include a snack on the quickest (and dirtiest) way to get async processing in rails.

I’m using the spawn plugin to fork a child (it patches ActiveRecord so the database connection doesn’t get messed up), then I daemonize (except I don’t use Kernel.daemonize()… take that code, remove the first fork/exit, then use exit!() instead of exit(), so mongrel doesn’t lose its pid file).

Please get back to me (costan@gmail.com) if you want more details on this. I think it’s a really useful hack, and it’d have saved me many hours of agony if I’d have known how to do this “right”.

2008-03-07
325OK

The acts_as_secure plugin contains no test, I could not get the example to work on Rails 2.0.2 has anyone successfully used this on rails 2?

2008-03-18
238OK

I could not get this plugin to work using the instructions provided in snack recipe 47 and Rails 2.0.2
However the instructions included with the README file in the plugin itself work fine.

2008-03-18
19TYPO

Recipe #1 creates a scaffold with price but the example uses capacity, the sample code also uses capacity.

Page 15 (note price is used)
script/generate scaffold event name:string description:text ֓
price:decimal starts_at:datetime

Code/book p19 uses capacity
e = Event.create(:name => “Shortest event evar!”,
:starts_ad => 1.second.ago,
:capacity => 100)

2008-03-18
339TYPO

A minor point - the screenshot showing the custom maintenance page shows a different completion time (2:15 PM) to the one given in the command which supposedly generated the maintenance page (10:30 AM).

2008-03-18
292OK

The browser_profile! page gives me ‘Can’t convert Fixnum into String’. The line that is causing the problem is in application.rb:
controller.response.body << printer.print(“”,0)

I have tried a to_s to each side of the <<, but that didn’t help.

2008-03-18
20OK

It might be nice to mention that ActiveResource uses real HTTP PUT and DELETE instead of using the hidden form field. This is why “You can use it to reach out
to any server supporting the RESTful conventions of Rails.”

2008-03-18
22TYPO

Example uses search but ActiveRecord Search extension has not been discussed or setup in the example.

Also. The code is looking for parameter “q”

@events = Event.search(params[:q])

but the example URL is using “term”

/events/search?term=rubyconf

2008-03-18
391ERROR

Apendix A (Bibliography) shows up as part of Big-Picture Recipes in contents. This should probably go next to Big-Picture Recipes, not inside it.

2008-03-18
70ERROR

No mention in the recipe of how the form partials are to be incorporated into the ‘new’ and ‘edit’ views - even though the controller fragments shown render both those views. If there is nothing special in there - say so!

2008-03-18
391TYPO

[HL06] Should read “Beginning Ruby on Rails E-Commerce …” not “Begginng Ruby on Rails E-Commerce …”

2008-03-18
16TYPO

in pdf shows {:action=>“index”, :controller=>“events”}

in my actual rails app :action and :controller are switched, so it looks like
{:controller=>“events”, :action=>“index”}

2008-03-18
291OK

In regards to the code near the bottom of the page:

@related_products = cache([‘related_products’, user_id], :expires_in => 15.minutes) do
Product.related_products(user_id)
end

if you were to use a more complicated find method which includes other models, you’ll get an error when using cache_fu with memcached:

undefined class/module

since apparently you need to manually preload your models so memcache knows about them. You might want to mention this in the footnotes, and possibly discuss a method to get around this issue (the best solution I could find was to manually call your class names before invoking your method to be cached. More information can be found by googling memcache rails undefined class/module)

2008-03-18
94SUGGEST

when you try to rework the code in the album_controller, it is really easy to miss that the if statement has also changed from what was generated by the scaffold created code. it has changed from the album being told to save to the service being told to save. there is no mention of that in the surrounding description of what is happening there. this is true for both create and update.

def create
album = Album.new(params[:album]) cover = Cover.new(:uploaded_data => params[:cover_file])
service = AlbumService.new(album, cover) respond_to do |format| if service.save
flash[:notice] = ‘Album was successfully created.’
format.html { redirect_to(album) } format.xml { render :xml => album,
:status => :created,
:location => album } else format.html { render :action => "new" } format.xml { render :xml => album.errors,
:status => :unprocessable_entity }
end
end
end

2008-03-27
67OK

Should be noted that this technique does not work if you place a ‘validates_presence_of :project_id’ inside the Task class. If both the Project and the Task are new, Project will validates_associated its tasks before it saves itself, and thus the foreign key project_id isn’t set, so the validates_presence_of will fail.

It’s a chicken-and-the-egg problem. Because many people use validates_presence_of :project_id to enforce relational integrity, it should be noted this won’t work with the technique listed in this chapter.

Mike says: I’d recommend using foreign key constraints here, rather than Rails validations.

2008-03-27
311OK

If you create a separate environment, for your staging deployment, it is wise to add this to your deploy/staging.rb

set :rails_env, “staging”

Then the rails environment is set to this environment, when deploying.

2008-03-27
268OK

starting server with config.cache_classes = false will raise error “dependencies.rb:376:in `new_constants_in’: You have a nil object when you didn’t expect it! (NoMethodError)”.

The solution: in vendor/plugins, rename selenium-on-rails to selenium_on_rails. Note the underscores, rather than the dashes.

2008-03-27
95TYPO

“For example, the thumbnails are automatically gen-
erated after the cover has been saved. Thing can go wrong when a cover
is being saved, in which case attachment_fu will raise an exception.”

“Thing” should be “Things”

2008-03-27
89ERROR

Unless I’m missing something, Recipe 19 (Handle Multiple Models In One Form) doesn’t work when you want to delete all the tasks associated with a project—when all tasks are removed from the form, no task data is submitted and existing_task_attributes= is never called.

I’ve solved this by creating dummy tasks in my controller update action, but hidden fields (that don’t get hidden when the ‘remove’ link is clicked) might work too. Again, I may be missing something…

2008-03-27
19TYPO

Typo in “ever”
e = Event.create(:name => “Shortest event evar!”,
should be “Shortest event ever!”

2008-03-27
86SUGGEST

The recipe suggests passing the :direction parameter through the form, and then using send on the @quiz object. This seems awfully dangerous - what if someone posted the :direction param with “delete” instead of “next!”. Granted, you wouldn’t do this in real life, but someone might follow the recipe without realizing the implications.

I suggest using a case statement in the controller rather than #send. It’s not as nifty, but it prevents anyone from posting malicious code to the controller.

2008-03-27
132ERROR

The ingredients need to include the Hpricot gem as it also needs to be installed for the rails_api.rake script to work.

2008-03-27
135OK

There is a filesystem tweak that is required at least for Mac OS X. Otherwise, the rake ultrasphinx:index returns the following error:

dyld: Library not loaded: /usr/local/mysql/lib/mysql/libmysqlclient.15.dylib
Referenced from: /usr/local/bin/indexer
Reason: image not found

The Oct 29, 2007 entry of freelancing-gods.com provides the details on the fix:

sudo ln -s /usr/local/mysql/lib /usr/local/mysql/lib/mysql

2008-03-27
96OK

The code provided for updating albums doesn’t work if you don’t provide a new image every time you edit it (at least on my machine). I’ve found I had to change:

unless cover_file.blank?
@cover = Cover.new(:uploaded_data => cover_file)
end

to

unless cover_file.blank?
cover = Cover.new(:uploaded_data => cover_file) else cover = @album.cover
end

for it to work

2008-03-27
23OK

I get the following error when clicking on the “Copy” button:

NoMethodError in EventsController#copy

undefined method `copy’ for #

RAILS_ROOT: /home/inno/aptana/workspace/dan1
Application Trace | Framework Trace | Full Trace

/usr/local/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/base.rb:1532:in `method_missing’
app/controllers/events_controller.rb:96:in `copy’

/usr/local/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/base.rb:1532:in `method_missing’
/usr/local/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/base.rb:1158:in `send’
/usr/local/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/base.rb:1158:in `perform_action_without_filters’
/usr/local/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/filters.rb:697:in `call_filters’
/usr/local/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/filters.rb:689:in `perform_action_without_benchmark’
/usr/local/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/benchmarking.rb:68:in `perform_action_without_rescue’
/usr/local/lib/ruby/1.8/benchmark.rb:293:in `measure’
/usr/local/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/benchmarking.rb:68:in `perform_action_without_rescue’
/usr/local/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/rescue.rb:199:in `perform_action_without_caching’
/usr/local/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/caching.rb:678:in `perform_action’
/usr/local/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/connection_adapters/abstract/query_cache.rb:33:in `cache’
/usr/local/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/query_cache.rb:8:in `cache’
/usr/local/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/caching.rb:677:in `perform_action’
/usr/local/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/base.rb:524:in `send’
/usr/local/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/base.rb:524:in `process_without_filters’
/usr/local/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/filters.rb:685:in `process_without_session_management_support’
/usr/local/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/session_management.rb:123:in `process’
/usr/local/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/base.rb:388:in `process’
/usr/local/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/dispatcher.rb:171:in `handle_request’
/usr/local/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/dispatcher.rb:115:in `dispatch’
/usr/local/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/dispatcher.rb:126:in `dispatch_cgi’
/usr/local/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/dispatcher.rb:9:in `dispatch’
/usr/local/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel/rails.rb:76:in `process’
/usr/local/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel/rails.rb:74:in `synchronize’
/usr/local/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel/rails.rb:74:in `process’
/usr/local/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:159:in `process_client’
/usr/local/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:158:in `each’
/usr/local/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:158:in `process_client’
/usr/local/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:285:in `run’
/usr/local/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:285:in `initialize’
/usr/local/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:285:in `new’
/usr/local/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:285:in `run’
/usr/local/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:268:in `initialize’
/usr/local/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:268:in `new’
/usr/local/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:268:in `run’
/usr/local/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel/configurator.rb:282:in `run’
/usr/local/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel/configurator.rb:281:in `each’
/usr/local/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel/configurator.rb:281:in `run’
/usr/local/lib/ruby/gems/1.8/gems/mongrel-1.1.4/bin/mongrel_rails:128:in `run’
/usr/local/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel/command.rb:212:in `run’
/usr/local/lib/ruby/gems/1.8/gems/mongrel-1.1.4/bin/mongrel_rails:281
/usr/local/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:489:in `load’
/usr/local/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:489:in `load’
/usr/local/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:342:in `new_constants_in’
/usr/local/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:489:in `load’
/usr/local/lib/ruby/gems/1.8/gems/rails-2.0.2/lib/commands/servers/mongrel.rb:64
/usr/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `gem_original_require’
/usr/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `require’
/usr/local/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:496:in `require’
/usr/local/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:342:in `new_constants_in’
/usr/local/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:496:in `require’
/usr/local/lib/ruby/gems/1.8/gems/rails-2.0.2/lib/commands/server.rb:39
/usr/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `gem_original_require’
/usr/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `require’
script/server:3

/usr/local/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/base.rb:1532:in `method_missing’
app/controllers/events_controller.rb:96:in `copy’
/usr/local/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/base.rb:1158:in `send’
/usr/local/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/base.rb:1158:in `perform_action_without_filters’
/usr/local/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/filters.rb:697:in `call_filters’
/usr/local/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/filters.rb:689:in `perform_action_without_benchmark’
/usr/local/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/benchmarking.rb:68:in `perform_action_without_rescue’
/usr/local/lib/ruby/1.8/benchmark.rb:293:in `measure’
/usr/local/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/benchmarking.rb:68:in `perform_action_without_rescue’
/usr/local/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/rescue.rb:199:in `perform_action_without_caching’
/usr/local/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/caching.rb:678:in `perform_action’
/usr/local/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/connection_adapters/abstract/query_cache.rb:33:in `cache’
/usr/local/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/query_cache.rb:8:in `cache’
/usr/local/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/caching.rb:677:in `perform_action’
/usr/local/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/base.rb:524:in `send’
/usr/local/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/base.rb:524:in `process_without_filters’
/usr/local/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/filters.rb:685:in `process_without_session_management_support’
/usr/local/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/session_management.rb:123:in `process’
/usr/local/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/base.rb:388:in `process’
/usr/local/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/dispatcher.rb:171:in `handle_request’
/usr/local/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/dispatcher.rb:115:in `dispatch’
/usr/local/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/dispatcher.rb:126:in `dispatch_cgi’
/usr/local/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/dispatcher.rb:9:in `dispatch’
/usr/local/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel/rails.rb:76:in `process’
/usr/local/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel/rails.rb:74:in `synchronize’
/usr/local/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel/rails.rb:74:in `process’
/usr/local/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:159:in `process_client’
/usr/local/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:158:in `each’
/usr/local/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:158:in `process_client’
/usr/local/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:285:in `run’
/usr/local/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:285:in `initialize’
/usr/local/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:285:in `new’
/usr/local/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:285:in `run’
/usr/local/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:268:in `initialize’
/usr/local/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:268:in `new’
/usr/local/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel.rb:268:in `run’
/usr/local/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel/configurator.rb:282:in `run’
/usr/local/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel/configurator.rb:281:in `each’
/usr/local/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel/configurator.rb:281:in `run’
/usr/local/lib/ruby/gems/1.8/gems/mongrel-1.1.4/bin/mongrel_rails:128:in `run’
/usr/local/lib/ruby/gems/1.8/gems/mongrel-1.1.4/lib/mongrel/command.rb:212:in `run’
/usr/local/lib/ruby/gems/1.8/gems/mongrel-1.1.4/bin/mongrel_rails:281
/usr/local/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:489:in `load’
/usr/local/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:489:in `load’
/usr/local/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:342:in `new_constants_in’
/usr/local/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:489:in `load’
/usr/local/lib/ruby/gems/1.8/gems/rails-2.0.2/lib/commands/servers/mongrel.rb:64
/usr/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `gem_original_require’
/usr/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `require’
/usr/local/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:496:in `require’
/usr/local/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:342:in `new_constants_in’
/usr/local/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:496:in `require’
/usr/local/lib/ruby/gems/1.8/gems/rails-2.0.2/lib/commands/server.rb:39
/usr/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `gem_original_require’
/usr/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `require’
script/server:3

Request

Parameters:

{“authenticity_token”=>“8c36c63d573758062f12a1ab0c41bf939bbd17cf”,
“id”=>“5”}

Show session dump


flash: !map:ActionController::Flash::FlashHash {}

:csrf_id: a4806a9952528835d9d92a2f2ee04a05

Response

Headers:

{“cookie”=>[],
“Cache-Control”=>“no-cache”}

2008-04-08
86SUGGEST

Recipe 16 (Create Multi-Step Wizards) suggests using the button_to helper for to generate the “previous” button. However, this would create a second form element embedded within the quiz form. I’m not sure if this would be invalid HTML, but it may cause problems with some browsers.

Instead, I suggest using button_to_function, which would create a button element that could execute javascript to update the hidden field and submit the form.

Example: <%= button_to_function “← Previous”, “$(‘direction’).value = ‘previous!’; this.form.submit();” %>

2008-04-08
69DEFER

Adding multiple subforms the way it’s described in this book can cause some serious defects because all new items have the same ids and names:

Fails html validation:

Unless he explicitly makes the “id” attribute nil the id attribute will be project_new_task_attributes__name - like so:

If you want to add labels with ids to this you will end up with duplicate ids for labels and this will fail validation. But even if you don’t care about w3c validation this can cause serious bugs in subforms - for example if you add radio buttons. Here’s the scenario:

  • You have an event registration form where a person can register a company and several employees
  • Every employee has a set of radio buttons for meal preferences that you’d like to display with radio buttons
  • You follow this recipe, add the radio buttons like you would any other form and view the page
  • After you click “add” several times clicking any radio button you’ll notice that you can only specify one value across all subforms!

The solution has 2 parts:

  • when adding a form via the “add” link you have to manually set an id from javascript (there’s no way around that)
  • when re-rendering the form with errors you need to render the partials with an index, and set the javascript index to be correct.

I’ll provide more info on this is you need it - jeff at zilkey . com

2008-04-11
300ERROR

I still get the “can’t Fixnum into String” error when loading a page with ‘?browser_profile!’ appended to the URL.

This was reported for the previous version as #31189 where it is marked as fixed in B1.06.

The line apparently with the problem is:

controller.response.body << printer.print(“”, 0)

162ERROR

Keep Forms Dry, error_handling_form_builder.rb defines array of helpers; two are removed in the line “%w(label fields_for)” — this should also include “hidden_field”

BTW — this was a much needed recipe for my app. Now I need to figure out how to make it work for the scaffold generated “show” views, too :-)

117ERROR

DynamicMetaTags has this code which fails on IE:

def meta(name, content)
%(<meta name=“#{name}” content=“#{content} />” )
end

should be this (end quote incorrect)

def meta(name, content)
%(

)
end

But why not use tag helper and be more railsy :-)

def meta(name, content)
tag(“meta”, :name => name, :content => content)
end

291ERROR

In the first set of code examples on the page, a list of caching commands to execute through the console, in the last example of that section:

>> products = Product.related_products(“barney”)
>> ActionController::Base.cache_store.fetch(“barney”) { products }
=> [#<Product id: 21, …]

The description of fetch just below this says: " When it doesn’t find your key in the cache,
it’ll run the block, save its results into the cache, and give them back
to you."

But in this case the Product#related_products method gets executed before the call to fetch which is then only passed the reference to the already loaded collection.

Should the correct way to handle this not look like:

ActionController::Base.cache_store.fetch(“barney”) do
Product.related_products(“barney”)
end

?

73ERROR

Hi, there’s a delete of a task from inside an iterator. I don’t think that’s safe, you’ll not get to the end of the collection there. I had a collection of two objects where the first was deleted inside the iterator. The iterator never iterated over the second object. Better to collect an array of tasks_to_be_deleted and then call tasks.delete(tasks_to_be_deleted) once outside the iterator. Also, tasks are deleted a different step and not wrapped within the same transaction as the rest of the update when the after_update is called.

94SUGGEST

rescue and then just return false eats all exceptions (I for example had a type in the code), in my point of view this is very dangerous. Don’t understand why you don’t just track the status of the first save in a local variable?

147TYPO

After the two rake commands on the 4th & 5th lines of p147, it says:

“(If you’re into shortcuts, these THREE Rake tasks…”

I believe the third rake task it is referring to is
“rake ultrasphinx:configure”
from two pages prior. But I can’t be sure and it is very unclear.

297ERROR

This recipe doesn’t work. If I type Status::PENDING on the console, I always get a NameError: uninitialized constant Status::PENDING

Maybe it’s because I’m using Postgres?

394TYPO

Index item for “Konkel, William” should be “Konkel, Warren”.

188ERROR

recipe #32 is a potential security problem.
Sending email.

297SUGGEST

It should be mentioned that the caches_constants method does not play nice with tests (at least in Rails 2.0.2).

Apparently fixtures are loaded after caches_constants is called which results in no constants being defined and tests failing due to this.

Assuming the following fixture:

pending:
name: Pending

active:
name: Active

disabled:
name: Disabled

Here’s an ugly work-around for unit tests that calls caches_constants again after the fixtures are loaded:

def setup
# I’m assuming if Status::PENDING is undefined, so are the others
unless defined?(Status::PENDING)
Status.caches_constants
end
end

I hope you can come up with something better.

212TYPO

In the restaurants.html.erb layout file the line containing the google maps API key has a return character. When accessing the internet through a proxy this causes the key to be unrecognised. Simply making the src all one line solves the problem.

i.e change

to

N.B Had to remove the http part of the src in order to submit this erratum

90SUGGEST

For the upload images with thumbnail you have the migration file for the Covers. I don’t see a migration file for the actual Albums. Can you provide the migation for the Albums? I can decipher some of the fields from the albums/new.html.erb form.

380SUGGEST

RE: subdomains as account keys:

There’s a weird issue with Leopard and request.subdomains — I found the solution on the rails wiki (yeah, i know, something useful on the rails wiki ;) wiki.rubyonrails.org/rails/pages/HowToUseSubdomainsAsAccountKeys.

basically, on leopard currently you need request.subdomains(0) instead of request.subdomains.

Might just want to link to that information in a footnote, b/c I’d bet a large chunk of your readers are Leopard readers and this is a pretty annoying bug.

thanks!

216ERROR

If you don’t use the “set_no_auto_load true” option described later in the recipe, the args passed to the create method will be nil which causes a nil error to be raised. Checking args.nil? before running the args loop is recommended.

73SUGGEST

The recipe is formatted differently from the others (has no “problem”, “ingredients”, “solution”, etc. tabs). This looks messy

389TYPO

“Bibliography” section is given as a part of “Big picture recipes”

238ERROR

Broken link to March Chung’s plug-in.

70TYPO

The exisiting_task_attributes POST parameter example shows the hash of the existing task as and array of hashes. I think it is actually just a hash. When I tried to replicate that model in a functional test, if wouldn’t work unless I removed the array, and just made existing_task_attributes a hash based on the task idea rather than a nested hash.

212SUGGEST

I think it should be mentioned where to get the class S3Uploader and what does it do (does it erase the filesystem files?, does it save the thumbnails?).

32TYPO

Second to the last paragraph, last line, should probably say “as we’ll see in a minute”

171SUGGEST

OrdersController should show samples of all actions not just NEW and CREATE because you are likely going to need them. This would also distinguish the recipe from the one Jay Fields has on his website and summarize differences in working with the excluded actions. It seems incomplete to me.

239ERROR

creating the worker as per the example, the job_key is not returned, though the code seems to work otherwise

98ERROR

in the save method of the AlbumService, you have:

if cover.new_record? album.cover.destroy if album.cover cover.album = album cover.save
end

I think this should be

if cover.new_record? album.cover.destroy if album.cover album.cover = cover cover.save
end

as Album has_one Cover and Cover belongs_to Album.

Or I’m missing something. But that’s how I got it to work.

162TYPO

error_handling_form_builder.rb lists helpers in a series of %w(…) clauses. collection_select is duplicated

156ERROR

Assuming that the sample results from Article.publicly_viewable and Article.premium are sorted by id, wouldn’t Article.publicly_viewable.premium NOT include #<Article id: 1> since nested scopes are AND’d and not OR’d?
It should only include those which are true for ALL of the named_scope filters.

>> Article.publicly_viewable
=> [#<Article id: 1,…]
>> Article.premium
=> [#<Article id: 2,…]
To find all publicly viewable and premium articles, we can nest the scopes:
>> Article.publicly_viewable.premium
=> [#<Article id: 1,…>, #<Article id: 2,…> ]

18SUGGEST

re: puts events.map(&:name)

The frequent use of the &:method_name syntax in this book warrants some explanation. As far as I can tell, the current edition (2) of the pickaxe does not mention it at all, and it really threw me for a loop.

As far as I can guess, if you have a method that takes a block, you can supply a symbol that represents another method’s name (prefixed w/ & as usual), and the referenced method will get converted to a proc & sent to the first method, with the block parameters automatically getting supplied as parameters to the referenced method.

However I’d love for someone who actually knows what’s going on here to independently confirm this.

22ERROR

the method copy in this page is incomplete. The online code has it right.

14SUGGEST

rake migrate is enough, no need to rake create before that

21SUGGEST

I’d suggest the reader at this point to add a search.html.erb file to display the search results

26ERROR

in registrations/index.html.erb, the following line of code:
for registration in registrations should be for registration in event.registrations

323TYPO

This is of little importance, but the second line in the “Problem” paragraph should probably start with “by HIPAA” (instead of “by HIPPA”)

242SUGGEST

It may be obvious to those that have been doing Rails for a while but for new folks you might want to mention that the Backgroundrb requires that you call the prototype.js script from scriptaculous when you include the periodically_call_remote as you get a Javascript error that “PeriodicalExecuter is undefined”.

72ERROR

In the first code example, it shows that “existing_task_attributes” references an array of hashes. I think it just references a hash, and the prose seems to support that.

Also, in the prose, whenever params[something] is used, it’s hard to tell if those are parenthesis or brackets. It may be a font thing.

Thanks!

50ERROR

On the bottom of page 50, it says, “we can mix in our custom validation methods only when we need them.” I don’t understand. They’re always mixed in. I see “ActiveRecord::Base.extend(CustomValidations)”. Isn’t this always mixing them in?

301TYPO

It says “rake:test:acceptance”. I think this should be “rake test:acceptance”.

196ERROR

It says, “The encrypt method creates a new instance of the chosen cipher.” I’m guessing that’ it’s actually Cipher.new that creates the new instance.

288ERROR

It says, “One fairly unique feature of Shoulda is nested contexts.” RSpec has this too, right?

366SUGGEST

In this code, the salt is configured once for each environment. It’d be better if each and every piece of data was encrypted with a different salt. The salt should be stored with each piece of data in the database. That’s how Linux password files work. It’s something like:

salt = something_random_for_each_record
encrypted = encrypt(data + salt + site_wide_password) + salt

The site_wide_password is really the key. The salt is there just to thrown a monkey wrench in the works and make things a bit harder to figure out the site_wide_password.

368ERROR

I see “proxy_set header X_FORWARDED_PROTO https;”. What happens if the user uses HTTP instead of HTTPS and manually sets that header?

370SUGGEST

This recipe will redirect the user to HTTPS if he uses HTTP. However, if you accidentally submit a credit card over HTTP, it’s too late—the game is already over and a redirect won’t help. That’s why I’ve decided that such situations should result in a 404. If it’s flat out broken, then I’ll realize the problem faster and fix it. A redirect could cover up the real problem.

Maybe you should mention this in the “Discussion” section.

235SUGGEST

I’m reading the “Send Lightweight Messages” recipe. I’m worried that if the rake task crashes after getting the task, the task will be lost. A lot of queue software tries to handle this case.

For instance, if a worker takes too long, the manager will assume he’s borked and reassign the task to another worker.

135ERROR

It says, “String-based fields (for example, the MySQL VARCHAR type) can often be easily indexed directly in the database where appropriate.”

Because of the way you’re using LIKE, it turns out MySQL won’t use an index. Because MySQL has to examine every row, it turns out that a linear table scan is faster than scanning the entire index. That’s why MySQL won’t use an index if it has to scan the entire table (unless the index would help with ordering). It’s helpful to use “explain” on the query in order to double check whether MySQL is or isn’t using an index.

Happy Hacking!

139ERROR

It says, “you may want to change the name of the pid_file for the three environments so that you can run servers for each environment simultaneously.”

To run more than one server, you’re also going to need a different port for each.

140TYPO

It says “Calling find_by_contents turns around behind the scenes…” However, there’s a huge amount of space after “Calling”. Maybe it’s just in my version, but it’s as if someone had their hand resting on the space bar ;)

204SUGGEST

In the “Discussion” section for “Process Credit Card Payments”, it’d be useful to mention that authorize.net has a customer information manager that could completely alleviate the need for this recipe and make it easier to achieve PCI compliance. I was a confused when I read this recipe because I was looking for how to process credit card numbers, not how to store credit card numbers. It might make sense to change the chapter’s title.

Also, while I’m definitely no Ruby on Rails expert, it seems to me that set_encryption_password isn’t thread safe. I thought Rails 3 was supposed to support threaded servers, so being non-thread-safe might be a big deal. Who knows if that’ll ever actually happen, but it might at least warrant a comment in the code.

211SUGGEST

I’m looking at Geocoding/app/views/restaurants/search.html.erb. It’s interesting to note that “restaurants” is pluralized, but “miles” isn’t. It’s probably best to always pluralize or never pluralize.

429SUGGEST

In the “Discussion” section of “Give Users Their Own Subdomain”, I think you should add a few more caveats.

If you give users their own subdomain, it’s important that you not allow them to upload Flash or JavaScript content. You should even make sure they can’t upload Flash content and pretend it’s an image. If they can upload Flash or JavaScript for andy.example.com, they can hijack sessions for all of example.com. Having recently read the security section for ActionScript, there’s all sorts of nasty things users can do if you let them upload their own ActionScript onto your domain.

I think that’s why Blogger makes me author my blog posts on blogger.com, but my actual blog lives at blogspot.com.

432ERROR

It says:

message = (String === message ? message : msg.inspect)

Is it really supposed to say “String === message”? Is that really how you check if message is a string?

Where is “msg” coming from?

433TYPO

In recipes_log_formatter.rb, it says:

.gsub(/\
/, ’’).strip

Why not replace newlines with spaces? That would be less confusing.

235ERROR

The otherwise excellent recipe contains an nginx conf. snippet to make sure all requests return the maintenance page:

if ($request_filename ~* \\.(css|jpg|gif|png)$) {
break;
}
if (-f $document_root/system/maintenance.html) {
rewrite ^(.*)$ /system/maintenance.html last;
break;
}

However, that does not work since it gets into an inf. loop on the maintenance page (/system/maintenance.html) itself.

The (or rather ‘a’) correct config is the following:

if ($request_filename ~* \\.(css|jpg|gif|png)$) {
break;
}
if ($request_filename = $document_root/system/maintenance.html) {
break;
}
if (-f $document_root/system/maintenance.html) {
rewrite ^(.*)$ /system/maintenance.html last;
break;
}

I hope that helps,
Bálint

212ERROR

Rails version - 2.3.5
ruby 1.8.7 (2008-08-11 patchlevel 72) [universal-darwin10.0]
gem version 1.3.6

The entry in app/layouts/restaurants.html.erb -

var restaurants = <%= @restaurants.to_json %>;

Show’s up in the browser as

var restaurants = [{restaurant Sushi“,”address“:”9447 Park Meadows Dr, Lone Tree, CO“,”created_at“:”2010-03-13T00:08:48Z“,”updated_at“:”2010-03-13T00:08:48Z“,”lng“:–104.879512,”id“:2,”lat“:39.554912,”distance“:”0.999219415981368“}},{”restaurant“:{”name“:”Sushi Wave“,”address“:”9555 E Arapahoe Road, Greenwood Village, CO“,”created_at“:”2010-03-13T00:09:54Z“,”updated_at“:”2010-03-13T00:09:54Z“,”lng“:–104.878099,”id“:3,”lat“:39.595709,”distance“:”1.84318061453223“}},{”restaurant“:{”name“:”Sushi Terrace“,”address“:”8162 S Holly St, Littleton, CO“,”created_at“:”2010-03-13T00:10:50Z“,”updated_at“:”2010-03-13T00:10:50Z“,”lng“:–104.9230185,”id“:4,”lat“:39.5688859,”distance“:”2.50444556563776"}}];

(After I entered the sample data).

The restaurants variable is then referenced in public/javascripts/application.js to create a marker like such …

var latlng = new google.maps.LatLng(restaurants[i].lat,restaurants[i].lng)

which is undefined in Javascript.

My fix —-

layouts/restaurants.html.erb

var found = <%= @restaurants.to_json %>;

javascripts/application.js

var latlng = new google.maps.LatLng(found[i].restaurant.lat,found[i].restaurant.lng);

I suupose you could just change application.js to
var latlng = new google.maps.LatLng(restaurant[i].restaurant.lat,restaurant[i].restaurant.lng);

Not sure what the @restaurants.to_json function is supposed to return and may well have worked differently when the recipe was written.

Just thought you should know of this gotcha.

224ERROR

Implementing the acts_as_state_machine works perfectly when using the Pdf model inside controllers and the console. But no matter what I do I cannot call the event methods inside the simple daemon class.

247247TYPO

Book says:

class Addressable
belongs_to :addressable, :polymorphic => true
end

But maybe it means:

class Address

end

80ERROR

Both the text and graphical depiction of the state machine ignore previous! when in state q10.

82SUGGEST

“Notice that we didn’t call the new method on Quiz. We have to use the create method in order for the acts_as_state_machine magic to kick in and set the initial state properly. Let’s check that:”

Why doesn’t new work? What’s so funny about acts_as_state_machine? How would I know other plugins that require using ‘create’ instead of ‘new’?

83TYPO

“we’ll write a helper figure out”

s/helper figure/helper to figure/

93SUGGEST

“Second, the form uses the file_field_tag helper (instead of f.file_field) to generate a Choose File button on the form.”

Why is the form using file_field_tag instead of f.file_field?

131TYPO

“native text­—indexing extension.” using a different hyphenation than “plug-in” or “T-search”

218SUGGEST

“The billing_status method gets the status status”

The variable is already named ‘status’, “status status” seems silly :) we don’t want the status of the status, we want the actual status.

220SUGGEST

“However, on a really busy day, we might have multiple shop owners all sending e-mails at the same time. And if the worker is already busy when a new task arrives, the work won’t get queued.”

Wow, I was surprised when I read that workers are unreliable, and thread pools must be used to make ‘reliable workers’. I’d read pages of code, and then this snippet is buried in as an afterthought seven pages into the recipe! It seems like it’d be useful to put this information near the front of the discussion of workers.

(And the code to make the workers reliable is stuck in each individual worker? seems like a recipe for cut-n-paste disasters..)

233ERROR

The procmail recipe is broken; it is missing the ‘cd’.

249SUGGEST

The entire RSpec recipe, I was waiting to find out why anyone would bother with using RSpec. I didn’t see anything obvious while reading it that it could do that standard Rails test infrastructure couldn’t do. Is it basically a way to say “should have_tag()” rather than “assert_select tag…”?

I’m not sure adding a ton of new synonyms to the language is worthwhile, so there’d better be something useful to RSpec to bother talking about it.

279TYPO

s/loop holes/loopholes/

280TYPO

In the epub version of the book, “underlying assertions:assert_w3c and assert_tidy”. There is a linebreak in the pdf (and probably the paper :) but the epub is missing any whitespace between assertions and assert_w3c.

344TYPO

In the epub version of the book, ‘devel-opment’ has an embedded hyphen; the PDF looks fine, because there is a word-wrap there, so I assume adobe things need to be told how to hyphenate “development” automatically :)

376SUGGEST

“One important caveat: Piston doesn’t preserve change history from the remote repository. Piston just takes the latest revision, or differences between what you currently have and the latest revision, and merges those changes into your checked-out copy. However, you can examine the changes before committing them to your local repository.”

Wow. Piston sounds like a pretty poor replacement for git. Piston might make it possible to tolerate svn:externals, but I think a bigger service to readers would be to suggest using the right tool for the right job. If you just want CVS but with changesets, svn is pretty good. If you want to perform distributed version management, that’s pretty firmly outside svn’s mission statement, and something like git would probably serve you way better.

172ERROR

The implementation of OrderPresenter will allow form submissions to assign any value to any of the supported models, completely bypassing the attr_accessible or attr_protected safeguards that those models (should) have in place. (Well, it isn’t any value — the values still must pass validation — but valid values can also be values that should not be set in bulk: account.admin=1. Or credential_username=root, credential_password=foobar.)

A correct implementation would not just blindly send() the constructed method — it must call or re-implement the attr_protected/attr_accessable checks that ActiveRecord supports. Or support only a specifically-named small list of allowed methods.

212ERROR

to_json function behavior
(Also please see contribution #42448 as reference)
In Rails 2.3.5 your code does not work.
In order to make your code work as expected, add statement ActiveRecord::Base.include_root_in_json = false to config/initializers/new_rails_defaults.rb file

Otherwise, Json string would have format: [{restaurant, etc.], so the proper reference would be restaurant[1].restaurant.name, i.e. to get the name of the first restaurant.

89ERROR

The download url for attachment_fu is not longer valid. The new url is (http) @ github.com/technoweenie/attachment_fu.git

382TYPO

“… and call set_cookie domain only when …” should be “… and call set_cookie_domain only when … ” (located near the end of the paragraph immediately following the code snipped for “Subdomains/app/controllers/application.rb”)

21ERROR

Routes syntax changed considerably in ROR 3.

The eg given map.resources :events, :collection => { :search => :get }

Should be

resources :events do
collection do
get ‘search’
end
end

44TYPO

Download CatchAll404s/app/models/four_oh_four.rb

find_or_initialize
in code provided

find_and_initialize
in code description

Categories: