Archive for category Ruby and Rails

Heroku error with conditional rb-fsevent gem

Using the guard gem to run tests etc in your Rails app normally requires some form of file system monitoring.

The monitoring will be OS dependant and rb-fsevent is the gem for OSX. This can be added to the Gemfile conditionally with:

gem 'rb-fsevent', :require => false if RUBY_PLATFORM =~ /darwin/i

Unfortunately when you next push to Heroku you are likely to get an error along the lines of:

This is due to Heroku not allowing conditions in the Gemfile, even in the dev group.

The alternative is to put the gem in it’s own group:

And on non Mac systems run bundle install --without darwin (this only needs to be run once, the without setting is remembered for future bundle installs). Then for Heroku run heroku config:add BUNDLE_WITHOUT="development test darwin"

Don’t forget to add –remote remote_name if you are pushing to a remote other than heroku (e.g. heroku config:add BUNDLE_WITHOUT="development test darwin" --remote staging) and don’t forget to merge your amended Gemfile into master before running git push heroku master.

, , , ,

No Comments

Optional Parameters in View Partials

It’s generally good practise to pass variables to view partials using locals rather than littering your code with @variables.

This allows better reuse of the partial.

To make the locals optional, provide default values if they are nil or undefined. I have seen many recommendations to do this with a test for defined?

According to the rails api this will not work and local_assigns.has_key? should be used.

My preference is to use ||=

With 2 caveats:

  • If the default value is nil or false the right hand side of the expression will always be evaluated. I can live with this as I think the any effect on performance will be insignificant.
  • The second caveat is when the default is true. The above statement would convert a local passed in as false to true which is obviously not the intent. Instead, for default values of true, this should be used.

, , , , , ,

No Comments

Rails 3.1 on Heroku, TLDR Version

Create the app

  1. If not installed, install PostgreSQL
  2. rails new app_name -T -d=postgresql
  3. cd app_name/
  4. rvm --create --rvmrc 1.9.2@app_name
  5. rvm rvmrc trust
  6. Edit .Gemfile
  7. bundle install
  8. createuser -P -S -R -d app_name (no to ‘Superuser’ and ‘Create roles’, yes to ‘Create databases’)
  9. rake db:create
  10. Create procfile in app root.
  11. foreman start and check http://0.0.0.0:5000/

Push to Github

  1. Edit .gitignore
  2. git flow init
  3. git add .
  4. git commit -m 'Project skeleton'
  5. Create app_name on Github
  6. git remote add origin git@github.com:JohnPlummer/app_name.git
  7. git push -u origin develop
  8. git push -u origin master

Push to Heroku

  1. heroku create app-name --stack cedar
  2. git flow release start '0.0.1'
  3. git flow release finish '0.0.1'
  4. git push --all
  5. git push heroku master
  6. heroku run rake db:seed
  7. heroku open

, , , , , , ,

No Comments

Installing Postgresql and pgAdmin

 

The default database for Heroku is PostgreSQL and, while you could use SQLite for development and Postgres for production, there are some inconsistencies between the two. Ideally you would use the same version of the database server but currently Heroku uses version 9 for dedicated databases and 8.3 for shared databases and seem to recommend you install the latest version for development.

Install Postgres with Homebrew with brew install postgresql and follow the instructions after the install to initialise a database.

initdb /usr/local/var/postgres

The database server can be set to start at login with

mkdir -p ~/Library/LaunchAgents
cp /usr/local/Cellar/postgresql/9.1.1/org.postgresql.postgres.plist ~/Library/LaunchAgents/
launchctl load -w ~/Library/LaunchAgents/org.postgresql.postgres.plist

But I prefer to add aliases to .bashrc to start and stop the server:

alias pgs='pg_ctl -D /usr/local/var/postgres -l /usr/local/var/postgres/server.log start'
alias pgq='pg_ctl -D /usr/local/var/postgres stop -s -m fast'

Postgres can be managed with the command line utility psql but, as much as I like the command line, I don’t really want to have to write SQL to edit or remove a user role. PgAdmin is a free GUI for Postgres management. Once installed, ensure the Postgres server is running then run pgAdmin and connect to the server.

In the server properties add a name for the connection and add your login as the username.

Server  1

pgAdmin provides the management tools you would expect.

PgAdmin III

 

, , ,

No Comments

Setting up Rails on a Clean Install of Mac OS X Lion

