This error was happening on a field that stored a serialized Hash.
It appears the size of the field was too small. I had it at a string varchar(255) and after changing it to a limit of 1000, the error went away.
change_column :users, :search_fields, :string, :limit => 1000
I presume this is due to a few characters at the end getting cut off, so the data structure no longer matched a hash.
Saturday, March 20, 2010
Monday, March 01, 2010
Rails Exception Logger Plugin
This is simple to set up, but not so easy to find on the web. Just writing it down so it's easier to find in one place.
First install the plugin. Do this from the app_root directory.
script/plugin install git://github.com/defunkt/exception_logger.git
Next, generate the migration and run it:
script/generate exception_migration
rake db:migrate
Add this to your ApplicationController
class ApplicationController
include ExceptionLoggable
Then, add to routes the following:
map.connect "logged_exceptions/:action/:id", :controller => "logged_exceptions"
Restart your system to pick up the plugin.
Pagination
To get pagination working with will_paginate, go into plugins/exception_logger/init.rb and modify it so it looks like this.
#$PAGINATION_TYPE = 'none'
require 'will_paginate'
$PAGINATION_TYPE = 'will_paginate'
WillPaginate.enable
#require 'paginating_find'
#$PAGINATION_TYPE = 'paginating_find'
LoggedExceptionsController.view_paths = [File.join(directory, 'views')]
And, in my case, I didn't have redcloth installed, so I modified plugins/exception_logger/views/logged_exceptions/_show.rhtml
I removed textilize and used 'simple_format'
By the way, there is part of the logged_exceptions README that encourages you to overwrite a few methods, including render_404(exception)
To do this, you would do something like the following. In your application_controller:
def render_404(exception)
log_exception(exception)
render :file => '/errors/400', :status => 400
end
This would be good if you wanted to reuse your layouts and show a dynamic page instead of using one of the static pages in the /public directory.
One last thing
If you want to restrict access to the logged_exception controller and you are using authlogic from binary logic, here is one way to do it:
In authorization_rules.rb, add the privilege to manage logged_exceptions
role :administrator do
has_permission_on :logged_exceptions, :to => :manage
end
Then, in the plugins/exception_logger/lib/logged_exceptions_controller.rb
I changed the file to look like this:
class LoggedExceptionsController .. ApplicationController
filter_access_to :query, require => :manage
filter_access_to :destroy_all, :require => :manage
And - the icing on the cake. I a free rss app for the iphone. Entered the url for the rss feed with the authlogic user_credentials parameter attached to the url
http://yourapp.com/logged_exceptions?format=rss&user_credentials=single_access_token
You can get the single_access_token from the user table - just use your admin user to access the rss feed. Very handy to have an rss feed of the latest exceptions right on your iphone. You can also modify the views to add more information to the rss item if you need to.
First install the plugin. Do this from the app_root directory.
script/plugin install git://github.com/defunkt/exception_logger.git
Next, generate the migration and run it:
script/generate exception_migration
rake db:migrate
Add this to your ApplicationController
class ApplicationController
include ExceptionLoggable
Then, add to routes the following:
map.connect "logged_exceptions/:action/:id", :controller => "logged_exceptions"
Restart your system to pick up the plugin.
Pagination
To get pagination working with will_paginate, go into plugins/exception_logger/init.rb and modify it so it looks like this.
#$PAGINATION_TYPE = 'none'
require 'will_paginate'
$PAGINATION_TYPE = 'will_paginate'
WillPaginate.enable
#require 'paginating_find'
#$PAGINATION_TYPE = 'paginating_find'
LoggedExceptionsController.view_paths = [File.join(directory, 'views')]
And, in my case, I didn't have redcloth installed, so I modified plugins/exception_logger/views/logged_exceptions/_show.rhtml
I removed textilize and used 'simple_format'
By the way, there is part of the logged_exceptions README that encourages you to overwrite a few methods, including render_404(exception)
To do this, you would do something like the following. In your application_controller:
def render_404(exception)
log_exception(exception)
render :file => '/errors/400', :status => 400
end
This would be good if you wanted to reuse your layouts and show a dynamic page instead of using one of the static pages in the /public directory.
One last thing
If you want to restrict access to the logged_exception controller and you are using authlogic from binary logic, here is one way to do it:
In authorization_rules.rb, add the privilege to manage logged_exceptions
role :administrator do
has_permission_on :logged_exceptions, :to => :manage
end
Then, in the plugins/exception_logger/lib/logged_exceptions_controller.rb
I changed the file to look like this:
class LoggedExceptionsController .. ApplicationController
filter_access_to :query, require => :manage
filter_access_to :destroy_all, :require => :manage
And - the icing on the cake. I a free rss app for the iphone. Entered the url for the rss feed with the authlogic user_credentials parameter attached to the url
http://yourapp.com/logged_exceptions?format=rss&user_credentials=single_access_token
You can get the single_access_token from the user table - just use your admin user to access the rss feed. Very handy to have an rss feed of the latest exceptions right on your iphone. You can also modify the views to add more information to the rss item if you need to.
Friday, February 12, 2010
Thinking Sphinx installation, indexing, deploying on Engine Yard
This took a few days, but it's very simple to do and should take minutes. If you're using Engine Yard Cloud, it's not obvious, but it is trivial. The post assumes you have Thinking Sphinx and the Sphinx daemon running on your dev machine and aren't new to either. I used the Thinking Sphinx plugin, as Engine Yard recommends, but I see there is also a gem which my work.
I'm working from memory here, so please let me know if you find any details missing or unclear.
Here's the steps I took:
First you need to clone the engineyard github repository for their chef recipes. This is how engine yard knows you want to have the sphinx daemon running.
I cloned this to my app root, but it probably didn't matter. You don't check it in.
http://github.com/engineyard/ey-cloud-recipes
Once you have this, you edit line 10 in the cookbooks/thinking_sphinx/recipes/default.rb file.
10. run_for_app("app_name") do |app_name, data|
Just add your engine yard app_name here.
Then follow the Installation instructions on the bottom of that page.
Indexing
You'll want to index regularly. For this, I set up a cron job.
cd /data/app_name/current && rake ts:index RAILS_ENV=production
Note: this didn't work for me at first. Not sure why. It could have been a spelling mistake or maybe it had something to do with how I was setting up the deployment. I'll describe deployment next.
Deployment
When you deploy on Engine Yard, you need to stop, index, and start thinking sphinx. To do this, you need to make a "deploy" directory under your rails app_root. For me, I have one file in there "after_restart.rb" and the contents of this file is just this:
sudo "cd #{current_path} && rake ts:stop RAILS_ENV=production"
sudo "cd #{current_path} && rake ts:index RAILS_ENV=production"
sudo "cd #{current_path} && rake ts:start RAILS_ENV=production"
Note: this also didn't work for me right away. I was getting an error that said it could not cd because the directory didn't exist, but I stopped seeing that error. Not sure why this happened.
More information
You may have done some searching to figure around this issue already. When I searched, I found there was a lot of extra or mis- information that made it tough to figure out what to do in production. There are many documents on Engine Yard about this, including the following:
http://www.engineyard.com/blog/2009/5-tips-for-sphinx-indexing/
https://cloud-support.engineyard.com/discussions/questions/265-thinking-sphinx
But these documents all seem to be out of date, at least for a Cloud deployment. Please read these to see if they apply to your needs, but they seem to contain a lot of information that was either old, or did not apply to the standard deployment.
Engine Yard support
When I wrote Engine Yard to ask for a clarification to the online docs, they said that I could submit a ticket to get an answer (this requires the $200+ per month service). It really seems like this should have been a quick answer for them, in the knowledge base somewhere, or worthy of a comment in their online docs. I didn't end up buying the support package, but may in the future.
Also, I posted a question on the community support forum, not the cloud support forum. I didn't realize these were different. The UI is identical and I'm not really sure how I got to the wrong site. Keep that in mind if you're asking for help in the forums.
Anyway, hope this helps someone save some time.
I'm working from memory here, so please let me know if you find any details missing or unclear.
Here's the steps I took:
First you need to clone the engineyard github repository for their chef recipes. This is how engine yard knows you want to have the sphinx daemon running.
I cloned this to my app root, but it probably didn't matter. You don't check it in.
http://github.com/engineyard/ey-cloud-recipes
Once you have this, you edit line 10 in the cookbooks/thinking_sphinx/recipes/default.rb file.
10. run_for_app("app_name") do |app_name, data|
Just add your engine yard app_name here.
Then follow the Installation instructions on the bottom of that page.
Indexing
You'll want to index regularly. For this, I set up a cron job.
cd /data/app_name/current && rake ts:index RAILS_ENV=production
Note: this didn't work for me at first. Not sure why. It could have been a spelling mistake or maybe it had something to do with how I was setting up the deployment. I'll describe deployment next.
Deployment
When you deploy on Engine Yard, you need to stop, index, and start thinking sphinx. To do this, you need to make a "deploy" directory under your rails app_root. For me, I have one file in there "after_restart.rb" and the contents of this file is just this:
sudo "cd #{current_path} && rake ts:stop RAILS_ENV=production"
sudo "cd #{current_path} && rake ts:index RAILS_ENV=production"
sudo "cd #{current_path} && rake ts:start RAILS_ENV=production"
Note: this also didn't work for me right away. I was getting an error that said it could not cd because the directory didn't exist, but I stopped seeing that error. Not sure why this happened.
More information
You may have done some searching to figure around this issue already. When I searched, I found there was a lot of extra or mis- information that made it tough to figure out what to do in production. There are many documents on Engine Yard about this, including the following:
http://www.engineyard.com/blog/2009/5-tips-for-sphinx-indexing/
https://cloud-support.engineyard.com/discussions/questions/265-thinking-sphinx
But these documents all seem to be out of date, at least for a Cloud deployment. Please read these to see if they apply to your needs, but they seem to contain a lot of information that was either old, or did not apply to the standard deployment.
Engine Yard support
When I wrote Engine Yard to ask for a clarification to the online docs, they said that I could submit a ticket to get an answer (this requires the $200+ per month service). It really seems like this should have been a quick answer for them, in the knowledge base somewhere, or worthy of a comment in their online docs. I didn't end up buying the support package, but may in the future.
Also, I posted a question on the community support forum, not the cloud support forum. I didn't realize these were different. The UI is identical and I'm not really sure how I got to the wrong site. Keep that in mind if you're asking for help in the forums.
Anyway, hope this helps someone save some time.
Friday, January 22, 2010
Rails Autocomplete without Ajax (Autocompleter.local)

