Archive

Archive for the ‘Gems’ Category

Converting attachment_fu to Paperclip

October 1st, 2009 mindtonic No comments

I am making the transition from attachment_fu to paperclip on a very large project of mine. I wrote the following method, inside of my old attachment_fu model ItemImage to do the work. I wrote it to run from inside the rails console. It gives handy messages out letting you know what happened. In my case you run:

$ script/console
>> ItemImage::convert_fu
def self.convert_fu
  for item in Item.all
    # has an image
    if item.item_image
      # the image exists
      filename = "public" + item.item_image.public_filename
      if File::exists?(filename)
        image = File.open(filename)
        item.image = image
        item.save
        puts "#{item.name} Image Converted"
      else
        puts "====> #{item.name} Image could not be found"
      end
    else
      puts "#{item.name} has no image"
    end
  end
end

Reference: http://thewebfellas.com/blog/2008/11/2/goodbye-attachment_fu-hello-paperclip

Categories: Gems, Ruby On Rails Tags: ,

Calendar Date Select Magic For Rails

July 27th, 2009 mindtonic No comments

Calendar Date Select is a new(ish) “date and time picker”, developed by Tim Harper, designed primarily for developers to use in Rails applications. It uses the standard Prototype JavaScript library, and is easily installed as a Rails plugin:

script/plugin install http://calendardateselect.googlecode.com/svn/tags/calendar_date_select

The demo seems to be down, but here is some more detailed info: http://ianli.com/site/HowTo/UseCalendarDateSelectRailsPlugin. You can also see the original contents of the demo site about halfway down the Google Code wiki for the project: http://code.google.com/p/calendardateselect/wiki/CalendarDateSelect

On the surface this is a very easy plugin to install and use. It seems the common problem is that there is very little documentation available and the demo server is down. After installing the gem, I was able to run “gem server” and view the rdoc for the plugin. A couple of things I thought would be helpful to repost here:


Form Helpers:

calendar_date_select(object, method, options={})

Similar to the difference between text_field_tag and text_field, this method behaves like text_field

It receives the same options as calendar_date_select_tag. Need for time selection is automatically detected by checking the corresponding column meta information of Model#columns_hash

calendar_date_select_tag( name, value = nil, options = {})

Similar to text_field_tag, but adds a calendar picker, naturally.
Arguments

  +name+ - the html name of the tag
  +value+ - When specified as a string, uses value verbatim.  When Date, DateTime, Time, it converts it to a string basd off the format set by CalendarDateSelect#format=
  +options+ - ...

Options
:embedded

Put the calendar straight into the form, rather than using a popup type of form.

  <%= calendar_date_select_tag "name", "2007-01-01", :embedded => true %>

:hidden

Use a hidden element instead of a text box for a pop up calendar. Not compatible with :embedded => true. You‘ll probably want to use an onchange callback to do something with the value.

  
  <%= calendar_date_select_tag "hidden_date_selector", "", :hidden => "true", :onchange => "$('cds_value').update($F(this));" %>

:image

Specify an alternative icon to use for the date picker.

To use /images/groovy.png:

  <%= calendar_date_select_tag "altered_image", "", :image => "groovy.png" %>

:minute_interval

Specifies the minute interval used in the hour/minute selector. Default is 5.

  <%= calendar_date_select_tag "month_year_selector_label", "", :minute_interval => 15 %>

:month_year

Customize the month and year selectors at the top of the control.

Valid values:

 * "dropdowns" (default) - Use a separate dropdown control for both the month and year
 * "label" - Use static text to show the month and the year.

   <%= calendar_date_select_tag "month_year_selector_label", "", :month_year => "label" %>

:popup => ‘force‘

Forces the user to use the popup calendar by making it‘s text-box read-only and causing calendar_date_select to override it‘s default behavior of not allowing selection of a date on a target element that is read-only.

  <%= calendar_date_select_tag "name", "2007-01-01", :popup => "force" %>

:time

Show time in the controls. There‘s three options:

 * +true+ - show an hour/minute selector.
 * +false+ - don't show an hour/minute selector.
 * +"mixed"+ - Show an hour/minute selector, but include a "all day" option - allowing them to choose whether or not to specify a time.

:year_range