I realise that OSX does not have a registry to clog up but I have just reinstalled Lion on my Macbook Air; probably a hang up from Windows. This is a checklist for installing Homebrew >> Rails.

  1. Install XCode 4.1 (There are issues with the 4.2 compiler and certain rubies and gems)
  2. Install Homebrew
    1. https://github.com/mxcl/homebrew/wiki/installation
    2. /usr/bin/ruby -e "$(curl -fsSL https://raw.github.com/gist/323731)"
  3. Ensure Homebrew apps are in path before Mac apps
    1. export PATH=/usr/local/bin:$PATH or edit /etc/paths
  4. Install Git
    1. brew install git (thanks Brendan)
  5. Install SSH keys
    1. Generate or copy from ~/.ssh from a backup.
  6. Install RVM
    1. https://rvm.beginrescueend.com/rvm/install/
    2. bash < <(curl -s https://raw.github.com/wayneeseguin/rvm/master/binscripts/rvm-installer )
    3. Add [[ -s "$HOME/.rvm/scripts/rvm" ]] && . "$HOME/.rvm/scripts/rvm"  # This loads RVM into a shell session. to bash_profile
    4. Restart shell
    5. Run rvm | head -1
  7. Install latest Ruby and set as default
    1. rvm install 1.9.3 (make sure you are using Xcode 4.1)
    2. rvm --default use 1.9.3
  8. Install Rails
    1. gem install rails

I keep all my .config files in Dropbox and run a bash script to create aliases in my home folder.

 

, , , , , , , ,

4 Comments

Rails default scripts and jquery-rails

I recently had an issue in a (3.0.7) rails app where link_to some_path, :method => :post was calling the action associated with GET, this was caused by not having a link to jquery_ujs.js (I’m using jquery so don’t want rails.js) in my html output.

Googling turns up a number of suggestions to add jquery_ujs.js and the other jquery script files to the default javascripts by amending config/application.rb. This works ok but it’s not ideal as you probably want minified versions of the files in production and non minified in development.

Digging into the jquery-rails gem reveals railtie.rb:

This sets the default scripts before config/application.rb is run. Unfortunatley with application.rb as it is generated if you run rails new with the -J switch (you probably don’t want prototype if you plan to use jquery) these defaults are overridden. Commenting out

From config/application.rb allows the jquery-rails scripts to load but doesn’t allow you to add to the defaults. I did submit a pull request amending the railtie to run it’s code on before_initialize (after config/application.rb has been run). This allowed defaults to be set and the jquery defaults appended but as Indirect pointed out, this prevents you overriding the jquery defaults in application.rb.

The way to add your own scripts is to append them to the defaults using:

This works but there are 2 related issues; jquery_ujs.js should be the last script loaded as it needs to hook into any submission events for ajax elements and it can’t unless scripts for those events are loaded before it.

With the solution above we have application.js (added by Rails) and our scripts loaded after jquery_ujs.js. Our scripts can be placed first by changing application.rb to:

This still leaves application.js loaded after jquery_ujs.js but that should be fine as long as there aren’t any submission events scripted in it.

Using the railtie to set the default scripts then allowing you to append or override these defaults is a neat solution by the jquery-rails gem, unfortunately it doesn’t seem that many know about it as there seems to be a lot of advice to add the jquery script files directly in config/application.rb. It looks as these issues will go away in Rails 3.1 anyhow.

, , , , , ,

No Comments

Rails Autoload and Ruby Require

Rails methods of locating and loading files is mostly based on convention but is built on top of Ruby’s methods.

Ruby

The basic way to tell a ruby to load a file is to require it, e.g. require some_file will load some_file.rb if the file has not already been loaded. load some_file.rb will load the file (and execute any code) regardless of if the file has been loaded already.

In 1.9.2 the path that Ruby looks for these files includes:

  • A number of directories in your Ruby install.
  • Directories of any gems loaded
  • Directories you have added to $LOAD_PATH, Rails adds a number of app directories to this variable. To see exactly what is added run puts $LOAD_PATH in both irb and a rails console.

To require a file relative to the file doing the requiring use require_relative some_directory/some_file.

Require and load both load the file when execution reaches the relevant require or load call, autoload some_file will not load the file until a module in the file is called.

Rails

In addition to adding  app directories to the $LOAD_PATH, Rails loads all *.rb files in /config/initializers/ when the application starts.

Rails also has an autoload_path, If Rails comes across an uninitialized constant it will check any paths in autoload_path for a file matching the name of the constant e.g. when execution hits an unrecognized constant MyConstant it will check for a file called my_constant.rb in any paths included in autoload_paths.

The autoload_path in 3.0.7 is empty, to add the lib directory to it, add config.autoload_paths += %W(#{config.root}/lib) to config/application.rb.

If the module name does not match the file name then the file will need to be required in the normal way.

Rails also allows you to require a file with require_dependency. Require_dependency works exactly like Ruby’s require except, in development mode, it reloads the file when a view is refreshed allowing you to make changes to the required file and see them by refreshing the browser.

Incude and Extend

There seems to be some confusion between require and include/extend but they are totally unrelated. Require and similar deal with loading files from the filesystem. Include and extend deal with including code from one module in another. A class the includes a module allows an instance of the class to access code from the included module. A class that extends allows the class to access code from the module called.

 

 

 

, , , , , , , , , , ,

No Comments

Launching irb from vim

You can run irb from vim with the command !irb.

Running !irb -r % should run the current file in irb then leave irb open. Unfortunately ruby 1.9.2 removed the current directory from the load path which causes this to fail. You could construct a path but it is easier to add the current directory back in, especially if you are using irbtools which does it for you.

Once irbtools are installed add:

map <F2> <ESC>:w<CR>:!irb -r %<CR>

to .vimrc.local which will write then load the current file into irb.

Edit: I was getting some weirdness with the irb prompt with irbtools so I have removed it and added

$: << ‘.’  if RUBY_VERSION >= ’1.9.2′

to my .irbrc file to add the current directory to the load path.

 

, , , , ,

No Comments

Rails, Compass, HTML5 Boilerplate and Heroku

Overview

HTML5 provides some great functionality but also, potentially, some headaches. HTML5 Boilerplate is a template which aims to solve the various cross-browser differences.

There is a gem to use HTML5 Boilerplate in a rails app which uses Compass to build the CSS. Using Compass on Heroku requires a small workaround as Heroku limits where an app can write to.

Setup

For a new Rails App: Follow the process in prior post on setting up a new project.

After the rspec and cucumber installs run

When asked, select yes for change of SASS location but no to change of CSS location

Carry on through prior post (but don’t install jquery as that is part of the HTML5 Boilerplate)

Create a home controller script

Delete the /public/index.html and the app/views/layouts/application.html.erb files

Set the root in the config/routes.rb

Fix the annoying Rails 3.0.5 bug by amending the javascript expansions line in config/application.rb to

The app should now run locally using hml5-boilerplate, compass, and haml.

Heroku

But not on Heroku, to run on Heroku the css files need to be written to a tmp directory as that is the only folder the app can write to.

In config/compass.rb change the css_dir line to

Change config/initializers/compass.rb to

This should allow the app to run locally and hosted on Heroku.

To push to Heroku follow these instructions.

In summary, once you have your SSH keys set up:

, , , , , , , , , , , , ,

No Comments

Authentication With Devise Using Username – Configuration

Devise is probably the most popular authentication gem for Rails apps but, in the current version (1.1.5), doesn’t fully support logging in with a username and password. This Railscast walks through how to add a username to the model and use username as the key to log in with but 1.1.5 will still require email as the key to unlock an account, reset a password or resend confirmation instructions.

Version 1.2rc adds the ability to use username as a key for unlocking and resetting and I have submitted a patch to use username as a key when resending confirmations which will hopefully make it into a 1.2.x release. I have included my fork in the Gemfile below and will re-edit this post as future versions of devise are released.

My patch has now been included in 1.2rc so use the https://github.com/plataformatec/devise.git url in your gemfile.

I’ll keep this terse and include my workflow

  1. Create a new Rails app.
  2. git flow feature start authentication
  3. Amend Gemfile:

    I have included hpricot and ruby_parser gems as they are required by devise for haml views. Note that the devise gem is pointing to my fork. I’ll amend this as soon as the patch gets included.
  4. bundle install
  5. rails g devise:install
  6. Make the three changes specified by generator:
    1. Set the action_mailer host in development.rb, test.rb, and production.rb.

      (The production host should obviously point to your production host.)
    2. Uncomment and amend the root route in routes.rb.

      This is also a good time to delete public/index.html.
    3. Add flash messages to the application layout. I prefer haml so I delete application.html.erb and add the following application.html.haml.
  7. This is a good time to commit with git add -A and git commit -m "Installed devise."
  8. Amend devise.rb.
  9. rails g devise user
  10. Amend user.rb.

    Note I can’t use the validatable module as that would require emails to be unique so I will have to write my own validation later.
  11. Amend ####_devise_create_users.rb.

    The most important points are to add the user column and index and remove unique from the email index.
  12. rake db:migrate
  13. rake db:test:clone
  14. Generate the devise views so we can amend them. rails g devise:views -e:haml (skip the -e:haml to generate erb views.) I will drive the view changes with tests later.
  15. Another good point to commit and take a break. git add -A and git commit -m "Configured devise"

 

Changing the views is just a matter of replacing :email with :username but I will do that with some cucumber tests in a future post.

, , , , , , , , , , , , , , , , , , , , , , , , , ,

No Comments