Register now and start sharing your code snippets.
-->

How to install and use the restful_authentication Rails plugin

Ruby posted 7 months ago by christian

This is an adaptation of the restful_authentication screencast by Ryan Bates, which has an issue with Rails 2.0.3 that throws the following error:

   1  NameError (uninitialized constant SessionsController):
   2      /usr/local/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:266:in `load_missing_constant'
   3      /usr/local/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:453:in `const_missing'
   4      /usr/local/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:465:in `const_missing'
   5      /usr/local/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/inflector.rb:257:in `constantize'

Installing the restful_authentication plugin

   1  script/plugin source http://svn.techno-weenie.net/projects/plugins/
   2  script/plugin install restful_authentication

Generating the model and controller

   1  script/generate authenticated user sessions

Now run the migration:

   1  rake db:migrate

Configure routing

Open config/routes.rb and add the following routes:

   1  map.resources :users
   2  map.resource  :session
   3  
   4  map.signup '/signup', :controller => 'users', :action => 'new'
   5  map.login  '/login', :controller => 'sessions', :action => 'new'
   6  map.logout '/logout', :controller => 'sessions', :action => 'destroy'

Include restful_authentication in ApplicationController

First remove these lines from the users and sessions controllers:

   1  # Be sure to include AuthenticationSystem in Application Controller instead
   2    include AuthenticatedSystem

Now include restful_authentication in the application controller:

   1  class ApplicationController < ActionController::Base
   2    include AuthenticatedSystem

Integrate restful_authentication with your views

First let’s create a controller and view by executing the generate script:

   1  script/generate controller home index

Modify index.html.erb as follows:

   1  <h1>Welcome</h1>
   2  
   3  <% if logged_in? %>
   4    <p><strong>You are logged in as <%=h current_user.login %></strong></p>
   5    <p><%= link_to 'Logout', logout_path %></p>
   6  <% else %>
   7    <p><strong>You are currently not logged in.</strong></p>
   8    <p>
   9      <%= link_to 'Login', login_path %> or
  10      <%= link_to 'Sign Up', signup_path %>
  11    </p>
  12  <% end %>

Start Rails and access your application. If needed, add the following to config/routes.rb to make the home controller the default:

   1  map.root :controller => "home"

Login, sign up and logout should work.

Tagged rails, ruby, authentication, restful_authentication

Using backgroundrb to execute tasks asynchronously in Rails

Ruby posted 8 months ago by christian

Draft…

Planning on using BackgroundDRB? Take a long look at the alternatives first

Ask yourself, do you really need a complex solution like BackgroundDRB? Most likely you don’t, so use a simple daemonized process instead, see this snippet about the daemons gem for more information.

Heck, even a simple Ruby script run by cron every 5 minutes will be more stable than BackgroundDRB and require less work.

Even if you really need to process a lot of data asynchronously in the background, I wouldn’t recommend BackgroundDRB, it’s riddled with bugs and unstable in production, so use the BJ plugin instead.

Anyway, continue reading if you want to use BackgroundDRB…

Installing the prerequisites:

   1  $ sudo gem install chronic packet 

Installing backgroundrb

   1  $ cd rails_project
   2  $ git clone git://gitorious.org/backgroundrb/mainline.git vendor/plugins/backgroundrb

You can also get the latest stable version from the Subversion repository:

   1  svn co http://svn.devjavu.com/backgroundrb/trunk  vendor/plugins/backgroundrb

Setup backgroundrb

   1  rake backgroundrb:setup

Create a worker

   1  ./script/generate worker feeds_worker

   1  class FeedsWorker < BackgrounDRb::MetaWorker
   2    set_worker_name :feeds_worker
   3    
   4    def create(args = nil)
   5      # this method is called, when worker is loaded for the first time
   6      logger.info "Created feeds worker"
   7    end
   8    
   9    def update(data)
  10      logger.info "Updating #{Feed.count} feeds."
  11      
  12      seconds = Benchmark.realtime do
  13        thread_pool.defer do
  14          Feed.update_all()
  15        end
  16      end
  17  
  18      logger.info "Update took #{'%.5f' % seconds}."
  19    end
  20  end

Starting backgroundrb

First configure backgroundrb by opening config/backgroundrb.yml in your editor:

   1  :backgroundrb:
   2    :ip: 0.0.0.0
   3  
   4  :development:
   5    :backgroundrb:
   6      :port: 11111     # use port 11111
   7      :log: foreground # foreground mode,print log messages on console
   8  
   9  :production:
  10    :backgroundrb:
  11      :port: 22222      # use port 22222

