ChangingThePresent
The Few, The Proud, The Pradipta 416
CV

Moved!

bryan / 01.Jul.2009

Please steer over to artofobjects.com, where I will be migrating the articles, new postings, software, etc.. Thanks!

overhaul

bryan / 28.Jan.2009

I have not added much to the website recently because it is going through an overhaul. I am replacing Mephisto with a custom app which simplifies very basic asset uploading, ad management and article posting. Should be ready shortly. Thanks for your patience.

updates to resource_helper

bryan / 09.Oct.2008

resource_helper is currently a Rails plugin that exists to make ActiveResource more compatible with ActiveRecord as well as add some additional functionality. I made some big changes recently, check it out on github

Grr! rake and Test::Unit errors

bryan / 03.Oct.2008

This was one of those bugs that was just killing me. I absolutely could not figure out why some of my new shiny rake tasks were failing. I went through the motions of uninstalling my custom ruby and rails on my Mac and upgrading instead the system installed Ruby then reinstalling rails and all gems.

It was a lot of work, and actually I produced a neato script to help clean gems. (maybe I’ll post it up here soon)

But it didn’t fix the situation. Several hours of google and forum threads that were only somewhat related, I stumbled on an old Rails bug, wherein “require ‘test/unit’” was being called by something or other. Of course it should only be called when testing and when needed. But it was unfortunately being called on EVERY rake task after anything that was called. The problem was that rake was passing the arguments to Test::Unit::AutoRunner which returned errors and generally hosed the parsing of the rake outcome (which is what I was up to).

Anyhoo, here is my workaround. Quick and dirty, but works. CaveatL only use if you are NOT using Test::Unit for anything good. (i.e. you still haven’t switched to rspec _ ) Or use the second method listed and control the monkey patch a bit.

It can be used in 1 of two ways, I prefer the latter as it gives more control.

  1. Add the module below to the project’s main Rakefile
  2. Add a file to lib called “_rake_helper.rb” and paste the module in there.
For 2., use it in any Rakefile needing to avoid the Test::Unit clash by requiring it

 require 'lib/tasks/_rake_helper'
 include RakeHelper

Here is the module:


 module Test
   module Unit
     class FakeAutoRunner
       class <<self
         def run
           return true
         end
       end
     end
     begin
       silence_warnings do
         const_set("AutoRunner", FakeAutoRunner)
       end
     rescue
     end
   end
 end

many updates

bryan / 05.Sep.2008

Lots of updates to the application_configurator plugin. Check it out on git http://github.com/rubyisbeautiful/application_configurator/wikis

Also, some rake tasks for refactoring our migrations, on pastie for sake http://pastie.org/266855 do stuff like check for tables with no models, models with no tables, etc…

rake refactor:db # Refactor the database with migrations rake refactor:models # Look for models with no matching table rake refactor:schema # Look for tables in the schema that don’t exist rake refactor:tables # Look for tables that have no matching models

released: resource_helper plugin

bryan / 23.Aug.2008

A very basic version of resource_helper as Rails plugin only is live on github

resource_helper plugin

bryan / 13.Aug.2008

I am about to release resource_helper plugin. I wrote in while working on my client’s project and it has become invaluable to our team. It attempts to bridge the small gaps between ActiveRecord and ActiveResource and make them quack nearly the same. It also adds some convenience methods which I found myself rewriting for every new ActiveResource. I hope to release it by the end of the day today.

Update: plugin released on github

Hehe, my new acronym for god.

The config suggestion I posted earlier works in theory, but I was having some trouble getting it to work from init

What I ended up having to do was add

sleep
after some steps of the god init. Multiple sub-config loading from a main config file just wasn’t going to work. I’m am sure there is a better way, but this works for the time being, until I have more free time to work on Unrud itself.


# v.0.0.3
# cobbled by Bryan Taylor http://rubyisbeautiful.com
# god - Start/stop/check Unrud via init 
#
# chkconfig: - 85 15
# description: http://god.rubyforge.org/
# processname: god
# config: /etc/god.conf

