ruby on rails - has and belongs to many view plugin

So I’ll never have to write another has_and_belongs_to_many view again, here’s a plugin that dynamically makes 2 <ul> lists which you drag and drop both ways to manage the association.

http://svn.ahabman.com/public/many_to_many_view/

From the readme:

Assumming you have an @project var and you want to associate people with it.

<div id="m2m_container">
<%= render :partial => "shared/m2m", :locals => {
:thing => @project,
:association => 'people',
:association_attr => 'first_name' }   %>
</div>

:thing take the current object
:association takes the pluralized association, a string.
:association_attr takes the attribute of the associated object that will be displayed.

You can’t use class variables in rails.

You can’t use class variables in rails.  Unless you’d like to develop in production mode (specifically with config.cache_classes = true).  In development mode all classes are reloaded on each request, which clears all class variables.

I had the perfect place to use them - while running a mass synchronization, and needing to store the timestamp (I couldn’t use the latest last_updated from each record).  It worked perfect in ./script/console but failed entirely through the browser.

ruby csv to structured hash

I had a csv like this:

object color flavor shape
apple red sweet round
banana yellow sweet long
lemon yellow sour round

and I wanted a ruby hash structured like this:

{
'apple'=> { 'color'=>'red',  'flavor'=>'sweet', 'shape'=>'round'},
'banana'=> {  'color'=>'yellow',  'flavor'=>'sweet', 'shape'=>'long'},
'lemon'=> {   'color'=>'yellow',  'flavor'=>'sour', 'shape'=>'round'}
}

So I wrote this, which does the job:

require "faster_csv"

def csv_to_structured_hash
	arr_of_arrs = FasterCSV.read( 'your.csv' )
	stuff = {}
	header = arr_of_arrs.shift
		arr_of_arrs.each_with_index do |row, i|
		thing = { row[0] => {} }
			header.each_with_index do |col, header_index|
			thing[ row[0] ][ header[header_index] ] = row[ header_index]
			end
		stuff.update( thing )
		end
	return stuff
end

Django Tango

 
icon for podpress  Django Tango: Play Now | Play in Popup | Download

A Django Reinhardt and David Grisman fusion.

multitrack mandolins, nylon guitars,  and percusion.

Ruby conversion module

This is a ruby module useful for conversions dealing with length, weight, torque.

module Convert

  def Convert.number_with_precision(number, precision=2)
    "%01.#{precision}f" % number
  rescue
    number
  end

  def Convert.mm_to_in(mm, precision=2)
    number_with_precision(mm * 0.03937, precision)
  end

  def Convert.in_to_mm(inches, precision=2)
    number_with_precision(inches / 0.03937 , precision)
  end


  def Convert.feet_to_meters(f, precision=2)
    number_with_precision( f * 0.3048, precision)
  end

  def Convert.meters_to_inches(m, precision=2)
    number_with_precision( m * 39.37, precision)
  end

  def Convert.meters_to_feet(m, precision=2)
    number_with_precision( m * 3.281, precision)
  end

  def Convert.kg_to_lbs(kg, precision=2)
    number_with_precision( kg * 2.2   , precision)
  end

  def Convert.lbs_to_kg(lbs, precision=2)
    number_with_precision( lbs / 2.2   , precision)
  end

  def Convert.nm_to_inch_pounds(nm, precision=1)
    number_with_precision( nm * 8.850   , precision)
  end

  def Convert.inch_pounds_to_nm(inlb, precision=1)
    number_with_precision( inlb / 8.850   , precision)
  end

end

Rails redirect_to :back in Internet Explorer

Today I realized that the rails command   redirect_to :back  does not work in Internet Explorer because  redirect_to :back  depends on HTTP_REFERER, which IE does not do.  I was capturing an onclick event with jQuery and was able to sending along the  current URL as a query string, which provided an easy way around this limitation.

In the view:

<script>
    $jQuery('#myLink').click(function(){
        window.location.href = 'theDestinationPage/?current_url=' + document.location ;
    })
</script>

In the controller:

def myAction
    .....
    redirect_to params[:current_url]
end

Rails background process - simple, fast, easy.

My situation was this -

  • Rails 2.0 app running on slicehost (ubuntu 8.04) in passenger mod_rails
  • The goal was Dynamic PDF generation for a product catalog ( > 100 pages)
  • This event had to be triggered from within the rails request / response cycle, but run outside of it
  • I needed the simplest, fastest, more reliable way for this to happen

I looked at BackgroundRB, it is the most robust, well documented solution available.  But it was overkill since I didn’t need status feedback and my time was very limited (backgroundRB setup seems somewhat involved).  And, I wasn’t sure how it would interact with Passenger mod_rails - although FooBarWidget mentioned on IRC that it should work as expected.

I looked at Spawn plugin which supports threading and forking ruby processes.   No luck - setting it one way never ran inside mod_rails and setting it the other way tied up the request response cycle.

All the ruby code was in place, except for how to detach this process from the request/response cycle, when severnspoon provided this
Simple, Easy, One-Line Solution:

My_Controller
  def generate_pdf_in_background
    system " RAILS_ENV=#{RAILS_ENV}   ruby  #{RAILS_ROOT}/script/runner   'MyModel.create_pdf_in_background'  &
  end
end

That ampersand was all I needed.  It runs the command as a background process.  A new ruby process is kicked off, and the 10 minute task runs perfectly.  Something makes the browser hang and wait for a response, but we confirmed that other requests can happen along side this.

Point

 
icon for podpress  Point: Play Now | Play in Popup | Download (20)

mod_rails set RAILS_ENV variable to QA, Staging, or Production

I’m using mod_rails with capistrano and multi-stage (qa, staging, production), and wrote this workaround so that the RAILS_ENV could be set correctly in each stage.  Mod_rails sets RAILS_ENV once in the global server conf file, but I needed it set once for each environment: qa, staging, and production.  I tried setting ENV['RAILS_ENV] in each file under config/deploy/ but the setting was not picked up.

Solution - write the correct value into config/environment.rb’s  ENV[''RAILS_ENV] while deploying.

So here is my 3 step fix -

Step 1.

I created a new file

lib/set_mod_rails_env.rb

# sets ENV['rails_env'] for mod_rails
# http://www.megasolutions.net/ruby/search-a-file-and-replace-text-50116.aspx
# Robert Evans'
def ChangeOnFile(file, regex_to_find, text_to_put_in_place)
  text = File.read file
  File.open(file, 'w+'){|f| f << text.gsub(regex_to_find,
      text_to_put_in_place)}
end
ChangeOnFile("#{ARGV[0]}/config/environment.rb”, /#mod_rails_env_here/, “ENV['RAILS_ENV']=’#{ARGV[1]}’”)

Step 2.

Add the following code to config/deploy.rb

namespace :deploy do
desc "set ENV['RAILS_ENV'] for mod_rails”
task :before_restart do
run "ruby #{current_release}/lib/set_mod_rails_env.rb  #{current_release}  #{stage}"
end
end

Step 3.

Add the following code to config/environment.rb

# deploy.rb will swap this out for the appropriate rails_env.
# mod_rails apparently need this var in this file (not ./environments/qa.rb)
# do not change the following line. Ruby regexp looks for it.
#mod_rails_env_here

That’s it.  Let me know if you know of an easier way.

jQuery validation with Prototype

Here is the jQuery validation plugin fixed up so that it works if you have prototype installed along side jQuery.  I just replaced references to $() with jQuery() in the jQuery.validations.js file.
jquery.validate.js with prototype

Next Page »