Next, start backgroundrb in development mode:

   1  ./script/backgroundrb -e development &

Call your worker

From the command line:

   1  $ script/console
   2  Loading development environment (Rails 2.0.2)
   3  >> MiddleMan.worker(:feeds_worker).update() 

When things go wrong

Asynchronous programming is complex, so expect bugs…

Rule #1 know who you’re calling.

If you give your MiddleMan the wrong name of your worker, he’ll just spit this crap at you:

   1  You have a nil object when you didn't expect it!
   2  The error occurred while evaluating nil.send_request
   3  /usr/local/lib/ruby/gems/1.8/gems/packet-0.1.5/lib/packet/packet_master.rb:44:in `ask_worker'
   4  /Users/christian/Documents/Projects/xxx/vendor/plugins/backgroundrb/server/lib/master_worker.rb:104:in `process_work'
   5  /Users/christian/Documents/Projects/xxx/vendor/plugins/backgroundrb/server/lib/master_worker.rb:35:in `receive_data'
   6  /usr/local/lib/ruby/gems/1.8/gems/packet-0.1.5/lib/packet/packet_parser.rb:29:in `call'
   7  /usr/local/lib/ruby/gems/1.8/gems/packet-0.1.5/lib/packet/packet_parser.rb:29:in `extract'
   8  /Users/christian/Documents/Projects/xxx/vendor/plugins/backgroundrb/server/lib/master_worker.rb:31:in `receive_data'

So for example this command would generate the above mentioned error:

   1  MiddleMan.worker(:illegal_worker).update() 

It’s always nice to see a cryptic error messages such as this, it really deserves an award.

Check for bugs and bug fixes

git mainline commits

Going to production

Starting the daemon:

   1  ./script/backgroundrb -e production start

Configuring your task to run periodically

The following example makes backgroundrb call the FeedsWorker’s update method once every 15 minutes:

   1  :production:
   2    :backgroundrb:
   3      :port: 22222      # use port 22222
   4      :lazy_load: true  # do not load models eagerly
   5      :debug_log: false # disable log workers and other logging
   6  # Cron based scheduling
   7  :schedules:
   8    :feeds_worker:
   9      :update:
  10        :trigger_args: * */15 * * * *
  11        :data: "Hello world"

At the time of writing, the cron scheduler seems to be broken, so I prefer hard-coding the interval in the worker’s create method:

   1  def create
   2             add_periodic_timer(15.minutes) { update }
   3           end

If using Vlad or Capistrano, it’s also a good idea to fix script/backgroundrb by changing these lines:

   1  pid_file = "#{RAILS_HOME}/../../shared/pids/backgroundrb_#{CONFIG_FILE[:backgroundrb][:port]}.pid"
   2  SERVER_LOGGER = "#{RAILS_HOME}/../../shared/log/backgroundrb_server_#{CONFIG_FILE[:backgroundrb][:port]}.log"

Resources

Backgroundrb homepage

Backgroundrb best practices

Backgroundrb scheduling

Debugging backgroundrb

Backroundrb’s README

topfunky’s messaging article

Tagged backgroundrb, rails, ruby, distributed, messaging

Installing/compiling and using git with Ruby on Rails (on Mac OS X Leopard and Debian Linux)

Shell Script (Bash) posted 8 months ago by christian

Git is a good alternative to Mercurial, and of course SVN or CVS if you’re still using stone age tools, so in this post I’ll show you how to compile, install and use git with Rails.

Installing git on Mac OS X

First compile and install git:

   1  cd /usr/local/src
   2  wget http://kernel.org/pub/software/scm/git/git-1.5.4.4.tar.bz2
   3  tar jxvf git-1.5.4.4.tar.bz2
   4  cd git-1.5.4.4
   5  make prefix=/usr/local all
   6  make prefix=/usr/local test && echo $?
   7  sudo make prefix=/usr/local install

Installing git on Debian

On a Debian installation install git by first executing the following commands:

$ sudo apt-get install git-core

Note that the package name is git-core not git.