# Source function library.
. /etc/rc.d/init.d/functions

# Source networking configuration.
. /etc/sysconfig/network

# Check that networking is up.
[ ${NETWORKING} = "no" ] && exit 0

[ -x /usr/bin/god ] || exit 0

RETVAL=0
prog="god" 

start() {
# Start daemon only
echo -n $"Starting $prog: " 
/usr/bin/god
sleep 5
  RETVAL=$?
  [ $RETVAL -eq 0 ] && {
     touch /var/lock/subsys/$prog
     success $"$prog" 
  }
  echo

#load the configs
if [ -e /u/apps/content/current/config/content.god ] ; then
  echo -n $"Loading content config: " 
  /usr/bin/god load /u/apps/content/current/config/content.god
  echo -n $"Loading admin config: " 
  /usr/bin/god load /u/apps/admin/current/config/admin.god
  sleep 5
  RETVAL=$?
  [ $RETVAL -eq 0 ] && {
     touch /var/lock/subsys/$prog
     success $"$prog" 
   }
   echo
else
  RETVAL=1
fi
return $RETVAL  
}

stop() {
    # Stop daemons.
    echo -n $"Shutting down $prog: " 
    /usr/bin/god quit &
        sleep 5
    RETVAL=$?
    echo
    [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/$prog
    return $RETVAL
}

reload() {
    echo -n "$reloading $prog config: " 
        /usr/bin/god load /u/apps/content/current/config/content.god
        /usr/bin/god load /u/apps/admin/current/config/admin.god
}

# See how we were called.
case "$1" in
    start)
      start
      ;;
    stop)
      stop
      ;;
        reload)
            reload
        ;;
    restart)
      stop
      start
      ;;
    status)
      /usr/bin/god status
      RETVAL=$?
      ;;
    *)
      echo "Usage: god {start|stop|reload|restart|status}" 
      exit 1
  ;;
esac      
exit $RETVAL

Also, I modified the init script a little, as god doesn’t quite behave like a typical *nix daemon.

Update:

via Twitter from Ivey: updates pushed to rubyforge.

I just checked and all is well; still, follow the advice below to get using git.

If you follow the merb core development, you’ll see that Ivey pushed 0.9.3 gems. Unfortunately it appears temporarily broken via the default install from rubyforge. For now, if you haven’t already hooked up to github and merb, now is the perfect time.


> git clone git://github.com/wycats/merb-core.git
> cd merb-core
> rake install
> cd ..
> git clone git://github.com/wycats/merb-more.git
> cd merb-more
> rake install

However poor the taste of the author in choosing a name, it is indeed a great way to monitor, nay, control pretty much anything.

I use god on my local dev box (mac) as well to keep all things developery running.

I got the init script from http://ezinearticles.com/?Why-Rails-Developers-Need-God&id=845672 and all the good info from http://god.rubyforge.org/

Handily, a god init script will of course start your mongrels et al when properly configured. Here is how I use a config template for the many gods-mongrels


host = `hostname`
app = "foo" 

case
when host =~ /theproductionbox/
  ports = %w{ 6400 6401 } 
  RAILS_ROOT = "/u/apps/#{app}/current" 
  shared_path = "/u/apps/#{app}/shared" 
  mongrel_cmd = "/usr/local/bin/ruby /usr/local/bin/mongrel_rails" 
  pid_dir = "#{shared_path}/pids" 
  log_file = "#{shared_path}/log/mongrel.log" 
  uid = 'production_guy'
  gid = uid
  ENV['RAILS_ENV'] ||= 'production'
  rails_env ||= ENV['RAILS_ENV']
  http_host = "fancy.productionbox.com" 
  http_path = "/" 
  http_code = "200" 
