Setting up a virtualized Rails development environment

Posted by on August 30th, 2007.

As a Rails developer currently stuck using a Windows environment, I've run into a number of problems trying to use gems with native extensions such as RMagick, etc. Fed up with taking twice the time to accomplish the same thing, I decided to get a Linux-based server up and running locally. Since I don't have a dedicated box lying around, I decided to try virtualization. The end result is a virtualized Linux server into which I can shell, build apps, and test either locally or remotely.

Acquiring the Appliance

The first thing I needed to do was get The VMware Player. This freely available virtualization solution is widely used and allows for easy setup of virtualized operating systems of any kind. Download and install VMware Player using normal options.

Next, I needed to get my base appliance. While there is an existing Rails Appliance for VMware Player, I found that it didn't give me the flexibility I needed in installing custom gems and caused more problems than it eased. I decided to go with a clean install of Ubuntu Server on top of which I would add everything I needed. Get the Feisty Fawn distro I used here.

Once your distro has finished downloading, extract into desired location and run using the VMware player. The distribution linked in this article has no root, but an account called notroot with a password of thoughtpolice. You should obviously either change the password or create a new account for yourself immediately for security purposes.

Get Rails Up and Running

Now it's time to install ruby, rubygems, rails, and everything else you might need or want for your new web distribution. Note that I am not setting up an elaborate system, just the bare basics needed to run and test rails applications.

Next we're going to set up our distro with all of the things we'll need for a basic Rails development box. Do the following in your command shell (References: urbanpuddle.com, rails wiki):

sudo apt-get update
sudo apt-get install build-essential ruby rubygems irb1.8 ri rdoc ruby1.8-dev mysql-server libmysql-ruby libmysql-ruby1.8 libmysqlclient15off mysql-client-5.0 mysql-common mysql-server-5.0 rdoc1.8 ri1.8 ruby1.8 libmysqlclient5-dev
gem install rails --include-dependencies
gem install mongrel --include_dependencies
gem install mongrel_cluster
echo 'export PATH=$PATH:/var/lib/gems/1.8/bin' >> ~/.bash_profile
source ~/.bash_profile

That giant block of goodness builds and installs everything you need to get started with your development.We're installing Ruby, RubyGems, a MySQL server, and the associated development libraries that will let us build native extensions such as the mysql gem if desired.

Now that we have the basics, you should be able to pop open a directory (I used /var/www) and create your rails application skeletons. Gem installations should work as normal, and you now have a very basic Rails development environment.

SSH and NAT

You may want to be able to shell into your new virtual machine. The first thing you will need to do is install an SSH server:

sudo apt-get install openssh-server

The trickier part comes in configuring the virtual machine's networking to allow external access. First you need to find out the internal IP for your virtual machine. In your shell, type ifconfig and write down your IP. Now, if you are running VMware Workstation, open the "Manage Virtual Networks" item in the VMware Start Menu folder. If you are running the free VMware Player, open up vmnetcfg.exe in your install directory.

There's a lot to this program, but what you want now is the NAT tab. Make sure NAT service is started then click the "Edit..." button. Click through to "Port Forwarding...". Now you need to add port forwarding for any ports you may want accessible outside the virtual machine. To add a forwarded port, go to add and fill in the IP address you wrote down from ifconfig.

I forwarded port 22 for SSH and ports 3000-3005 for my rails development apps. Once you've added all of the ports you wish to forward, hit "OK" and "OK" again and "OK" again. You should now be able to shell into your VM using PuTTy or the like, transfer files with an SCP program such as WinSCP, and visit your Rails apps live once you run a server with script/server.

There's infinitely more to go over in the world of server configuration, but this is a quick and easy way to get a Linux environment on a Windows box.


Continue reading this post

Share:

Comment on this post (3 comments)


Intridea wins 3rd place at Google Video Contest at Agile 2007

Posted by on August 16th, 2007.
This year the Agile 2007 Conference was held in Washington DC, our home town. We presented two workshops on Rails and Agile. Since we talked about movie making , we thought we shoot a quick marketing video for Intridea. We created "Agile vs Waterfall" video, a spoof on Apple's famous "Mac vs PC" commercial. We submitted the video to Google's YouTube video contest. The video won third place. It was shown to an audience of 1200 attendees at the Google Party and the Conference Banquet.