This was fun - though not easy to find the answer right away.
I wanted to add an autocomplete to a form, but I wanted the suggestions to be local (I didn't want to make any ajax requests, I wanted to use a pre-defined javascript array).
This ended up to real easy.
The scenario here - I have a nested set of objects that an admin may want to give membership privileges to an existing user in their system. The number of existing users, is low (< 100).
For this to work, I had a @member_emails variable accessible to the view. This held all the emails from members that were already members somewhere else in the system.
With this, admins are able to access existing users or add new users quickly.
<%= f.label :user_email, "User's email" %>
<%= f.text_field :user_email, :autocomplete => "off" %>
< div class="auto_complete" id="user_email_auto_complete" >< /div >
<%= javascript_tag("new Autocompleter.Local('membership_user_email', 'user_email_auto_complete', [#{ @member_emails.map{|e| "'" + e + "'" }.join(',') }] , {fullSearch: true, frequency: 0, minChars:1});") %>
Tuesday, January 12, 2010
RubyGem version error: rack(1.0.0 not ~> 1.0.1)
If you see this error - it may be due to the fact you installed Rails 2.3.5 a while ago and you do not have 1.0.1. Even after installing the latest rack gem, this error may persist.
Here are many people with the same issue
http://weblog.rubyonrails.org/2009/11/30/ruby-on-rails-2-3-5-released
I got around this by uninstalling rack and rails 2.3.5. When I reinstalled rails, it included the rack dependency.
Here are many people with the same issue
http://weblog.rubyonrails.org/2009/11/30/ruby-on-rails-2-3-5-released
I got around this by uninstalling rack and rails 2.3.5. When I reinstalled rails, it included the rack dependency.
Saturday, January 02, 2010
Adding Cron Jobs on Engine Yard
This is a bit hard to find on Engine Yard, but it's not tricky.
To get a cron job to run, you need to go to the Dashboard and click on 'crontab' for the running instance. This will show you all Scheduled Jobs - which is probably empty at this point.

In the "Run this command..." field, you want to enter something like this if you're going run a rake task:
cd /data/app_name/current && RAILS_ENV=production rake ns:run_task
This will change directory to the app in question and run the appropriate task from the right place.
Once you have the cron job in place, you need to 'deploy' one more time. Uncheck all your checkboxes and deploy. This won't overwrite your app, but will do other things that are needed to configure the cron job. This is also true if you delete a cron job.
There is currently no way to edit a cron job. You'll have to delete the job and recreate it with changes.
To get a cron job to run, you need to go to the Dashboard and click on 'crontab' for the running instance. This will show you all Scheduled Jobs - which is probably empty at this point.

In the "Run this command..." field, you want to enter something like this if you're going run a rake task:
cd /data/app_name/current && RAILS_ENV=production rake ns:run_task
This will change directory to the app in question and run the appropriate task from the right place.
Once you have the cron job in place, you need to 'deploy' one more time. Uncheck all your checkboxes and deploy. This won't overwrite your app, but will do other things that are needed to configure the cron job. This is also true if you delete a cron job.
There is currently no way to edit a cron job. You'll have to delete the job and recreate it with changes.
Tuesday, December 22, 2009
GMail on Engine Yard
Jump to the end of this if you just want the solution I found, the rest of this includes the trials and errors that didn't work, but may help someone find this page.
We have an application on Engine Yard that is configured to use GMail to send email. Everything works fine in development, but in production, we get the following error:
So, I started searching on Engine Yard to figure out what to do. First I tried to use the Engine Yard search engine - I looked for "GMail", and this is what I got.
https://cloud-support.engineyard.com/faqs/questions/ssmtp
I tried to make these changes (I'm not a Unix expert, by any means), but when I restarted, I didn't see any change. Same error in the projection.log file.
Doing a search on Google for site:engineyard.com "GMail" brings back a couple posts that seemed more specific to GMail, but they didn't work either. Each change was a redeployment and this was looking like it could take some time.
I then contacted @engineyard on twitter. I ususally get a nice response, and I was passed on to one of the support guys at EngineYard. This is what I was sent by email after describing what I was trying to do:
FROM ENGINEYARD SUPPORT...
This is great - I already tried the suggestion from the document, but that didn't work for me so I'll take EY Support's suggestion and get the plugin. Why wasn't that in the documentation?
Anyway, I go to the recommended page and try to the install the plugin that's referenced, but the plugin doesn't install. The page itself is almost 2 years old and the plugin that's mentioned doesn't exist at all. Ugh, apparently EngineYard didn't take the time to make sure it was a good article to refer a customer to.
Back on my own and realizing the plugin approach is recommended, I try searching on google I find the gem on github. OK - still making progress.
http://github.com/openrain/action_mailer_tls
I have the option to install the gem or the plugin. I'll do the gem, as I only need it in production.
To do this on EngineYard, you have to add it through their dashboard UI. But, it turns out they already have the gem hosted on their site. Why didn't support tell me about this? Maybe they didn't know it was there. I assume the gems that are hosted are common and put their intentionally, but now I don't really know for sure.
So, I install the gem, and configure production.rb to require the gem.
I redeploy and am now getting this error when I try to send a password reset email:
Yuck - I didn't add a lot of code to get this error. Doing a little more Googling, I find a thread discussing a similar problem. I get the feeling the Ruby version on EY and this plugin are incompatible.
But one good thing happened here - I stumbled upon another plugin: action_mailer_optional_tls
I search for it and find it on GitHub.
http://github.com/collectiveidea/action_mailer_optional_tls
I tell you, whenever I see Collective Idea's name and Brandon Keeper's face, I have confidence things are going to work. I use many other collective idea gems and read Brandon's blog once in a while, this is a good sign. If this works, I'm going to Holland Michigan to register for a class with Idea Foundary.
And, after yet another deployment to EngineYard ...
It worked! Hard to believe after all that.
And all it ultimately took was the following.
I really appreciate the position that Engine Yard takes - easy to deploy and manage Rails Applications. I saw Tom Mornini talk in Seattle - the vision is great: Engine Yard handles deployment and we (developers) can focus on development and features. It's clear that's where we're headed as an industry, but Engine Yard has plenty of room to improve before it can really own those claims.
We have an application on Engine Yard that is configured to use GMail to send email. Everything works fine in development, but in production, we get the following error:
Net::SMTPUnknownError (530 5.7.0 Must issue a STARTTLS command first. 21sm5842339qyk.4Turns out - Engine Yard is still using Ruby 1.8.6 and 1.8.6 doesn't support SMTP TLS that Google uses.
):
/usr/lib/ruby/1.8/net/smtp.rb:679:in `check_response'
/usr/lib/ruby/1.8/net/smtp.rb:581:in `auth_login'
/usr/lib/ruby/1.8/net/smtp.rb:685:in `critical'
/usr/lib/ruby/1.8/net/smtp.rb:580:in `auth_login'
/usr/lib/ruby/1.8/net/smtp.rb:570:in `__send__'
/usr/lib/ruby/1.8/net/smtp.rb:570:in `authenticate'
/usr/lib/ruby/1.8/net/smtp.rb:410:in `do_start'
/usr/lib/ruby/1.8/net/smtp.rb:377:in `start'
app/models/invitation.rb:13:in `send_invitation_request'
app/controllers/invitations_controller.rb:50:in `create'
app/controllers/invitations_controller.rb:47:in `create'
So, I started searching on Engine Yard to figure out what to do. First I tried to use the Engine Yard search engine - I looked for "GMail", and this is what I got.
https://cloud-support.engineyard.com/faqs/questions/ssmtp
I tried to make these changes (I'm not a Unix expert, by any means), but when I restarted, I didn't see any change. Same error in the projection.log file.
Doing a search on Google for site:engineyard.com "GMail" brings back a couple posts that seemed more specific to GMail, but they didn't work either. Each change was a redeployment and this was looking like it could take some time.
I then contacted @engineyard on twitter. I ususally get a nice response, and I was passed on to one of the support guys at EngineYard. This is what I was sent by email after describing what I was trying to do:
FROM ENGINEYARD SUPPORT...
"The issue is that Net::SMTP doesn't have proper TLS support, so you
can't use it directly with ActionMailer. You have two options. You can
install a plugin for your app to add TLS support following these
directions:
http://www.danielfischer.com/2008/01/09/how-to-use-gmail-as-your-mail-server-for-rails/
Or you can get ssmtp configured on your instance and just set
actionmailer to use :sendmail to send outgoing emails. The latter
option is what our documentation will walk you through. If you're
going to be sending a small volume of email and just want the simplest
setup, using the above link is probably the easiest option.
If you're going to be sending a larger volume of mail (unlikely due to
Gmail's SMTP limits) then I would definitely see about getting either
ssmtp or even a full blown MTA set up on your instance.
Hope that helps."
This is great - I already tried the suggestion from the document, but that didn't work for me so I'll take EY Support's suggestion and get the plugin. Why wasn't that in the documentation?
Anyway, I go to the recommended page and try to the install the plugin that's referenced, but the plugin doesn't install. The page itself is almost 2 years old and the plugin that's mentioned doesn't exist at all. Ugh, apparently EngineYard didn't take the time to make sure it was a good article to refer a customer to.
Back on my own and realizing the plugin approach is recommended, I try searching on google I find the gem on github. OK - still making progress.
http://github.com/openrain/action_mailer_tls
I have the option to install the gem or the plugin. I'll do the gem, as I only need it in production.
To do this on EngineYard, you have to add it through their dashboard UI. But, it turns out they already have the gem hosted on their site. Why didn't support tell me about this? Maybe they didn't know it was there. I assume the gems that are hosted are common and put their intentionally, but now I don't really know for sure.
So, I install the gem, and configure production.rb to require the gem.
I redeploy and am now getting this error when I try to send a password reset email:
ArgumentError (wrong number of arguments (2 for 3)):
/usr/lib/ruby/gems/1.8/gems/action_mailer_tls-1.1.3/lib/smtp_tls.rb:8:in `check_auth_args'
/usr/lib/ruby/gems/1.8/gems/action_mailer_tls-1.1.3/lib/smtp_tls.rb:8:in `do_start'
/usr/lib/ruby/1.8/net/smtp.rb:377:in `start'
app/models/user.rb:123:in `deliver_password_reset_instructions!'
app/controllers/password_resets_controller.rb:27:in `create'
Yuck - I didn't add a lot of code to get this error. Doing a little more Googling, I find a thread discussing a similar problem. I get the feeling the Ruby version on EY and this plugin are incompatible.
But one good thing happened here - I stumbled upon another plugin: action_mailer_optional_tls
I search for it and find it on GitHub.
http://github.com/collectiveidea/action_mailer_optional_tls
I tell you, whenever I see Collective Idea's name and Brandon Keeper's face, I have confidence things are going to work. I use many other collective idea gems and read Brandon's blog once in a while, this is a good sign. If this works, I'm going to Holland Michigan to register for a class with Idea Foundary.
And, after yet another deployment to EngineYard ...
It worked! Hard to believe after all that.
And all it ultimately took was the following.
- Installed action_mailer_optional_tls plugin
- Added ''require 'smtp_tls'" to production.rb
- Modified the :smtp_settings => { ..., :tls => true, ... }
I really appreciate the position that Engine Yard takes - easy to deploy and manage Rails Applications. I saw Tom Mornini talk in Seattle - the vision is great: Engine Yard handles deployment and we (developers) can focus on development and features. It's clear that's where we're headed as an industry, but Engine Yard has plenty of room to improve before it can really own those claims.
Subscribe to:
Posts (Atom)