If you want the latest and greatest version, you first need to install the dependencies (note that you can leave out tk and expat):

   1  sudo apt-get install curl
   2  sudo apt-get install libcurl3
   3  sudo apt-get install libcurl3-dev
   4  sudo apt-get install tk8.4
   5  sudo apt-get install cpio expat
   6  sudo apt-get install zlib
   7  sudo apt-get install build-essential
   8  sudo apt-get install zlib1g-dev 
   9  sudo apt-get install asciidoc
  10  sudo apt-get install xmlto

Then compile and install:

   1  NO_EXPAT=yes NO_SVN_TESTS=yes NO_IPV6=yes NO_TCLTK=yes make -j2 prefix=/usr all
   2  NO_EXPAT=yes NO_SVN_TESTS=yes NO_IPV6=yes NO_TCLTK=yes make -j2 prefix=/usr install

Configuring git

Run these commands to tell git your name and email:

   1  git config --global user.name "u name"
   2  git config --global user.email x@x.com

Otherwise, you might get this error:

   1  *** Environment problem:
   2  *** Your name cannot be determined from your system services (gecos).
   3  *** You would need to set GIT_AUTHOR_NAME and GIT_COMMITTER_NAME
   4  *** environment variables; otherwise you won't be able to perform
   5  *** certain operations because of "empty ident" errors.
   6  *** Alternatively, you can use user.name configuration variable.
   7  
   8  fatal: empty ident  <........@........com> not allowed
   9  fatal: The remote end hung up unexpectedly

If you like colorized command output execute these commands:

   1  git config --global color.diff auto
   2  git config --global color.status auto
   3  git config --global color.branch auto

Using git

If all goes well, change to your project directory and run the following commands:

   1  git init

This creates the git repository, so we’re now ready to start adding files to it, but first we need to create the git ignore file, which tells git to ignore certain files completely:

   1  cat <<EOF<<EOF > .gitignore 
   2  config/database.yml
   3  db/*.sqlite3
   4  log/*.log
   5  tmp/**/*
   6  .DS_Store
   7  doc/api
   8  doc/app
   9  EOFEOF

By default git doesn’t add empty directories—sucks if you ask me—so we’ll create a dummy file in all empty directories with the find and touch commands:

   1  find . \( -type d -empty \) -and \( -not -regex ./\.git.* \) -exec touch {}/.gitignore \; 

Importing files

We’re now ready to start adding and commiting files, so without thinking execute:

   1  git add .
   2  git commit -m 'initial import'

This creates the git repository, adds and commits all files that are in the current folder.

Using remote repositories

If you’re like me you’ll want to use a remote repository, so let’s continue the exercise by creating the repository folder on the remote server (Note that commands are executed on the remote server from now on):

   1  mkdir /var/lib/git/repositories/project_name

We want the folder to be accessible by users belonging to the git group only:

   1  addgroup git
   2  chown root.git /var/lib/git/repositories/project_name
   3  chmod 770 /var/lib/git/repositories/project_name

Now add yourself—or the user you’ll be using to connect to the remote server—to the git group:

   1  usermod -a -G git your_username

Alternatively create a new user:

   1  useradd -g git your_username

Now we’re finally ready to copy the local repository to the remote server, which is done with the scp command (Note that commands are executed locally again from now on):

   1  scp -rp .git user@server://var/lib/git/repositories/project_name

To let git know that this repository exists we’ll use the git remote command:

   1  git remote add project_name ssh://server/var/lib/git/repositories/project_name

This adds the information to .git/config, which might be good to have a quick look at.

Note that if you’re using a non-standard SSH port you need to add the following to your ~/.ssh/config file:

   1  Host server
   2    Port 1234

Commit files and push them to the remote server

Now change a file and commit and push the changes to the remote server:

   1  git commit -m "Me be sleepy"
   2  git push project_name

If you get an error such as this it means you need to install git:

   1  $ git push project_name
   2  username@server's password: 
   3  sh: git-receive-pack: command not found
   4  fatal: The remote end hung up unexpectedly

That’s all…

Miscellaneous problems

error: unable to create temporary sha1 filename ./objects/obj_FUu2jb: Permission denied

Resources

http://jointheconversation.org/railsgit

http://devblog.michaelgalero.com/2007/12/17/my-git-notes-for-rails/

http://railscasts.com/episodes/96

http://groups.google.com/group/rails-oceania/browse_thread/thread/2c8611dc93917952/e175f72310823547

http://www.kernel.org/pub/software/scm/git/docs/tutorial.html

http://scie.nti.st/2007/11/14/hosting-git-repositories-the-easy-and-secure-way

Tagged git, osx, mac, compile, ruby, rails, remote, linux

