Sandbox
From MathsDept
Contents |
About
This page details some standard elements of Rails development at SIT.
Versions
The Rails setup at SIT are running these versions:
- Rails 2.0.2
- Ruby 1.8.6 or 1.8.7
- Apache 2
- Passenger (mod_rails for Apache) 2.2.2+
Setting Up A New Rails App
Generate a new Rails application
rails app-name cd app-name
Remove default index files
cd app-name rm public/index.html rm public/images/rails.png
Rails and Subversion
Setting up
Import local Rails project to the subversion repository, where {app-name} is replaced with a name for the project
cd app-name svn mkdir https://subversion.sfac.auckland.ac.nz/svn/UoA.Science/{app-name} svn import https://subversion.sfac.auckland.ac.nz/svn/UoA.Science/{app-name}/trunk
Remove the generated Rails application and check out the imported project from svn
cd .. rm -rf app-name svn checkout https://subversion.sfac.auckland.ac.nz/svn/UoA.Science/{app-name}/trunk app-name
Set svn to ignore the database.yml, log and tmp files
Don't check into subversion any file that has sensitive information including passwords, such as the database.yml file. Log and tmp files don't need to be version controlled.
Remove config/database.yml from subversion and any other sensitive information. (After performing these steps you'll need to re-add the file, svn will ignore it at this point).
svn remove config/database.yml svn propset svn:ignore "database.yml" config/ svn update config/ svn commit -m "Ignoring database.yml"
Remove the log files
svn remove log/* svn commit -m "removing all log files from subversion"
Ignore the log files when they are re-created
svn propset svn:ignore "*.log" log/ svn update log/ svn commit -m "Ignoring all files in log/ ending in .log"
Ignore the tmp directory with all its content (cache, sessions, sockets)
svn remove tmp/* svn propset svn:ignore "*" tmp/ svn update tmp/ svn commit -m "Ignoring all files in tmp/"
ActiveRecord Extensions
ActiveRecord:Extensions is a library that extends ActiveRecord's find() method to make it a lot more user-friendly, and allows mass imports of data. It's recommended to include this library in every Rails app you create.
Installation
Note, version 0.7 should be used for Rails 2.0.2 apps. To install:
cd /path/to/rails/app script/plugin install http://arext.rubyforge.org/svn/tags/ar-extensions-0.7.0
Usage
Extensions to the ActiveRecord find() method:
<source lang="ruby"> Post.find(:all,
:conditions=> {
:rating_ne => 4, # rating != 4
:rating_gt => 4, # rating > 4
:rating_lt => 4, # rating < 4
:author_contains => "Zach", # author like '%Zach%'
:author_starts_with => "Zach", # author like 'Zach%'
:author_ends_with => "Dennis", # author like '%Zach'
:published_at => (Date.now-30 .. Date.now), # published_at BETWEEN xxx AND xxx
:rating => [ 4, 5, 6 ], # rating IN ( 4, 5, 6 )
:rating_not_in => [ 7, 8, 9 ] # rating NOT IN( 4, 5, 6 )
:content => /(a|b|c)/ # REGEXP '(a|b|c)'
}
) </source>
Importing data:
Note: There's a bug in the 0.7.0 version of ar-extensions where validations will be called before importing, but not other before_ or after_ callbacks (like before_save). The bug has been patched in the Web Booker so you should copy the linked file of that application's ar-extensions plugin and replace before trying to do imports. Search for "luke edit" to read comments on the patch.
<source lang="ruby">
- import() can take an array of ActiveRecord objects
imports = [
ModelObject.new(:name => 'first'), ModelObject.new(:name => 'second')
]
- call import() to attempt to save all records in one go
ModelObject.import(imports)
- call import() and assign the result to see if there were errors
result = ModelObject.import(imports) result.failed_instances # an array of all ModelObjects that failed to be saved </source>
Security
Security.
Don't check in database.yml or other sensitive information to subversion
config/database.yml contains the database connection details for your application. Make sure that this file, and any file containing passwords, are not checked in to the repository. See the Rails and Subversion wiki page for how to tell subversion to ignore files.
Set robots.txt
As a security step for admin applications, add the following lines to public/robots.txt to ask searchbots not to index the site if ever the authentication layer was to fail.
User-agent: * Disallow: /
Best Practices
Vendored Gems
If your Rails application requires particular gems to be installed then consider the vendor everything approach, where gems get unpacked into the vendor directory of the Rails application, making deployment simpler.
This will work for all gems that don't need compiling (most of them).
<source lang="bash">
- from rails application root
mkdir vendor/gems cd vendor/gems gem unpack [name of gem] </source>
Inside the existing Rails::Initializer block in config/environment.rb of your Rails application, add the following. This will add all libraries in vendor/gems to the Rails load_path making them available to the application:
<source lang="ruby">
Rails::Initializer.run do |config|
# ...
config.load_paths += Dir["#{RAILS_ROOT}/vendor/gems/**"].map do |dir|
File.directory?(lib = "#{dir}/lib") ? lib : dir
end
# ...
end </source>
Use shared models and config files
Folders and files that are shared between a number of Faculty of Science Rails applications have their own svn repository.
These can be included into any Rails application to keep things DRY.
To use
The following is a duplicate of information of the README file in the rails-shared-resource repository.
Add this repository as an external svn repository.
From the Rails application root (note the '.' at the end is important):
<source lang="bash"> svn propset svn:externals "shared https://subversion.sfac.auckland.ac.nz/svn/UoA.Science/rails-shared-resources/" . svn commit -m 'adding svn:externals to rails-shared-resources' svn update </source>
In config/environment.rb on your Rails application, add the following lines near the bottom of the file:
<source lang="ruby">
- require all models in the shared folder
Dir["#{RAILS_ROOT}/shared/models/**"].each do |model|
require model
end
- require all files in the lib shared folder
Dir["#{RAILS_ROOT}/shared/lib/**"].each do |library|
require library
end </source>
If you just want to select certain things to load from a directory, use:
<source lang="ruby">
- require these models in the shared folder
models = %w(booking_event_shared ip_shared) Dir["#{RAILS_ROOT}/shared/models/**"].each do |model|
if models.include?(File.basename(model, ".rb")) require model end
end </source>
To inherit all methods of a shared model, change your normal Rails model from:
<source lang="ruby"> class [ModelName] < ActiveRecord::Base </source>
to:
<source lang="ruby"> class [ModelName] < Shared::[ModelName] </source>
All methods in the shared model will be inherited and available. You can add application-specific methods to the regular model as normal, including overwriting methods that were in the shared model to redefine them.
Important notes
- Changes to shared files should be tested between apps after having been committed to the shared repository.
- Only put generic methods in the shared models. Put things specific to your application in the regular Rails model.
Example use
An example shared model in the shared/models folder
<source lang="ruby"> module Shared
class Ip < ActiveRecord::Base
def self.say_hello
"hello"
end
end
end </source>
Your regular Ip model, set to inherit from the shared model
<source lang="ruby"> class Ip < Shared::Ip
def self.say_hi "hi" end
end </source>
Will now have two class methods available, as well as interfacing with ActiveRecord
<source lang="ruby"> Ip.say_hello # => "hello" Ip.say_hi # => "hi" Ip.find(:first) # => and all ActiveRecord methods </source>
Write tests
Rails has a test framework built in, which can automate testing of all your models, controllers and views.
See the Unit and Functional Testing for Rails wiki page for more info.
Use rake to write cron tasks
rake is a way of writing task scripts for your Ruby code. Rails comes with a lot of inbuilt rake tasks, and you can write your own. To see the list of rake tasks for any Rails application:
<source lang="bash"> cd /path/to/rails/app rake -T </source>
To execute a rake task from the command line you type:
<source lang="bash">
- from the rails application root:
rake api:task_name </source>
To set a rake task up as a cronjob you can use the following format and add it to the crontab:
<source lang="bash"> 0 5 * * * cd /var/wwwdata/applications/wbapi && /usr/bin/rake RAILS_ENV=production api:send_reminders </source>
The above will cd to the Rails application, and run the equivalent of rake RAILS_ENV=production api:send_reminders.
To see some existing rake cronjobs that have been set up, ssh to www7, sudo to bash and crontab -l, and also see the Web Booker API/Developer notes.
For a good tutorial on rake tasks and Rails see this Ruby on Rails and Rake tutorial.
Add a Readme file
Add a file called README.app to the root of the Rails application with a link to the SIT wiki page for the application, development and production sites, svn repository and any other relevant notes. Keep most of the notes in the application wiki page.
Optimisation
SQL Query Reviewer
SQL Query Reviewer plugin inserts a div with plenty of debugging information and recommendations for speeding up slow database queries.
Date optimisation gem
The Ruby Date library is quite slow, and sites that extensively use Ruby Date types (like the Web Booker) might benefit from using the date-performance gem. After requiring it in your config/environment.rb it should seamlessly replace the normal Ruby Date library.
Installation:
<source lang="bash"> gem install date-performance --source=http://tomayko.com </source>
Use:
<source lang="ruby"> require 'date/performance' # or, require 'date/memoize' </source>
Resources and Links
Security
- Securing Rails Applications
- Is Your Rails App Safe From Mass Assignment?
- Tarantula - Plugin that can test your application's security (requires
htmlentitiesgem to be installed)
Best Practices
Debugging
Optimisation
- 4 Steps to Detect and Fix Slow Rails Requests
- 5 Tips to Scale Your RoR Application
- Google Code Optimising web sites

