1

I'm running Rails 3.1.1 and getting an odd bug. In development (haven't yet tried pushing to production with it) I'm occasionally getting routing errors in my controller or in my mailer template when it tries to generate a url for a newly created record. This happens even though the record is created successfully and appears to have nothing to do with the record properties (I can recreate a record with the exact same params right after and not get the error, it seems totally random when it happens).

It seems to happen maybe one in 10 times, though I can't say I ever saw an incident of it happening before I added the mailer action.

There's one more potentially complicating factor: I'm using an encryption method to obfuscate the record's id in its URL, but this is otherwise working without a hitch. To do this I adapted the method discussed here

It seems to me like the URL's not generated in time for the link_to call some of the time... But that doesn't make much sense to me. I didn't think race conditions were something I needed to worry about here.

Here are my error logs when this happens in the controller (when the params don't call for an email to be generated):

ActionController::RoutingError (No route matches {:action=>"show", :controller=>"watch_lists", :id=>#<WatchList id: 195, title: "sfdsfd", created_at: "2012-03-19 05:18:46", updated_at: "2012-03-19 05:18:46", public_list: false>}):
  app/controllers/watch_lists_controller.rb:72:in `block (2 levels) in create'
  app/controllers/watch_lists_controller.rb:56:in `create'

And here's when it happens in the mailer template (when the params do call for an email to be generated before the render command):

Rendered watch_list_mailer/share_notification.html.erb (3.2ms)
Completed 500 Internal Server Error in 113ms

ActionView::Template::Error (No route matches {:action=>"show", :controller=>"watch_lists", :id=>#<WatchList id: 210, title: "sdggsgsg", created_at: "2012-03-19 05:47:17", updated_at: "2012-03-19 05:47:17", public_list: true>}):
    20:             <% end %>
    21:         <% end %><br>
    22:         <br>
    23:         Here's a link to your WatchList: <%= link_to @wl.title, watch_list_url(@wl) %><br>
    24:         <br>
    25:         Enjoy!
    26:     </p>
  app/views/watch_list_mailer/share_notification.html.erb:23:in `_app_views_watch_list_mailer_share_notification_html_erb___1391186431365383285_70156615518000'
  app/mailers/watch_list_mailer.rb:12:in `share_notification'
  app/controllers/watch_lists_controller.rb:124:in `share_notification'
  app/controllers/watch_lists_controller.rb:68:in `block (2 levels) in create'
  app/controllers/watch_lists_controller.rb:63:in `each'
  app/controllers/watch_lists_controller.rb:63:in `block in create'
  app/controllers/watch_lists_controller.rb:56:in `create'

EDIT: Upon further testing, this appears to happen regardless of whether I include the mail task. It seems most likely spurred by the obfuscation of the links. It's possible that the encoding of the links has something to do with it (I had to make sure to URI-escape them to prevent slashes in the wrong places elsewhere in my code). I'll investigate this futher and report back.

Community
  • 1
  • 1
Trespassers W
  • 379
  • 1
  • 5
  • 14
  • Check that `persisted?` is returning true for your instances. – Frederick Cheung Mar 19 '12 at 08:47
  • I solved it. The issue was with the URL obfuscation returning invalid links when the encrypted id contained a slash. Because the records were created successfully, trying again would actually create a record with a different id and thus a different encrypted URL that might have included '/' or other invalid characters in it. I previously corrected for this directly where I created paths to the record, but it didn't transfer to working in the view. Forcing URI encoding of every encrypted id fixed the issue. `URI.escape(self.encrypt(value), Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))` – Trespassers W Mar 19 '12 at 18:49

1 Answers1

0

It was a problem with the id encryption creating invalid links occasionally and me failing to account for that in early enough in the process.

In lib/obfuscate.rb

def uri_encrypt(value)
    URI.escape(self.encrypt(value), Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
end

In my model

def to_param
    uri_encrypt(id)
end
Trespassers W
  • 379
  • 1
  • 5
  • 14