Installing Rails, mongrel and mongrel_cluster on Debian

Shell Script (Bash) posted 8 months ago by christian

DRAFT …

Install RubyGems

   1  http://rubyforge.org/frs/download.php/29548/rubygems-1.0.1.tgz
   2  
   3  tar zxvf rubygems-1.0.1.tgz
   4  
   5  cd rubygems-1.0.1
   6  
   7  ruby setup.rb

Install Rails

   1  gem install rails

Install sqlite3 (optional)

   1  apt-get install sqlite3 libsqlite3-dev
   2  gem install sqlite3-ruby

Install mongrel and mongrel_cluster

   1  $ gem install mongrel mongrel_cluster
   2  
   3  $ mongrel_rails cluster::configure -e production \
   4    -p 8000 \
   5    -a 127.0.0.1 \
   6    -N 3 \
   7    -c /var/www/xyz/current
   8  
   9  
  10  $ mongrel_rails cluster::start
  11  
  12  
  13  $ useradd -g www-data -d /var/www mongrel

Surviving reboots

   1  sudo mkdir /etc/mongrel_cluster
   2  
   3  sudo ln -s /var/www/xyz/config/mongrel_cluster.yml /etc/mongrel_cluster/xyz.yml
   4  
   5  sudo cp /usr/local/lib/ruby/gems/1.8/gems/mongrel_cluster-1.0.5/resources/mongrel_cluster /etc/init.d/
   6  
   7  sudo chmod +x /etc/init.d/mongrel_cluster
   8  
   9  sudo /usr/sbin/update-rc.d -f mongrel_cluster defaults
  10  
  11  mongrel_cluster_ctl status

Stale pids

If your mongrels crash or if you kill them, mongrel_cluster won’t start your mongrels because mongrel_cluster believes the processes are still running, instead mongrel_cluster complains and does nothing:

   1  ** !!! PID file tmp/pids/mongrel.8000.pid already exists.  Mongrel could be running already.  Check your log/mongrel.8000.log for errors.
   2  ** !!! Exiting with error.  You must stop mongrel and clear the .pid before I'll attempt a start.

To fix this simply add the —clean switch to the /usr/local/lib/ruby/gems/1.8/gems/mongrel_cluster-1.0.5/resources/mongrel_cluster startup script:

   1  mongrel_cluster_ctl start -c $CONF_DIR --clean

Tagged rails, ruby, debian, install, sqlite3, mongrel, mongrel_cluster

Valid RSS 2.0 Feed Template for Rails

HTML (Rails) posted about 1 year ago by christian

Here’s the template, modify it to fit your needs. I know there are plugins and other ways of doing this, but I hate code that gets too abstract:

   1  <?xml version="1.0"?>
   2  <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
   3    <channel>
   4      <atom:link href="http://xxxxxxx" rel="self" type="application/rss+xml" />
   5      <title>Code Snippets - Aktagon</title>
   6      <link>http://snippets.aktagon.com/</link>
   7      <description>Share your code with the world. Allow others to review and comment.</description>
   8      <language>en-us</language>
   9      <pubDate><%= @snippets[0].created_at.rfc822 %></pubDate>
  10      <lastBuildDate><%= @snippets[0].created_at.rfc822 %></lastBuildDate>
  11      <docs>http://blogs.law.harvard.edu/tech/rss</docs>
  12      <generator>Aktagon Snippets</generator>
  13   <% for snippet in @snippets %>
  14      <item>
  15        <title><![CDATA[<%= snippet.title %>]]></title>
  16        <link><%= snippet_url(snippet) %></link>
  17        <description><![CDATA[<%= snippet.rendered_body %>]]></description>
  18        <pubDate><%= @snippets[0].created_at.rfc822 %></pubDate>
  19        <guid><%= snippet_url(snippet) %></guid>
  20  	  <% for tag in snippet.tags%>
  21  		<category domain="http://snippets.aktagon.com/snippets"><![CDATA[<%= tag.name %>]]></category>
  22  	  <% end%>
  23      </item>
  24  <% end %>
  25    </channel>
  26  </rss>
  27  

Remember to serve the feed with the correct HTTP headers.

It also helps to have an auto-discovery tag inside the head tag:

   1  <link rel="alternate" type="application/rss+xml" title="RSS feed" href="http://<%= request.host %>/rss/" />

Tagged ruby, rails, rss2.0, feed, rss, template, example