Facts behind the video

  1. The child actors are BoySonic, 9 and ViqVegas, 5. ViqVegas can't read so he had to memorize all the lines and technical jargon.

  2. The total budget was two M&M chocolate packs.

  3. The script, the shoot, and the edit took about 6 hours in total.

  4. The videos received about 2500 views.


Ok, I am not quite ready to quit my day job to go into the movie business.

The script:

Hi I am agile...

[waterfall: wearing a yellow rain jacket...]
[agile: wearing brown intridea tee shirt and blue jeans]

agile: hi i am agile
waterfall: i am waterfall

agile: what are you doing there waterfall?
waterfall: we just got a new project, I am going through the contract [flips through a stack of papers], you can never be too careful…

agile: really, i just started new project with my customer, we made some sketches on the white board... and we came up with a quick prototype

pulls out a hand drill, brrr, brrr
agile: What's that…
waterfall: Oh, its our requirements tool, its pretty neat, you can drill down 12 levels deep. It automatically generates three binders so we can be CMM Level One Certified.

agile: that sounds like fun…
agile: what's are you doing now?

waterfall: just a little planning. we have three development teams. We should have the initial design in four months, three days, and 14 minutes. It used to take us six months...

agile: that's pretty good planning, we build software in short cycles, so we can learn and adapt...
Waterfall: ok i have to go now, i need a meeting to plan our meetings...
Share:

Comment on this post (1 comment)


with_scope is protected

Posted by on August 10th, 2007.

I've seen a lot of people run into trouble using with_scope on edge. It's now a protected method Ticket: http://dev.rubyonrails.org/ticket/8524.

The solution? Don't use it or use it sparingly. They made it protected for a reason - to protect people from abusing it - but if you absolutely must have at it then you can do something like this:

So say you want to scope your finders to retrieve only MyModel objects of type 'super':

Using self.class.send is a way to get around public and private checking in ruby 1.8. Use with caution.

Share:

Comment on this post (0 comments)


Bending Ruby (Part I) - An User-friendly Hash using method_missing

Posted by on August 7th, 2007.

There’s been a lot of talk about method_missing lately. Let’s do a little example that leverages this freaky but neat little method in our quest to bend Rails to our will. The following code is a handy trick that lets you access key values in a Hash as regular class methods.

class Hash
  def method_missing(method, *params)
    method = method.to_sym
    return self[method] if self.keys.collect(&:to_sym).include?(method)
    super
  end
end

If you have a key called :name, then my_hash[:name] and my_hash.name will now give the same result. If you call some key that doesn’t exist, then the super call tells Object to throw a generic NoMethodError. Neat, no?

P.S. the collect(&:to_sym) shortcut used above actually evaluates to collect{|x| x.to_sym} in Rails. This functionality is not available in Ruby, but it can easily be replicated by overriding the Symbol class, like so:

class Symbol
  def to_proc(*args)
    Proc.new { |*args| args.shift.__send__(self, *args) }
  end
end

Bending Ruby will be a series of posts that will build on one another.

Share:

Comment on this post (1 comment)


Tag Type-Ahead with Multiple Items

Posted by on August 6th, 2007.

If you've ever implemented type-ahead functionality and wondered how to get it to work when users are entering multiple items, like a list of comma delimited tags, here it is.

You can, of course, roll your own Javascript and Ajax calls but why bother when Rails gives us a nice Javascript helper to handle this. The helper is text_field_with_auto_complete but this defaults to the current controller. For my purposes tags can be entered on different areas of the site for different models so I used text_field_with_auto_complete with one modification:

def text_field_with_auto_complete_with_custom_url(object, method, url_options = {}, tag_options = {}, completion_options = {})
  (completion_options[:skip_style] ? "" : auto_complete_stylesheet) +
  text_field(object, method, tag_options) +
  content_tag("div", "", :id => "#{object}_#{method}_auto_complete", :class => "auto_complete") +
  auto_complete_field("#{object}_#{method}", { :url => { :action => "auto_complete_for_#{object}_#{method}" }.update(url_options) }.update(completion_options))
end

Note: text_field_with_auto_complete is deprecated and will be moved to a plugin in Rails 2.0.

The third parameter is now a hash of optional url arguments (action, controller, etc). You can also monkey patch the original method or better use some alias/alias_method_chain trickery in your own app. In your view call the newly created helper with your arguments.

<label for="tag_name">Tags:</label>
<%= text_field_with_auto_complete_with_custom_url :tag, :names, 
    {:controller => "tagging_demo"}, {}, { :tokens => ','} %>

