Posts tagged Ruby

Feb 28, 2010

Ruby whenever and day of month crontab syntax

Ruby cron | comments

Whenever by Javan Makhmali is an excellent way to manage the cron tasks that relate to your ruby app. It provides a very powerful and readable ruby syntax for planning a job schedule.

I had a hard time figuring out how to recreate the case of running a job on a specific day per month, however. The following crontab line is an example of running a job on the first day of month every month at 7:13am:

# .---------------- minute (0 - 59) 
# |  .------------- hour (0 - 23)
# |  |  .---------- day of month (1 - 31)
# |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ... 
# |  |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7)  OR sun,mon,tue,wed,thu,fri,sat 
# |  |  |  |  |
# *  *  *  *  *  command to be executed
  13 7  1  *  *  my_funky_command

The key to understanding the possible syntax is understanding that chronic is whenever’s underlying natural date and time parser. So the whenever syntax for the above cron definition is most elegantly:

every 1.month, :at => 'start of the month at 7:13am' do
  runner 'my_funky_command'
end

Running a job on days other than the beginning or ending of the month is not so straightforward. This GitHub issue explains it best. To running the same command every month at the same time, but on the 15th of the month:

every 1.month, :at => 'January 15th 7:13am' do
  runner 'my_funky_command'
end

‘January’ will be ignored as whenever parses the monthly job into its pieces.


Feb 28, 2008

Move server configuration files into your repository

capistrano rails ruby scm svn Ruby Rails SVN SCM Capistrano | comments

Dung repository
 
Photo by Chambo25

Are you a programmer? Do you hate any process that involves SSH’ing into a server and editing files directly in production? Would you like to get rid of this non-source controlled hackery? Damn right you would!

If you’re deploying an application to a server, get those app-specific configuration files in your source control system! I happen to be a Ruby on Rails programmer, so the two files I’m looking to control are the Apache and Mongrel configuration files. Here are two sample locations:

Maruku could not parse this XML/HTML: 
<pre>/usr/local/apache2/conf/apps/appname.conf
/etc/mongrel_cluster/appname.yml

Meat

Via terminal, browse into your local Rails app directory. Then, create a couple directories to store this configuration:

mkdir ./config/apache
mkdir ./config/mongrel

Then copy the configuration files you have sitting on your server into the local directory (I’m using SCP and assuming you know the rest). Again, locally:

scp bjhess@server_or_ip:/usr/local/apache2/conf/apps/appname.conf ./config/apache/
scp bjhess@server_or_ip:/etc/mongrel_cluster/appname.yml ./config/mongrel/

Potatoes

Now you’re all ready to commit these configuration repositories to your SVN/git/mercurial repository. But wait, you also want to actually use these versions of the configuration files in production, no? Well, let’s do it. Rename the original configuration files on the remote server:

mv /usr/local/apache2/conf/apps/appname.conf /usr/local/apache2/conf/apps/appname.conf.bak
mv /etc/mongrel_cluster/appname.yml /etc/mongrel_cluster/appname.yml.bak

Then simply update your deployment script to create symlinks from the expected configuration file location to the new location. I’m using Capistrano (version OLD), so adjust accordingly:

desc "Tasks to complete after code update"
task :after_update_code do
  #            LINK TARGET                                   LINK SOURCE
  run "ln -nfs #{current_release}/config/apache/appname.conf /usr/local/apache2/conf/apps/appname.conf"
  run "ln -nfs #{current_release}/config/mongrel/appname.yml /etc/mongrel_cluster/appname.yml"
end

Conclusion

This is great, isn’t it? The programmer in you loves having limitless history of configuration changes, not to mention the ability to use whatever local editor you choose. Wonderful day!

But what about the whole-server configuration files? Unless you commit to one app per server, I don’t think base Apache config files or server-level logrotate config files should be in a specific app’s repository. Perhaps a new repository could be setup to deal with these files? I imagine Capistrano could even be used for the bare-bones deployment.

Or maybe just backing up these general files is enough to keep your mind at ease. Just be sure to think about it. That’ll put you one step ahead of the rest

Update: Be sure to deal with symlinks upon rollbacks, something I just got burnt by:

desc "Tasks to complete after code rollback"
task :after_rollback do
  run "ln -nfs #{previous_release}/config/apache/appname.conf /usr/local/apache2/conf/apps/appname.conf"
end

Feb 19, 2008

