SyntaxHighlighter

Thursday, December 09, 2010

heroku pgbackups - Unknown command

This is a short one. If you try to access Heroku PGBackups with an old version of the gem, you'll get something like this...

$ heroku pgbackups
Unknown command. Run 'heroku help' for usage information.

If you run

$ heroku info

You won't see the pgbackups command in the list, either.

You just need to update the gem.
gem update heroku

Tuesday, October 26, 2010

Heroku Read-Only file system

I recently got this error on an app I was pushing to Heroku for the first time:

==> dyno-687840.log (crash) <==
/usr/ruby1.8.7/lib/ruby/gems/1.8/gems/bundler-1.0.0/lib/bundler/definition.rb:184:in `initialize': Read-only file system - /disk1/home/slugs/101931_3c1385b_c5a8-4204ff34-8821-47c1-a8e8-b951ce5a6c3f/mnt/Gemfile.lock - Heroku has a read-only filesystem. See http://docs.heroku.com/constraints#read-only-filesystem (Errno::EROFS)

The reason was because I'd checked in the tmp directory and it's contents. Woops.

Wednesday, September 01, 2010

Consulting Firm vs. Startup

Ubermind I just started working for an iPhone App and Rails web application consulting firm in Seattle called Ubermind. They are filled with really great people and the atmosphere is easy to work in. I just started this week and I'm already struck by the differences between startups and consulting firms.

I've been in startups for the last 15 years. And, until this week, I hadn't realized how startups are emotionally different from other businesses. In a startup, you really never get a chance to stop and look at what you've done. You never get the feeling really being finished, you're always planning that next feature.

The atmosphere is very different at a consulting firm. You don't tend to spend an entire day working on a client's projects directly, so the other time you have is spent analyzing new projects, tools, frameworks, testing environments, etc. You actually get time to research new technology, and each new client brings completely new needs that make you consider new solutions.

This is a significant difference. Releases in consulting firms are major milestones. The project is shipped and you are done. Employees are shifted to other projects. The cycle starts over again. The next time you may choose to use PostgreSQL instead of MySQL, or try Rails 3.0.

With new technology being introduced so rapidly in web development, I felt like I was falling behind when I worked at a startup, we picked our technology and approach and stuck with it. I don't feel that way in a consulting firm.

In a startup, where you're racing to prove features are needed, it's harder to rationalize all the tests that you'd want to have. In consulting, it's encouraged and absolutely necessary. It's an important part of the process and I can now see why test driven development is so widely recommended. It's usually recommended by those working in consulting firms.

I have wondered why all the speakers (and published authors) at Rails conferences are from consulting firms. Most of the critical gems I use are from consultants or consulting firms. Broad-use innovation comes from consulting. Firms tend to solve common problems like authentication, content management, file uploading, delayed jobs, to name a few.

If consulting considers solutions that have broad use, startups tend to develop a proprietary solution for the deeper problem - a custom content management system, or a custom search tool.

For any of you thinking about Consulting VS. Startups you might give this some thought to see where you fall. I love startups and will always be involved with new product ideas in some way, but if you want more opportunity to learn broadly and try new technology first, I'd recommend consulting. Especially in the Rails community, that's where the innovation is happening the fastest.

Thursday, August 26, 2010

Amazon Web Developer Interview

There are a lot of things to talk about to test technical skills in an Rails web developer interview. There are many Rails topics that could be covered - just to name a few, topics could include Routes, Migrations, Testing, Fixtures, Gems/Plugins, Authentication, 3rd Party Tools and services, Named Scopes, Rails 3.0. Nested Attributes, Observers, Counter caches, Tagging, Delayed Worker Jobs, Email.

The nice thing about Rails, as it is open source and quite elegantly architected, it's easy to also discuss common web design patterns at a higher level - like REST, Model View Controller (MVC), Authentication, DB performance, Querying strategies, Caching strategies, etc. without talking about Rails specifically.

I interviewed with Amazon recently - it was a phone interview for a Senior Ruby on Rails Developer. I talked with one of the members of the team that uses Ruby on Rails for their app. Rails at Amazon is pretty rare and I was intrigued.

The phone interviewer had two questions for me. The questions weren't about Web Development or Ruby on Rails, but I expected that. Amazon is known to be consistent with their technical interviews - they ask about big O notation, memory usage, performance, etc. Here's what we talked about in my interview.

Implement a Fibonacci method so f(0) = 0, f(1) = 1, and f(n) = f(n-1) + f(n-2)

def f(n)
n <= 1 ? n : f(n-1) + f(n-2)
end

def f(n)
a = 0; b = 1
n.times { a, b = b, (a + b) }
return a
end


After the methods were written and I sent them to the interviewer by email, we discussed the Order (big O notation) of the methods. The order of the second Fibonacci method is linear the first method's order is exponential.

We then had a discussion about the following...

Given an array of integers, return all integers in a particular range.

Web developers hardly ever write algorithms like these in their daily work and the questions may seem unrelated or outdated. If you did write a method like this, you'd want it to be readable and maintainable for other developers and could give a little on performance and memory. We discussed the performance issues and memory usage for these methods. In practice, performance issues for a web application are often due to slow queries or slow web pages and multiple requests to the server.

Keep in mind - Amazon technical interviews are not meant to gather your practical experience for the job, they are intended to test your CS fundamentals and the questions provide a standard that all interviewees can be measured against. Amazon is comparing apples to apples this way, even if they aren't necessarily the skills you'd use on the job.

If you pass the technical phone interview, you will be invited in for a longer set of interviews, and those tend to cover job related skills.

If you are interviewing at Amazon, I recommend you look over the Amazon interview questions posted on Glassdoor. They have many examples that will give you a good idea of the questions and how to answer them.

Tuesday, August 03, 2010

Permission denied for http://talkgadget.google.com to call method Location.toString on http://www.google.com/

I keep getting these javascript errors -

Permission denied for http://talkgadget.google.com to call method Location.toString on http://www.google.com/

GM80 is not defined

They show up in firebug, and appear to be due to google analytics. Looking on Google, I see nothing - surprisingly, the phrase "GM80 is not defined" is not even indexed (as of today - update, it took Google just a few minutes for this post to be indexed), but it's hard to believe no one else runs into this.

It doesn't seem to cause any real problems, just throws errors once in a while.

Wednesday, June 30, 2010

MySql inconsistency when using Group By and Order By


I have a Ruby on Rails application where my development environment MySQL version is...

Server version: 5.0.45 MySQL Community Server (GPL)

And the production server (at Engine Yard) is...

Server version: 5.0.51-log Gentoo Linux mysql-community-5.0.51

This SQL satement:

SELECT id,name FROM properties GROUP BY id ORDER BY name DESC LIMIT 10;


Is sorted in Development, but not in Production (in production the results are sorted by ID)

Wednesday, May 19, 2010

Loading a partial with a Javascript Helper in Ruby on Rails

Sometimes, you have content that you want reloaded whenever someone goes to a page - even if they hit the 'Back' button. I had a drop down that I was using for navigation on Placeforce, and I wanted it to update even if they hit back. The drop down was your standard select tag, with a simple onchange event that would navigate the user to another page.

When you hit back, the select was still where it was left. This is good for forms, but not good in this case.

Here's a simple rails example to help you out:

<%= update_page_tag { |page|
page[:content_div].replace_html( ... )
} %>


The "..." (or whatever html your generating) is what you're using now. Just wrap that with the update_page_tag { |page| page[:content_div].replace_html(...) }

Simple, took just a few minutes. I wasn't familiar with 'update_page_tag', so thought I'd share.

Thursday, May 06, 2010

Placeforce was officially launched

It's been 6 months of development, and Placeforce.com is finally released. I just added a tour to explain how placeforce works, and added links to sign-up, use a credit card, and get a free trial.

It's been a very interesting 6 months.

Back in November 2009, when we started, we had plans to release by February (3 months). We were targeting the Property Management industry, and trying to create a tool that Property Managers could use to allow their managers, building owners, and vendors to communicate and manage tasks and recurring maintenance. It was an ambitious project, but as we started to get feedback in January and February, we realized the vendor (the Window Cleaner, Plumber, Inspector, Electrician, etc) had a very clear need that we could solve first. Even for Property Management companies, they usually had a service department to handle handy-man projects, cleaning, etc. It changed our focus a little bit, for now.

We realized the tools that were being used by this group were completely substandard, and tended to focus around just one part of the task - Outlook or Google Calendar for scheduling, Appointment-plus sometimes, Quickbooks for billing, lots of rigged-together MSExcel solutions etc. Nothing, usually, for collecting or storing leads. Lots of paper laying around the office. Just a hodge-podge of tools and the owners of these companies were desperate for a solution. This also allowed us to simplify our story and focus on features that provide clear value.We decided to concentrate on two things -
  1. Getting new customers
  2. Servicing those customers
Placeforce centers around scheduling tasks for properties - this includes photos, maps, documents, geo-location, etc. Having a easy access to property information can greatly improve the efficiency of your business - take a look at an article my brother, Eric recently posted on our blog - Three Keys to Managing Better with Property Information. Placeforce has potential for a strong mobile component, as well (coming soon, hopefully). And, unlike other tools out there, we did not build a generic tool for any industry, we're specific to property-based service companies. This narrows our potential customer pool, but allows us to really focus on what our true customers need.

Saturday, March 20, 2010

ActiveRecord::SerializationTypeMismatch (search_fields was supposed to be a Hash, but was a String):

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.

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.

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.

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.

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.