Limit the year range. You can pass in an array or range of ruby Date/Time objects or FixNum‘s.

  <%= calendar_date_select_tag "e_date", nil, :year_range => 10.years.ago..0.years.from_now %>
  <%= calendar_date_select_tag "e_date", nil, :year_range => [0.years.ago, 10.years.from_now] %>
  <%= calendar_date_select_tag "e_date", nil, :year_range => 2000..2007 %>
  <%= calendar_date_select_tag "e_date", nil, :year_range => [2000, 2007] %>

CALLBACKS

The following callbacks are available:

 * before_show / after_show
 * before_close / after_close
 * after_navigate - Called when navigating to a different month. Passes first parameter as a date object refering to the current month viewed
 * onchange - Called when the form input value changes

  <%= calendar_date_select_tag "event_demo", "",
    :before_show => "log('Calendar Showing');" ,
    :after_show => "log('Calendar Shown');" ,
    :before_close => "log('Calendar closing');" ,
    :after_close => "log('Calendar closed');",
    :after_navigate => "log('Current month is ' + (param.getMonth()+1) + '/' + (param.getFullYear()));",
    :onchange => "log('value changed to - ' + $F(this));"

}}}

All callbacks are executed within the context of the target input element. If you‘d like to access the CalendarDateSelect object itself, you can access it via "this.calendar_date_select".

For example:

  <%= calendar_date_select_tag "event_demo", "", :after_navigate => "alert('The current selected month is ' + this.calendar_date_select.selected_date.getMonth());" ,

For use with Form Builders

calendar_date_select(method, options = {})


Controllers:

In my application, I am using a custom form builder, so I used the calendar_date_elect with the form builder. The options hash appears to be the same as in the other view tags, so I just passed along what I needed:

<%= f.calendar_date_select "date", :embedded => true, :year_range => 1.year.ago..5.years.from_now, :time => false %>

I was pleased to discover that, utilizing some of the magic of Rails, the date property on my event was automatically turned into a datetime attribute, and on editing, was reloaded into the calendar as expected.

Categories: Gems, Ruby On Rails Tags: ,

Experiments in Rails Process Scheduling

July 8th, 2009 mindtonic 1 comment

I need a way to call a process on a regular basis inside of my Rails application. I have been working in and around this idea for over a year and have tried several different methods.

One thing to mention is that CRON jobs are an obvious solution to these problems. However, as I am serving off a Joyent server, I have had difficulty setting up my CRON jobs and getting them into the right file with the right RAILS_ROOT settings to my application files. If anyone knows a good way to set these up on Joyent, please let me know!

I have been reading several excellent blog posts, including Igvita.comhttp://www.igvita.com/2007/03/29/scheduling-tasks-in-ruby-rails/, and the Rails Wiki itself – http://wiki.rubyonrails.org/howtos/background-processes.

Rufus Scheduler

My current attempt is to try Rufus. I highly recommend that you examine the article Dead simple task scheduling in Rails by Brent Collier.

You can find the online documentation for the Rufus-Scheduler here: http://rufus.rubyforge.org/rufus-scheduler/

The first error I encountered in my odyssey was:

