Help Stop Internet Censorship

by Irish on January 17, 2012

PROTECT IP / SOPA Breaks The Internet from Fight for the Future on Vimeo.

{ 0 comments }

Got burned by two things today in one of my apps by upgrading to Rails 3.1. The first thing was a few nested forms stopped working when editing an existing record that had child records. None of the children were getting rendered. For briefity, the form basically was like:

<%= form_for @meal do |meal_form| %>
  <table>
    <tbody>
      <% meal_form.fields_for :meal_items do |item_form| %>
        <%= render :partial => 'meal_item_fields',
                   :locals => { :f => item_form } %>
      <% end %>
    </tbody>
  </table>
<% end %>

Can you spot the error? Once I spotted it I felt rather dumb myself. It’s the following erb tag

<% meal_form.fields_for :meal_items do |item_form| %>

Ya even when they’re nested you HAVE to use the <%= form... doh!

<%= meal_form.fields_for :meal_items do |item_form| %>

The second problem I ran into, and which I still don't have an answer for, though if you do answer my StackOverflow question. Basically, in Rails 2.3 if you needed to get at an instance of the Template Builder you could use @template, but then they changed it in Rails 3 to a special method called "view_context". Far enough, so I was using view_context in Rails 3.0.X to create nested forms (other than the one above) dynamically using jQuery ajax and js.erb partials. Using view_context allowed me to call fields_for off of it so that I would get nicely named form_fields when I didn't have the parent FormBuilder handy. Like this

In some_view.js.erb

<% fields =
    view_context.fields_for :meal_items, Meal.new.meal_items.new do |f|
      render :partial => 'meal_item_fields', :locals => {:f => f}
    end %>

$("#meal-items").append("<%= escape_javascript(fields) %>");

But once I upgrade to 3.1, I started getting the following error