when host =~ /somedevbox/
  ports = %w{ 6400 } 
  RAILS_ROOT = "/u/apps/#{app}" 
  shared_path = "/u/apps/#{app}" 
  mongrel_cmd = "/usr/local/bin/ruby /usr/local/bin/mongrel_rails" 
  pid_dir = "#{shared_path}/tmp/pids" 
  log_file = "#{shared_path}/log/mongrel.log" 
  uid = 'development_guy'
  gid = uid
  ENV['RAILS_ENV'] ||= 'development'
  rails_env ||= ENV['RAILS_ENV']
  http_host = "ratbike.devbox.com" 
  http_path = "/" 
  http_code = "200" 
end

ports.each do |port|
  God.watch do |w|
    w.group = app
    w.uid = uid
    w.gid = gid
    w.name = "#{app}-mongrel-#{port}" 
    w.interval = 30.seconds
    w.start = "#{mongrel_cmd} start -d -a 0.0.0.0 -p #{port} -P #{pid_dir}/dispatch.#{port}.pid -e #{rails_env} -c #{RAILS_ROOT} -l #{log_file}" 
    w.stop = "#{mongrel_cmd} stop -P #{pid_dir}/dispatch.#{port}.pid" 
    w.start_grace = 30.seconds
    w.restart_grace = 30.seconds
    w.pid_file = File.join(pid_dir, "dispatch.#{port}.pid")

    w.behavior(:clean_pid_file)

    w.transition(:init, { true => :up, false => :start }) do |on|
      on.condition(:process_running) do |c|
        c.running = true
      end
    end

    w.transition([:start, :restart], :up) do |on|
      on.condition(:process_running) do |c|
        c.running = true
      end
      on.condition(:tries) do |c|
        c.times = 5
        c.transition = :start
      end
    end

    w.transition(:up, :start) do |on|
      on.condition(:process_exits)
    end  

    w.transition(:up, :restart) do |on|
      on.condition(:memory_usage) do |c|
        c.interval = 60.seconds
        c.above = 57.megabytes
        c.times = [4, 5]
      end
      on.condition(:cpu_usage) do |c|
        c.interval = 60.seconds
        c.above = 10.percent
        c.times = [3, 5]
      end
      on.condition(:http_response_code) do |c|
        c.host = http_host
        c.path = http_path
        c.code_is_not = http_code
        c.timeout = 30.seconds
    c.interval = 30.minutes
      end
    end

    # lifecycle
    w.lifecycle do |on|
      on.condition(:flapping) do |c|
        c.to_state = [:start, :restart]
        c.times = 5
        c.within = 5.minute
        c.transition = :unmonitored
        c.retry_in = 10.minutes
        c.retry_times = 5
        c.retry_within = 2.hours
      end
    end
  end
end

God::Contacts::Email.message_settings = {
  :from => 'god@rubyisbeautiful.com'
}

God::Contacts::Email.server_settings = {
  #settings
}

God.contact(:email) do |c|
  c.name = 'bryan'
  c.email = 'bryan@rubyisbeautiful.com'
end
		
		
	

making errors better

bryan / 24.Apr.2008

First, I haven’t written in awhile. Like many bloggers that I follow, success in one area diminishes my capacity in other areas. My contracting business is doing very well. More than that however, I don’t like to waste space or mince words on my blog, as you have already noticed. I won’t write unless I have something that I think is worth sharing; I won’t write just to keep a fresh article in the feeds.

I have been doing a lot of debugging – mostly of the needle-in-a-haystack variety. Simultaneously I am working on a new, re-engineered version of the legacy app I am debugging. So I have the opportunity to do some things “right” this time (I didn’t write the legacy app, and the developer who did is AWESOME and a friend. I am not criticizing the code here. What always happens is the problems and business rules become clearer as the project matures, giving rise to an opportunity to craft a better model)

There are of course great plugins to do some of this, and more. I personally have found that in some cases less is more and projects that rely to heavily on 3rd party code may end up paying for at debug time.