Include the necessary javascript libraries (prototype and scriptaculous):

<%= javascript_include_tag 'prototype' %>
<%= javascript_include_tag 'scriptaculous' %>

You can set the controller and action to whatever you like but it defaults to a method in the form of auto_complete_for_object_method. Going with that your action could look something like this:

def auto_complete_for_tag_names
  @tags = Tag.find(:all, 
    :conditions => ["name like ?", "%#{params[:tag][:names]}%"], 
    :order => 'name DESC', :limit => 20)
  render :layout => false
end

And your view (auto_complete_for_tag_names.html.erb):

<ul class="tags">
<% for tag in @tags do -%>
  <li class="tag"><%= tag.name -%></li>
<% end -%>
</ul>

That's all there is to it. The magic comes from providing a token to Ajax.Autocompleter which we provided in the argument hash to text_field_with_auto_complete_with_custom_url ( { :tokens => ','} ). You can use any delimiter you like. You can also customize the UI in your view and CSS.

Here's a demo http://www.naffis.com/demos/tagging_demo

Share:

Comment on this post (0 comments)


Customized page.* methods for Rails' RJS Templates

Posted by on August 6th, 2007.

So you want to clear your live search fields the moment someone clicks on a result. Here’s a little bit of code that will let you do so in your RJS template:

However, suppose you want to use this same live search clearing scheme over multiple controllers. You can either do re-use the above code for each respective controller method, or you can write the following in your RJS views, thereby DRY-ing up your code:

How, oh how ever do I implement this for my app? Well, this works because in Ruby, it’s quite easy to add or override methods to any class or module. So let’s hack into ActionView, which is the part of Rails that gives you all those neat-o functions in your views (for example: the much-loved link_to).

The trick to overriding Rails code is to always have a copy of Edge Rails checked out to refer to, so you can get the namespace right. For this example, we have established that we want to extend the page.* methods that are prevalent through RJS templates and “render :update” calls. First we need to find out where the code lives. Let’s run a text search on our edge rails copy for ‘insert_html’, which is a commonly used RJS method. We then find out that it’s at action_pack/lib/action_view/helpers/prototype_helper.rb. Well, this is a start!

Next, we look at the namespace of the code in prototype_helper.rb, and try to find insert_html. We then see that it’s nested like so:

Now, in lib/actionview_hacks.rb, copy this namespace and replace the insert_html method with a method of your choice:

Next, update your environment.rb file by adding this somewhere:

That’s it! You can now call page.clear_my_live_search from any RJS template or render :update method. You can also use update_page_tag to insert the page. methods we just generated into your views as javascript.

Also, this example is quite basic. Some might call it overkill to override Rails helpers to get this running. Another good way of doing the same is to define a new method in one of your helpers that uses update_page, like so:

You can then use this helper all over the place, too.

This article barely touches the surface of what’s possible when extending Rails—most existing Rails plugins probably got their start by practically the same process as what we followed here.

Share:

Comment on this post (2 comments)


DRY Internal and External Notifications using ActionMailer

Posted by on August 1st, 2007.

I know that most Rails developers have come across the problem of notifying people by email that they have an internal message on your app’s own messaging system. Usually this is easy enough, and elegantly done in your model by using

However, let’s consider a situation where you need duplication of data on two different processes. For example, if you would like to generate a notification message when some posts to a common forum. The quick way to do this would be by calling two separate methods in your controller, like so:

This requires you to generate the subject and the body of the message and use the methods to work out the logic.

However, with a little ActionMailer hackery, you can make this scheme much cleaner.

In your model,

Next, in views/my_mailer/new_posting.rhtml

The following three lines generate a new MyMailer object, create the email specified by the method (in this case, :notify_posting) using ActionMailer’s create! method (which in turn uses Ruby’s glorious send method), and pull out the TMail object that ActionMailer sends to the SMTP server. Conveniently, the TMail object lets you extract out the subject and body, which lets you map them to your InternalMessage class.

The above code generates the email, pulls out the generated subject and the body and uses it as the subject and body of the internal message. The idea is that the content of both the email notification and the internal email match up. This method does not require you to setup your subject and body. Instead, this method lets you use ActionMailer as a rendering framework for generating text/html for all of your internal messages. DRY is Good!

Share:

Comment on this post (0 comments)