ActionView::Template::Error (undefined local variable or method `view_context' for #<#:0x1057b9f70>):

Perhaps this was removed as the Core team figured, why do you need the view_context available when you're in a view template already... but I don't know. I was able to workaround it though by moving my code up into the controller. Which does seem to be a violation of the MVC separation, but I couldn't find any other way to make it work like pre Rails upgrade. So instead of creating a local variable "fields", this became an instance variable that was set in the controller action. And render needed to become render_to_string with an html_safe call tacked on the end.

In controller

def some_ajax_action
  @fields =
    view_context.fields_for :meal_items, Meal.new.meal_items.new do |f|
      render_to_string(:partial => 'fields', :locals => {:f => f}).html_safe
    end
end

I don't like this, but it'll do for now I suppose. And now in some_view.js.erb

$("#meal-items").append("<%= escape_javascript(@fields) %>");

{ 0 comments }

Ruby 1.9.2 Segmentation Fault and OpenSSL

by Irish on September 2, 2011

In one of my current project, whenever I ran a rake task that did a net/http request it was causing segmentation faults.

$ bundle exec rake test:task
$ /Users/cirish/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/net/http.rb:678: [BUG] Segmentation fault
ruby 1.9.2 (2011-06-30 patchlevel 290) [i686-darwin10.8.0]

And it seems whenever I get a segmentation fault the first place I need to look is at OpenSSL. I’ve had similar problems with seg faults and openssl in the past, namely this OpenSSL Bus Error that I was getting on Ruby 1.8.7.

If you read that post you’ll see this happened because I use MacPorts and have OpenSSL installed through it, in addition to a local OS X version. To get Ruby to be happy, you have to point your Ruby install to the correct version at installation time. So remove the bad install

$ rvm remove ruby-1.9.2

And reinstall

$ rvm install ruby-1.9.2 --with-openssl-dir=/opt/local --with-iconv-dir=$rvm_path/usr

Which I forgot to do with my Ruby 1.9.2 install after upgrading OS X versions. That last bit about iconv isn’t directly related, but I have inconv package installed to RVM, you can read about that here RVM Iconv.

Also, this Phusion blog post REE 1-8-7-2011-03-released mentions problems with OpenSSL and MacPorts. Moral of the story… use HomeBrew? Dunno, but I’ll probably start using it when I upgrade my laptop.

{ 12 comments }

I just ran into a rather hard to track down issue with Authlogic and Rails 3. After upgrading an old app to Rails 3, in production, the sessions wouldn’t persist, but everything worked fine in development mode. After much searching it turns out that there’s an issue with using Rails 3, Authlogic, and HTTP auth together. I had put up HTTP basic auth in Nginx to prevent the site from getting seen by random people or web crawlers. When the app was a Rails 2 app, there was no issue, in fact the Rails app shouldn’t even have known about the HTTP auth since I was doing it in Nginx, not Rails. Not sure why this is a problem with this Rails/Authlogic/HTTP combination, but anyways, the fix was to add this one-liner to your UserSession model

    1 class UserSession < Authlogic::Session::Base
    2   allow_http_basic_auth false
    3 end

{ 3 comments }

Splitting Rails DOM ids with RegEx Look Aheads

by Irish on October 15, 2010

In my Rails erb views I make good use of the dom_id view helper method. It basically introspects the object you pass to it and creates a unique id to use in your markup, based on the object type and database id. So for example if I had a Post with id 1, I could do:

    1 
    2 <li id="<%= dom_id(@post) %>">
    3 

And it would be rendered as

    1 
    2 <li id="post_1">
    3 

This is fine until you use dom_id on an object with a compound name like EmailNotification. Now dom_id will create a unique id like

email_notification_1

Which is still good until I’m doing some front-end testing and I’m parsing these dom ids to find their related db records. Now I need to split “email_notification_1″ in a way that easily separates the object class from the identifier. How would you do that?

Well, what we can do here is use an advanced Regular Expression feature called a negative look ahead. We want to say, “split the string on the last underscore”.

A negative look ahead uses the ?! syntax in parenthesis, everything that follows ?! in the parenthesis will be used in the negative look ahead matching. So in our case we want to say, there should be a underscore that can be followed by any character except another underscore. The pattern would like like this:

/_(?!.*_)/

We can confirm in irb

$ ree-1.8.7-head > x = "email_notification_1234"
=> "email_notification_1234"
ree-1.8.7-head > klass, id = x.split(/_(?!.*_)/)
=> ["email_notification", "1234"]

Likewise, If we wanted to split the dom_id on the first underscore we could just use a regular look ahead. It is similar but uses the ?= syntax.

$ ree-1.8.7-head > x.split(/_(?=.*_)/)
=> ["email", "notification_1234"]

{ 1 comment }

How to install RVM on Ubuntu 10.04

by Irish on August 25, 2010

I’ve heard people describe frustrations they had in getting Rails 3 setup on Ubuntu 10.04 with Ruby 1.9.2. I’m going to outline the steps I’ve taken to do this. Let’s get started installing RVM.

It should be noted that I created a fresh slice on my Rackspace Cloud account to create this tutorial. And I’m assuming you’ve already setup SSH.

$ ssh root@173.XXX.XXX.XXX
<-- Output Snipped -->
root@173.XXX.XXX.XXX's password:
<-- Output Snipped -->

Alright, so lets confirm we don’t have ruby installed

$ which ruby
$

Cool, nada. Let’s grab the basic dependencies

$ sudo apt-get install curl git-core ruby
Reading package lists... Done
Building dependency tree
<-- Output Snipped -->

Now we’ll install RVM as per their instructions

http://rvm.beginrescueend.com/rvm/install/

$ bash -s stable < <(curl -s https://raw.github.com/wayneeseguin/rvm/master/binscripts/rvm-installer )

<-- Output Snipped -->

RVM: shell scripts which allow management of multiple ruby interpreters and environments.
RTFM: http://rvm.beginrescueend.com/
HELP: http://webchat.freenode.net/?channels=rvm (#rvm on irc.freenode.net)

* Installing rvm to /usr/local/rvm/
Correct permissions for base binaries in /usr/local/bin...
Copying manpages into place.

Notes for Linux ( DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=10.04
DISTRIB_CODENAME=lucid
DISTRIB_DESCRIPTION="Ubuntu 10.04 LTS" )

<-- Output Snipped -->

* For JRuby (if you wish to use it) you will need:
$ aptitude install curl sun-java6-bin sun-java6-jre sun-java6-jdk
* For MRI & ree (if you wish to use it) you will need (depending on what you are installing):
$ aptitude install build-essential bison openssl libreadline5 libreadline-dev curl git-core zlib1g zlib1g-dev libssl-dev vim libsqlite3-0 libsqlite3-dev sqlite3 libreadline-dev libxml2-dev git-core subversion autoconf
* For IronRuby (if you wish to use it) you will need:
$ aptitude install curl mono-2.0-devel

<-- Output Snipped -->

WARNING: you have a 'return' statement in your .bashrc, likely this will cause untold havoc.
This means that if you see '[ -z "$PS1" ] && return' then you must change this line to:
if [[ -n "$PS1" ]] ; then
... original content that was below the && return line ...
fi # <= be sure to close the if.
#EOF .bashrc
Even if you use zsh you should still adjust the .bashrc as above.
If you have any questions about this please visit #rvm on irc.freenode.net.

Installation of RVM to /usr/local/rvm/ is complete.

The last part in there about the .bashrc file is important! Using your editor of choice, open the .bashrc file that resides in your user directory.

You need to replace the line that says

[ -z "$PS1" ] && return

with

if [[ -n "$PS1" ]]; then

Now add this to the last line of the file

if [[ -s $HOME/.rvm/scripts/rvm ]] ; then source $HOME/.rvm/scripts/rvm ; fi

fi

And yes there needs to be that last fi as it closes the one we added earlier. Save this file with our changes. Now we can check if RVM is setup correctly.

$ rvm notes

If this gives you installation notes about RVM then you’re good to continue, otherwise double check you edited your .bashrc file correctly.

In the notes output RVM tells you what packages you’re gonna need to install for various flavors of Ruby. Since we’re going with 1.9.2 we want the packages it lists under the MRI & ree section. Let’s install those now.

$ sudo aptitude install build-essential bison openssl libreadline5 libreadline-dev curl git-core zlib1g zlib1g-dev libssl-dev vim libsqlite3-0 libsqlite3-dev sqlite3 libreadline-dev libxml2-dev git-core subversion autoconf

<-- A really long bit of Output Snipped -->

Now we can look at all the RVM known Ruby packages

$ rvm list known
# MRI Rubies
(ruby-)1.8.6(-p399)
(ruby-)1.8.6-head
(ruby-)1.8.7(-p302)
(ruby-)1.8.7-head
(ruby-)1.9.1-p243
(ruby-)1.9.1-p376
(ruby-)1.9.1(-p429)
(ruby-)1.9.1-head
(ruby-)1.9.2-preview1
(ruby-)1.9.2-preview3
(ruby-)1.9.2-rc1
(ruby-)1.9.2-rc2
(ruby-)1.9.2(-p0)
(ruby-)1.9.2-head
ruby-head

# JRuby
jruby-1.2.0
jruby-1.3.1
jruby-1.4.0
jruby-1.5.1
jruby(-1.5.2)
jruby-head

<-- Output Snipped -->

Next we install the version we want and set it as the default. You’re gonna see RVM install ruby-1.8.7-p302 first, be patient as it will need to also install rubygems-1.3.7, before it finally gets to that 1.9.2.

$ rvm install 1.9.2-head
<-- Output Snipped -->
info: Installing ruby-1.8.7-p302
<-- Output Snipped -->
info: Installing rubygems dedicated to ruby-1.8.7-p302...
<-- Output Snipped -->
info: Installing ruby-1.9.2-head
<-- Output Snipped -->
info: Updating rubygems for /usr/local/rvm/gems/ruby-1.9.2-head
$ rvm --default 1.9.2-head
$ ruby -v
$ ruby 1.9.2p0 (2010-08-18 revision 29034) [x86_64-linux]

Good to go.

{ 63 comments }

On a project I’m currently working on, we use ActiveRecord callbacks heavily. From simplying creating other associated objects, to recording the historic activity about the object in question, and more.

The drawback I find from the scope of AR callbacks though is that you only have direct access to data from the database. And since you can’t pass arguments to a AR callback, you can’t easily get the request params for example or know which controller action fired off the the AR chain that triggered the callback you’re in, or know who the current user logged in is.

But it turns out that there is a way, however it is neither straight forward or obvious. Say for example you have the following model and controller:

    1 class Post < ActiveRecord::Base
    2   belongs_to :user
    3   belongs_to :group
    4   has_one    :alert, :as => 'alertable'
    5
    6   after_update :note_activity
    7
    8   private
    9   def note_activity
   10     group.admins.each do |admin|
   11       # What user is doing this update?
   12       admin.notifications.create(:user => "Someone",
   13                                  :action => 'did something')
   14     end
   15   end
   16 end
    1 class Admin::PostsController < ApplicationController
    2
    3   def update
    4     @post = Post.find(params[:id])
    5
    6     if @post.update_attributes(params[:post])
    7       redirect_to admin_posts_path
    8     else
    9       render :action => 'edit'
   10     end
   11   end
   12 end

What we want to accomplish here is that all admins of a group get a notification when another admin user edits a post. The post in question here has no context in it’s callback of which admin was logged in at the time the update happened. So what we’re gonna do is put the admin user’s id onto the current thread of the request in a before filter. Then, we’ll pull that id off in the callback to look up the admin and create the notifications.

So we’ll add a simple before filter:

    1 class ApplicationController < ActionController::Base
    2   before_filter :store_user
    3
    4   def store_user
    5     User.current = current_user
    6   end
    7 end

And create a couple class methods on User to store the currently logged in admin for the duration of the request:

    1 class User < ActiveRecord::Base
    2
    3   def self.current=(user)
    4     Thread.current['user'] = user.try(:id)
    5   end
    6
    7   def self.current
    8     @@current ||= User.find_by_id(Thread.current['user'])
    9   end
   10 end

Now we can alter our note_activity method in Post to get the admin who did the edit:

    1 def note_activity
    2   group.admins.each do |admin|
    3     admin.notifications.create(:user => User.current,
    4                                :action => 'did something')
    5   end
    6 end

This works well in my project. I’d like to know if there is a less “hacky” way of doing this but I’m not currently aware of one.

{ 2 comments }

The Ruby %r{} expression

by Irish on August 12, 2010

Tonight I was reading over some Ruby code in a gem I’m currently using and came across this line:

    1 string = mode.to_s
    2 string.gsub!(%r{(^.)|(_.)}) { |m| m[m.length-1,1].upcase }
    3 

Two things struck me about that second line. For one I’ve never used gsub and passed it a block, thats cool. And two, what is %r{} ? I’ve never seen that before. It turns out that in Ruby, the /…/ or %r… literals, and using the Regexp.new constructor are all the same thing. All ways of created a regular expression. I still think I prefer the look of the simple slashes /…/ though.

{ 2 comments }

CSS Tricks

by Irish on August 11, 2010

Seeing as I’m not a UX/Designer guy, I’m always learning new css tricks and over coming css/browser gotchas in my day to day development work. My coworker Billy showed me this helpful site:

15 CSS Tricks that must be learned

Thought I’d pass it along, you may learn a thing or two as did I.

{ 0 comments }

How to install Sphinx on OS X

by Irish on August 10, 2010

Getting a local development environment setup to run Sphinx on your Mac is pretty easy. You can boil it down to the following quick commands.

$ wget http://www.sphinxsearch.com/downloads/sphinx-0.9.9.tar.gz
$ tar xvzf sphinx-0.9.9.tar.gz
$ cd sphinx-0.9.9
$ ./configure
$ make
$ sudo make install

This assumes you’re using a default MySQL installation. If however you’re like me and using MySQL installed from macports, you’ll need to pass the location of the MySQL configuration directories to Sphinx. The configure command would then change like so:

$ ./configure
$ ./configure --with-mysql-includes=/opt/local/include/mysql5/mysql/ --with-mysql-libs=/opt/local/lib/mysql5/mysql/

On a side note, Sphinx 1.10-beta has also just recently been released (July 10′). This release has real-time indexes support, a welcome addition I have been waiting for. Definately check it out.

{ 2 comments }