Why Ruby?

2011-01-24

Zach Dennis has a great post about why he likes Ruby. It was in response to another post by one of the many people who seem to resent the language. This all inspired me to add my two bits.

Funny thing about Ruby, I became interested in it four years ago because of the people who hated Ruby on Rails. Their arguments reminded me of the anti-Mac Microsoft apologists from the late 90′s. They tended to express resentment and contempt for the Mac, while Mac users responded by explaining why it was simply the tool that worked best for them.

The more I learned about Ruby and the Rails framework, the more I liked them. As with most Rubyists on Rails, I don’t claim that they are the best tools for in all situations, just that they work well for me in many situations.

There’s even something different about the developer community that I like. Maybe it has to do with the passion that many/most Rubyists have for their language of choice. That too reminds me of the Mac community from 10+ years ago. I don’t begrudge anyone who is more detached from their language or platform of choice, but I prefer to be around those who have some fire for what they do.

If you don’t like Ruby, don’t use it. Just because it works some, it doesn’t mean that there’s something wrong if it doesn’t work for you.


Communication – It’s the Meaning that Counts

2010-08-13

This post is an adaptation of my response to this blog posting at mutuallyhuman.com.

We can probably all agree that hurtful speech in the workplace, even when unintentional, should be avoided. However, I believe that the *meaning* is what’s important, not the words. Yes, it is important to say what you mean, but sometimes it just comes out wrong, and sometimes the words are taken wrong.

I have to admit that I am rather biased on this topic – I’ve struggled with correctly verbalizing my thoughts almost my entire life. Improvement in this area has come slow, but I’m working on it.

Communication is a two-way street. Sometimes it’s the speaker, sometimes it’s the listener. As a speaker, we should all do the best we can, but the listener has some responsibility as well. The next time that you’re hurt by something that was said, give the speaker a chance to clarify. Tell the speaker what you heard and ask them if that is what they meant. Chances are, the hurt feeling will go away and the bond between you and the speaker will be strengthened.

To re-iterate, it really is the meaning that counts, not the words. I think you’ll find that if you challenge someone who says something that is hurtful (especially if it was unintentional), it will help them become a better communicator and, at the same time, help reduce your sensitivity to “violent” speech.

I’d like to go-off about how the all-to-long trend of pollitical correctness has screwed things up – how it has caused an entire generation to pay attention to the words while ignoring the actions, but that is outside the scope of this post…


Obfuscating ID’s in URLs with Rails

2010-07-08

It seems to me that Rails should provide some magical mechanism that obfuscates IDs in URLs when running in production mode. Unfortunately it doesn’t, at least not to my knowledge. So we’re stuck doing it ourselves.

There are many approaches to obfuscating database IDs in URLs – some more clean than others, some more secure. The purpose of this article isn’t to discuss the various methods, it is to simply illustrate what worked for me for one particular application.

Here are the steps to take on an existing project that already has one or more models:

1. Create a class to handle the obfuscation.

Create a class named IdCrypt, or whatever works for you, and put it in the lib directory. The following sample code uses Knuth’s integer hash to obfuscate the ID, but it can be any reversible hash that avoids collisions. If you want better security, use 128-bit encryption.

class IdCrypt

  def initialize()
    @last_id = 0
    @encoded_id = 0
  end

  # the encode and decode algorithms come from Michael Greenly's blog:
  # http://blog.michaelgreenly.com/2008/01/obsificating-ids-in-urls.html.
  MAXID = 2147483647  # (2**31 - 1)
  PRIME = 1580030173  # number suggested on the blog
  PRIME_INVERSE = 59260789 # (PRIME * PRIME_INVERSE) & MAXID == 1

  # encode the given id
  def encode_id( clear_id )
    if clear_id
      id_int = Integer( clear_id )  # ensure that the id is an integer
      if @last_id != id_int
        @last_id       = id_int
        @encoded_id = (id_int * PRIME) & MAXID
      end
    else
      @encoded_id = clear_id
    end
    @encoded_id
  end

  # reverse the obfuscation that was applied to the given id
  def self.decode_id( encoded_id )
    clear_id = 0
    if encoded_id && (encoded_id != "")
      clear_id = (Integer(encoded_id) * PRIME_INVERSE) & MAXID
    end
    clear_id
  end

  # reverse the obfuscation that was applied to the given param symbol
  def self.decode_param( symbol )
    params[symbol] = IdCrypt::decode_id(symbol).to_s if params[symbol]
  end
end

2. Add encoding properties to each model

Add the following to each model to provide easy access to the encoded version of the id:

# get the encoded record id
def id_encoded
  @id_crypt.encode_id( self.id )
end

# override of the base class method to ensure that raw user ids are not displayed in the url
def to_param
  @id_crypt.encode_id( self.id )
end

protected
def after_initialize
  @id_crypt = IdCrypt.new
end

3. Add a before filter to the controller

Add the following ‘before filter’ to the model’s controller to automatically decode the id param before a controller processes it:

before_filter :decode_id

4. Create the decode_id method

Add the decode_id method to application_controller.rb so that all controllers have access to it. For example:

# decode the id url param if there is one
def decode_id
  params[:id] = IdCrypt::decode_id(params[:id]).to_s if params[:id]
end

5. Ensure that model objects are used as path params

Wherever a path to the model’s controller is referenced and the model id is a param, use the model object as the parameter, not the object’s id. This causes the to_param override to be called.

For example, do this:

<%= link_to 'view user profile', user_profile_path(user) %>
<%= link_to 'view user profile', :controller => 'user', :action => profile, :id => user %>

don’t do this:

<%= link_to 'view user profile', user_profile_path(user.id) %>

That should do it. Go ahead and try it out and let me know what you think. Please feel free to suggest improvements or even a completely different approach that you prefer.


Deploying Redmine on ASO Shared Hosting

2010-05-16

It took me a couple of days, but I finally got Redmine (redmine.org) deployed on my shared hosting account, A Small Orange (ASO – asmallorange.com). Here’s an overview of the ordeal. Even though it is specific to ASO, you may find it helpful for getting Redmine deployed on your shared hosting account.

Starting out, I thought that it would be a great idea to use the latest stable release of Redmine – 0.9.4. So I downloaded it via Subversion since that’s the version tracking system that I’m currently using. The process went well at first – I got it downloaded, created a test database locally, and tested it locally. When I tried to deploy, I realized that ASO isn’t using Rails 2.3.5, it’s using Rails 2.1.0. No problem, just freeze rails with the app and everything will be fine, right?… Well, not quite. I had all kinds of issues with Rack – it apparently isn’t supported by ASO’s shared hosting yet.

My next thought was to try the latest 0.8.x stable release of Redmine (0.8.7), which doesn’t require Rack. So I downloaded it via Subversion, tested locally, and then tried to freeze Rails (Redmine 0.8.7 uses Rails 2.1.2, ASO was on 2.1.0).

rake aborted: "undefined method `manage_gems' for Gem:Module"

gem update didn’t help. gem install -v=2.1.2 rails --include-dependencies didn’t help. Since ‘manage_gem’ is no longer supported and I couldn’t find a way around it, I remembered that Redmine’s ‘Installing Redmine’ page says that “Official releases include the appropriate Rails version in their vendor directory.”

HERE’S WHAT WORKED
- Download redmine-0.8.7.zip from rubyforge.org
- Copy the unzipped dir to /usr/local/src/proj
- Setup database.yml as instructed at redmine.org/wiki/redmine/RedmineInstall
- Upload the project to my shared hosting account
- Create the database on my shared hosting account
- Uncomment the “ENV['RAILS_ENV'] ||= ‘production’” line in environment.rb
- Setup permissions
$ chmod -R go-w ~/redmine
- Setup the session store and database as instructed at redmine.org/wiki/redmine/RedmineInstall
- Create a symbolic link to ~/public_html
$ cd ~
$ ln -sf ~/redmine/public ~/public_html/redmine
- Since I’m running out of a subdirectory, I need to update the .htaccess file to use mod_rails/Passenger, which is what ASO uses for running Rails apps.
$ cd ~/redmine/public
$ nano .htaccess
add the following to the file
RailsBaseURI /redmine
- Setup config/email.yml to receive email notifications. I had trouble getting the :smtp delivery_method to work on my ASO account, so I used :sendmail.

Redmine is now up and running on my shared hosting account. I’m actually using it to log and track issues at my neighborhood association.

I hope that this helps.


SQLite3::SQLException: no column named…

2009-06-05

Being relatively new to Ruby on Rails, I often get hung up on some ‘simple’ things. Here’s the latest:

In table credentials, I created a migration that renamed column ‘credentials’ to ‘credential_uri’, ran the migration and changed the code accordingly. Running test/unit/credential_test.rb resulted in the following error:

ActiveRecord::StatementInvalid: SQLite3::SQLException: table credentials has no column named credential: INSERT INTO...

A couple hours of googling and failed tries yielded nothing. So I went to bed (it was 1:30am). Ten minutes into looking at this in the morning, I discovered that the text fixture that was automatically generated when the model was created did not automatically update when the column name changed.

Changing
credential: MyString
to
credential_uri: MyString
in test/fixtures/credentials.yml made my unit test happy again.


Follow

Get every new post delivered to your Inbox.