config/initializers/task_scheduler.rb:6: undefined method `start_new' for Rufus::Scheduler:Module (NoMethodError)

This was caused because I didn’t include the rufus/scheduler line at the top of my config/initializers/task_scheduler.rb file:

require 'rufus/scheduler'

I only include this oversight in case someone else happens to encounter the same error in their code.

Back To BackgrounDRb

Rufus Scheduler worked great for the simple tasks, but some of what I am trying to do has the potential to take up a lot of time. The problem I encountered with rufus was that as the time requirements grew, it was taking more and more instances from my mongrel cluster, eventually drawing the server request/response cycle to a complete stop. Not good when you are trying to host a public site!

Because I know that these processes can be time consuming, they need to be relegated to a separate server instance. So I am returning to BackgrounDRb.

My previous experiences with BackgrounDRb produced the following opinion from my own blog post:

I really like the theory and concept behind BackgrounDRb, but it seems to be a bit overkill for what I am trying to accomplish. Also, it was almost impossible to keep the BackgrounDRb server running, even with the use of Monit. There just always seemed to be something that was crashing our beloved process.

Learning from my previous experiences, I have thoroughly tested and retested the code that will be called from my workers. I am setting things up to run using the add_periodic_timer method as my first attempt. On my local machine, everything seems to be working fantastically. I plan to set everything in motion on my production server tonight and see where we sit in the morning.

The First Results

I am happy to report that with the proper configuration, and the strategic placement of begin .. rescue Exception code, BackgrounDRb is successfully performing the functions I require!

One comment that I have is that it is difficult to figure out what it is doing when. To counter this issue, I have designed a very simple background_logger to monitor the processes and let me know when things start and stop.

To do this, you first make a class for the BackgroundLogger:

From lib/background_logger.rb:

class BackgroundLogger < Logger
  def format_message(severity, timestamp, progname, msg)
    "#{timestamp.to_formatted_s(:db)} #{severity} #{msg}\n"
  end
end

Then you add awareness of this logger in your environment file:

From config/environment.rb:

background_logfile = File.open("#{RAILS_ROOT}/log/background.log", 'a')
background_logfile.sync = true
BACKGROUND_LOG = BackgroundLogger.new(background_logfile)

This adds a contstant called BACKGROUND_LOG that you can then use in your workers:

From lib/workers/foo_worker.rb:

class FooWorker < BackgrounDRb::MetaWorker
  set_worker_name :foo_worker

  def create(args = nil)
    BACKGROUND_LOG.info("Foo Worker Started")
    add_periodic_timer(5400) { do_foo }
  end

  def do_foo
    BACKGROUND_LOG.info("Starting Foo...")
    MyModel::do_foo
    BACKGROUND_LOG.info("Foo Done!")
  end
end

The resulting log output will include timestamps and such that can help you keep track of what is going on, when it happens, and in the event of a hiccup, let you know when it happened and in which file. This is of course in addition to the information provided in BackgrounDRb’s own logs.

So, BackgrounDRb is NOT the answer… what else is there?

Everything was peachy until my processes gre to be very large in number. Not good when it takes so long to do something that the machine chokes and it all grinds to a halt!

So what are my other options? Turns out that now everyone recommends delayed_job, a plugin from shopify that does the same thing only better. The folks at Engine Yard highly recommend delayed_job over backgrounDRb due to severe memory leaks and other not so favorable conditions.

I am happy to report that the results are excellent! Without even having Monit or God running, delayed_job has been kicking serious butt on my project. I think I’ll stick with it for awhile.

Monitoring All Of These Processes

The next part is to explore how to keep it all running when I run off to play music for the weekend. I know that Monit is a common choice, and having read up about it, it might be the best option. I am however, going to start with a different option… you can follow my progress in this area from my Daemon Monitoring blog post.

Cheers!

Categories: Gems Tags: , ,

Available Fields from FeedNormalizer Gem

July 8th, 2009 mindtonic No comments

The FeedNormalizer Gem does an excellent job of returning a single unified object from many of several different syndicated feed types. This saves you from having to worry about whether you are dealing with an rss, atom or some other kind of feed.

The following is a list of the available fields for both the Feed object itself and the Entries objects associated as articles in the channel.

FeedNormalizer::Feed

  • title
  • description
  • id
  • last_updated
  • copyright
  • authors / author
  • urls / url
  • image
  • generator
  • items / channel

FeedNormalizer::Entry

  • content
  • description
  • title
  • date_published
  • urls / url
  • id
  • authors / author
  • copyright
  • categories

Etags

Etags and last_modified are crucial elements to sending proper request headers if you hope to receive conditional get responses and save yourself some overhead in feed processing. FeedNormalizer does not provide access to these elements as they are actually part of the http response headers, and not the feed itself.

While heavily studying the art of feed processing, I encountered Feezirra and Feedtosis, both excellent libraries for feed processing. My own application required a modified version of their concept, but there was a lot to learn in their code.

Feedtosis uses the HttpHeaders process to collect this information from a Curl::Easy object. I adapted the Feedtosis code to meet my needs like this:

require 'http_headers'

class Feed < ActiveRecord::Base
  def store_header_information
    headers = HttpHeaders.new(curl.header_str)
    self.response_code = curl.response_code
    self.etag = headers.etag unless headers.etag.nil?
    self.last_modified = headers.last_modified unless headers.last_modified.nil?
  end
end
Categories: Gems Tags: , , ,

How To Start the Gem Server for Local Gem Rdocs

July 8th, 2009 mindtonic No comments

To view the rdoc documentation for all of your locally installed gems, at the command line run:

$ gem server

This will start the gem server at port 8808, so to access the html from your browser, use the following url:

http://localhost:8808/

Note that this only access the documentation for Gems that are installed locally on your server.

Categories: Gems Tags: ,