Calling MailBuild AddWithCustomFields with Ruby

MailBuild Ruby SOAP | comments

Today I had a fun trial-and-error exploration of Ruby SOAP messaging. By “fun” I mean “hair-rippingly excruciating.”

Basic SOAP calls are pretty easy with the wsdlDriver inherent in Ruby. Here’s how you’d wrap MailBuild’s Subscriber.Add function in Ruby:

require 'soap/wsdlDriver'

class MailBuildWrapper

  attr_accessor :api_key, :list_id

  def initialize(api_key, list_id)
    @api_key = api_key
    @list_id = list_id
  end
  
  def add_subscriber(user)
    soap     = wsdl.create_rpc_driver
    response = soap.addSubscriber \
                 :ApiKey       => api_key, 
                 :ListID       => list_id, 
                 :Email        => user.email,
                 :Name         => user.full_name
    soap.reset_stream
    response.subscriber_AddWithCustomFieldsResult
  end

  private

    def wsdl
      SOAP::WSDLDriverFactory.new("http://iridesco.createsend.com/api/api.asmx?WSDL")
    end

end

Calling a simple add subscriber is, well, simple.

u  = User.find(:first)
mb = MailBuildWrapper.new
mb.add_subscriber(u)

Adding with custom fields is different. This is because an array of “SubscriberCustomField” objects is necessary. Finding the magic Ruby incantation to build this SOAP array was a trick. I never found anywhere that said how to do this - Google was not my friend. Here is an example MailBuildWrapper method adding a subscriber with an ‘is_admin’ custom field:

def add_with_is_admin_custom_field(user)
  soap     = wsdl.create_rpc_driver
  response = soap.addSubscriberWithCustomFields \
               :ApiKey       => api_key, 
               :ListID       => list_id, 
               :Email        => user.email,
               :Name         => user.full_name,
               :CustomFields => {:SubscriberCustomField =>
                 [{:Key => 'is_admin', :Value => user.is_admin?.to_s}]}
  soap.reset_stream
  response.subscriber_AddWithCustomFieldsResult
end

So the ‘CustomFields’ hash item needed to point to a hash with a ‘SubscriberCustomField’ item, which itself points to an array of hashes containing ‘Key’ and ‘Value’. So multiple custom fields would be specified as follows:

:CustomFields => {:SubscriberCustomField => 
                    [ {:Key => 'is_admin', :Value => user.is_admin?.to_s},
                      {:Key => 'is_loser', :Value => user.is_loser?.to_s}]}

Some useful links from my first experience consuming a SOAP web service with Ruby:


Jan 02, 2008

Integrating Rails and WordPress

WordPress Ruby on Rails | comments

Mad code rewrite
 
Photo by zhartley

Scrawlers, an online writing workshop I helped build, includes a blog. Rather than build the blog from scratch, or even use a Rails solution, I chose to stick with the familiarity of WordPress. I’d read enough about Rails-lovers switching to a Rails-based engine and back to WordPress that I wasn’t even going to bother leaving The WP.

Scrawlers sits on an Ubuntu server with Apache and Mongrel running. Unfortunately I have little to no server admin skill, and that includes Apache mod_rewrite. Ilya Grigorik posted an excellent HOWTO on integrating WordPress and Rails. Unfortunately it didn’t quite work for Scrawlers, and I put off figuring out my special mod_rewrite secret sauce for quite a while.

Eventually I figured out what I needed beyond Ilya’s original technique and posted it in the comments section of his blog. The completist in me needs to post the solution on my blog as well. What follows is pretty much word-for-word from Ilya’s comment section. Be sure to read his post. It’s an easier solution, if it works for you, and it provides background information for what follows.

I’m dealing with Apache configuration that I do not understand. So it turns out I have AllowOverride disabled on my server, even explicitly in my app-specific Apache configuration for the public directory. This is why .htaccess wasn’t working for me.

After reading up a bit on .htaccess/AllowOverride, I decided there was really no reason to turn it on and eat the overhead involved. Instead I made a Directory directive in my app-specific config file and placed it before my initial WordPress redirects.

Once these things were in place, the one-line RewriteRule worked in every instance except one. The URL http://www.scrawlers.com/blog (or /blog/) failed with an access denied error. Looking at the rules it sure appeared like it should work. In the end I needed to include a couple rules specific to these situations. Here is, essentially, the bit of configuration code I needed to make my blog start working naturally: