CommonThread

Displaying articles with tag

Textmate Footnotes with vim support

Posted by ben, Wed Jun 11 01:31:00 UTC 2008

I just switched to doing rails development in vim rather than textmate but I sure did miss my textmate footnotes. I found a post about a plugin called redit that converted stacktraces over to links that would open in vim (textmate footnotes style) so I decided to take that and patch Textmate Footnotes. I had to make sure not to messup any of the developers who were going to still use Textmate so it patches it to do both based on an env variable we will talk about later.

Redit Controller

First I took the controller from the afore mentioned plugin and tweaked it to make sure we were running in development mode before executing code on the server and changed it to use MacVim as the vim app. Simply create a new controller called ReditController and paste the code below changing the system call if you use something other than MacVim.

require 'base64'
class ReditController < ApplicationController
  def open
    if ENV['RAILS_ENV'] == 'development'
      file = Base64.decode64(params[:id])
      line = params[:line].to_s

      # Run editor here
      Thread.new do
        ### MacVim
        # Open file in new tab of vim server
        system("mvim","--remote-tab","+#{line}",file)
      end 
    end
    redirect_to :back
  end
end

Textmate Footnotes Patch

Next you need to replace the lib/textmate_footnotes.rb with this one. I am working with an older version of textmate footnotes so be forewarned that my file may not work 100% with your version … I will update to the latest soon and update my file. Here is an example of how the patch changes the urls generated:

def controller_url
    if ENV['FOOTNOTE_APP'] == 'vim'
      escape(
        "/redit/open/" +
        CGI.escape(Base64.encode64(controller_filename)) +
        (index_of_method ? "&line=#{controller_line_number + 1}&column=3" : "")
      )
    else
      escape(
        textmate_prefix +
        controller_filename +
        (index_of_method ? "&line=#{controller_line_number + 1}&column=3" : "")
      )
    end
  end

Environment Variable

And lastly to make the plugin give you vim links rather than textmate links you need to set the FOOTNOTE_APP env variable. To make this happen every time you login place the following snippet in your ~/.bash_profile

export FOOTNOTE_APP=vim

0 comments | Filed Under: | Tags:

Phusion Passenger

Posted by ben, Mon Jun 02 02:57:00 UTC 2008

We have been testing out mod_rails Phusion Passenger for a few weeks now on our staging server and one production server that hosts our company website and blog. Today we finally got our hands on the Ruby Enterprise Edition early release, so we are now running the full enterprise passenger stack and I must say that I am loving not having to deal with so many deploy issues like configuring monit, nginx & mongrel_cluster configs for every new app and for almost any configuration change, which we find almost unnecessary now since passenger is handling how many app instances to spawn up and it keeps an eye on instances that crash or get hosed for some reason.

We are able to able to really make better use of our VPS slices with the memory reduction we get from running passenger VS nginx+mongrel.

checkout this screencast or head over to the Phusion Passenger website to try it out for yourself.

0 comments | Filed Under: | Tags:

Complex Forms ... Just Easier

Posted by ben, Thu Apr 17 00:33:00 UTC 2008

I love having the ability to easily create/update multiple objects with a single form. There are some nice railscasts by Ryan Bates that describe how to do this in Ruby on Rails. What I needed was a way to make writing the attribute accessor methods easier. I also decided that there just weren’t enough rails plugins out there … so off to kill two birds with one stone.

The Plugin

The plugin is called association-attributes and it can be found on github. The goal was to make the process more semantic and most of all DRY. I decided that since we already had to have a method on the model to handle the association we would pattern after that. So, the two methods available are has_one_attr & has_many_attr.

The Model

So for a practical example of what this looks like in your model we will use a persons contact info. We also have a plugin out there that makes contact info easier since that is such a standard need and there is no reason to rewrite that all the time.

class Person < ActiveRecord::Base
  has_one :address, :as => :addressable, :dependent => :destroy
  has_one_attr :address

  has_many :phone_numbers, :as => :phoneable, :dependent => :destroy
  has_many_attr :phone_numbers
end

What that does is creates the methods address_attributes & phone_number_attributes on Person so that we can use them in our form. These newly created methods handle creating & updating existing entries for addresses and phone numbers.

The View

We use HAML for all of our views so these examples are no exception.

- fields_for("person[phone_numbers_attributes][]", @person.phone_numbers.new) do |phf|
  %label{:for => "number"} Phone Number:
    = phf.hidden_field :id
    = phf.text_field :number
A few things to note from this example are:
  • The fields_for has an extra [] on the first parameter … this is because we have a has_many and that tells the browser to treat that as part of an array so that we can have more than one of that same name and it will get put into the array.
  • We are only doing a new item but you would use the same technique to display existing items by replacing @person.phone_numbers.new with a variable of the actual phone number.
  • We have an id hidden field … this is if we use an existing phone number object it will update rather than creating a new object. (it still works without that but deletes the old number and creates a new one)
- fields_for("person[address_attributes]", @person.build_address) do |af|
  %p
    %label{:for => "line_1"} Street Address:
    = af.text_field :line_1
  %p
    %label{:for => "city"} City:
    = af.text_field :city
  %p
    %label{:for => "state"} State:
    = af.select :state, Address::VALID_STATES.map{|s| [s,s]}.sort
  %p
    %label{:for => "zip"} Zip:
    = af.text_field :zip