Here are some tweaks to errors and whatnot that I use:

1. extend StandardError with a simple to_xml method, for use in ActiveResource and pretty much anywhere:

class StandardError
  def to_xml
    return <<-ENDOFDOC
      <error type='#{self.class.to_s}'>
        <message>#{message}</message>
      </error>
    ENDOFDOC
  end
end
1.5. UPDATE: I also added a status method, since I use resources so heavily.

@status=400 #its never the server's fault
attr_accessor :status
and in the custom errors mentioned below, change as needed:

LocalApplication::SomeParameterIsMissing.new.status # => 406

This works nicely for StandardError and any descendent classes that don’t already have a to_xml method. For ActiveRecord:: and some other error classes, there is a to_xml which will override this one.

2. put a general error handler in ApplicationController


def handle_error(err=nil)
  begin
    if err.nil?
      @error = GenericNilError.new("Oops, something happened...")
    else
      @error = err
    end
    respond_to do |flavah|
      flavah.xml { render :xml => @error.to_xml, status => 500 and return false }
      flavah.html  # a template for error
    end
  rescue StandardError => e
    # some failsafe that hits a static
    render :nothing => true, :status => 500 and return false
  end
end
3. use local errors As in the example above, roll your own errors. Then you respond in customized ways. If you’re not already rescuing different kinds of errors and handling them in unique ways, you may want to explore that.

module LocalApplicationError
  class GenericError < StandardError ; end
  class ShouldNeverHappenError < StandardError ; end
  # etc...
end
4. have an error log So much better than scrolling through #{RAILS_ENV}.log

err_logger = Logger.new #customize how you want it
[ActiveRecord ActiveResource ActionController].each do |mod|
  mod.module_eval <<- ENDOFMONKEY
    include LocalApplicationError #why not throw this in there too, see #3 above
    @err_logger = err_logger
    mattr_reader :err_logger
  ENDOFMONKEY
end

5. Use specs so you don’t raise unknown errors!

new sites for merb docs

bryan / 31.Mar.2008

I recently created merbdoc.com (a.k.a. merbapi) to help the Merb community out. Let me know how if its useful, or how I can improve it. Its brand new, so it might be down for the next day or so.

Here’s a very easy way to change the default render format. Its not necessarily the best way for you. Consider that rendering HTML is hardcoded in the code and it is probably default in the browser/client’s Accept header.

rails/action_pack/lib/action_view/base.rb


when parameter_format.blank? && accept_format != :js
          @template_format = :html

For my usage, the best way to change was to add a method to application.rb and call it as a before filter (either by default in application.rb or as needed in each controller) (updated to a better way)


protected
def set_request_header
    xml_string = 'application/xml'
    request.instance_eval("@accepts=Mime::Type.lookup('#{xml_string}')")
    request.headers['HTTP_ACCEPT']  = xml_string
    request.env['HTTP_ACCEPT']      = xml_string
end

it’s not really “playing nice” but it works and is easy to debug and undo

and now for a break

bryan / 21.Mar.2008

Its Spring Break, which means nothing to me other than that my kids are home from school. Work is difficult. This week instead of carelessly crafter semi-digested thoughts on Ruby et al., I bring you a picture from railsblog

quick tip: bash profile

bryan / 13.Mar.2008

If you use a Unix-like development environment, this may be helpful. Here's some snippets from my .bash_profile on Leopard.


function wo {
  cd "/Users/bryan/apps/$1";
}
function devcon {
 eval script/console $1;
}
function testcon {
 eval "script/console test $1";
}
function prodcon {
 eval "script/console production -s $1";
}
function prodcon_live {
 eval "script/console production $1";
}

So I get something to go to a certain project I'm working on and use the console quickly.


bash:~> wo merb-core
bash:/Users/bryan/apps/lazy_developer> devcon
>>

It saves a lot of typing.

back to top

micro theme by seaofclouds, and powered with Mephisto Hosting by hostingrails.com