In future versions I will have a helper method that writes the fields_for for you as well. Looping through current objects and having an option to put a blank one at the end.

The Result

The result of this is that now when you submit a form to create or update a person that has these subforms using fields_for then the appropriate phone number and address objects will get created or updated as well. No more having to create the person first then associate the extra objects later. Even in the case of a has_many where the object is new it will create the object for you then create all the association objects next.

0 comments | Filed Under: | Tags:

Upgrading Ruby on Ubuntu (from package to source)

Posted by ben, Wed Jan 23 11:01:00 UTC 2008

We recently updgraded from ruby 1.8.4 to 1.8.6 on our production servers. When we did we went from the package manager versions of ruby to a source install, bedlam followed. Gems that required native extensions were no longer working properly and flames were pouring from the machines. So here is a list of actions to help anyone else wanting to upgrade on an Ubuntu machine.

  1. remove all gems ( sudo gem list, gem uninstall )
  2. remove all ruby related packages ( dpkg—list | grep ruby, dpkg -r )
  3. download ruby and rubygems src
  4. extract and install ruby ( ./configure—prefix=/usr , make , sudo make install )
  5. extract and install rubygems ( sudo ruby setup.rb )
  6. install gems ( sudo gem install )

0 comments | Filed Under: | Tags:

Tip: Rails Options Helpers

Posted by anthony crumley, Wed Jan 09 14:54:00 UTC 2008

Ok, so these are not really helpers but they are helpful. Rails often uses a hash as the last method parameter to pass options. When the method has a variable number of parameters there is a need to pull the options hash out of the arguments array. To do this they added an extract_options! method to the Array. This method removes and returns the last argument in the array if it is a Hash.

def some_method(*args)
  options = args.extract_options!
  ..
end

Another common options problem is setting default values. Rails added reverse_merge to the Hash object to help out here.

def some_method(*args)
  options = args.extract_options!
  options.reverse_merge!({:limit => 10})
  ..
end

0 comments | Filed Under: | Tags:

Tip: Ruby On Rails Random Array Element

Posted by anthony crumley, Thu Dec 06 21:56:00 UTC 2007

Rails 2.0 will include an array extension for retrieving a random element. The method name is rand. Since the active record find method returns an array, this method can be used to retrieve a random item from a database. In the following example a featured product will be randomly selected.

Product.find_featured.rand

0 comments | Filed Under: | Tags:

Textmate Footnotes on Edge

Posted by ben, Wed Dec 05 22:38:00 UTC 2007

You may have experienced some issues with textmate footnotes if you are running on edge rails. There are 2 different problems that I have run into.

The first is similar to my earlier post about Haml breaking my footnotes. When you are on a page with the new html.erb extension you don’t get footnotes and that is fixed in similar fashion, by adding the “html.erb” to the list of file extentions in the add_footnotes! method of the file vendor/plugins/footnotes/lib/textmate_footnotes.rb. Mine now looks like .. [“html.erb”, “haml”, “rhtml”, “rxhtml”]

The second is that error pages no longer show a stack trace but rather just a 500 page with no explanation. The reason is that the render_file methods in the file vendor/plugins/footnotes/templates/rescues/template_error.rhtml still point to ”.rhtml” files and edge and 2.0 moved to the new file extension ”.erb” so you need to change both refences to point to ”/_trace.erb” & ”/_request_and_response.erb”

I made a pastie for your convenience with the two diffs to make it easier …

Textmate Footnotes fix for edge rails & 2.0

1 comment | Filed Under: | Tags:

Tip: Ruby On Rails Returning

Posted by anthony crumley, Wed Dec 05 14:02:00 UTC 2007

The Rails returning method can clarify your code. Its basic purpose is to semantically group code that creates the return value for a method. We could discuss its K Combinator Lambda Calculus roots but we won’t go there. Heck, I don’t even remember what that crap is.

Returning accepts two parameters. The first parameter initializes the return value. The second parameter is a block that creates the return value.

Returning doesn’t usually save lines of code or help with performance but it does make things a little clearer. One thing it does well is separate setup code from code that actually creates the return value. Consider the following helper method that returns the full name of a user.

def full_name(user)
  user = current_user unless user

  name = user.first_name
  name << ' ' + user.middle_name unless user.middle_name.blank?
  name << ' ' + user.last_name
  name
end

Now the same method using returning to clarify what is being returned.

def full_name(user)
  user = current_user unless user

  returning String.new do |name|
    name << user.first_name
    name << ' ' + user.middle_name unless user.middle_name.blank?
    name << ' ' + user.last_name
  end
end

0 comments | Filed Under: | Tags:

Tip: Ruby On Rails to And from

Posted by anthony crumley, Tue Dec 04 17:33:00 UTC 2007

In Rails 2.0 arrays will have to and from methods that work like the ones on strings. The to(position) method will return elements from the beginning of the array up to and including the position passed in. The from(position) method will return elements from the position passed in to the end of the array.

[1, 2, 3].to(1) => [1, 2]
[a, b, c].from(1) => [b, c]

0 comments | Filed Under: | Tags: