First, add the asset_sync gem to your Gemfile inside the assets group, and bundle install it
Go to /config/application.rb, append any custom js and/or css files to the precompile list
Edit /config/environments/production.rb to add the asset_host option
Run the following to generate the asset_sync initialis(z)er. Tweak the config as your wish.
Next up, add all necessary AWS credentials as ENV vars
One thing to notice is the FOG_DIRECTORY value. It is the bucket name you created on S3. I was using _ in the bucket name, asset_sync or fog to be specific was complaining about the name. Updating the bucket names to use . instead of _ muted all the noises.
I also configured the above 3 ENV vars on Heroku, but I think only FOG_DIRECTORY is required.
Now, precompiling assets locally by doing
The above will put all the compiled assets in /public/assets. Now we need to make git happy.
First, stage and commit /public/assets/manifest.yml. Then edit .gitignore by adding
This will make git track the asset manifest, but ignore all the other compiled asset files (coz they are already uploaded to S3 as a post asset compilation step by asset_sync).
All good, all working… But wait a second … Now when developing locally, compiled assets from /public/assets are all loaded … trouble !!!
I haven’t written any blog posts for a while. I was either busy hacking Objective-C or just being sick instead …
Here’s one Ruby thing I did today. Nothing fancy, just pagination using Kaminari
After adding the Kaminari gem in the Gemfile and bundle install, we start from the controller. All we needed to do is to chain the page(params[:page]) method call after the ordered scope
Next up, adding the pagination HTML to the view
To finish it off, some coffeescript to listen on the new pager links
A side note, yesterday, Symfony master Fabien Potencier wrote a post PHP is much better than you think. It stirred up quite some controversy. As someone who worked with PHP for a good 6 to 7 years before moved on doing Ruby, my response is simple. Putting aside how good or bad PHP and its entire ecosystem is, the ease of use from Ruby and all these Ruby gems beats PHP hands down …
Ruby 1.9.3 uses a more restrict YAML parser, Psych, instead of the old Syck parser. This caused me issues when using Settingslogic. Even doing what suggested by Settingslogic to set the YAML parser back to Syck didn’t help.
A simple test script
Running it under Ruby 1.9.3 outputs this
You could see “development” lost its “bang” hash key.
There are ways to get around the issue by re-building Ruby with libyaml flag. I consider this as harmful than helpful. So I reverted my application.yml back to its very dumb form, no default options, no merging, just duplicate all settings for all environments. It’s definitely stupid to do so, but for now, it’s considered as a temporary workaround.
I explained how I setup Ruote and RabbitMQ in last post. From there on, you basically already have a working system. All there’s left is to have external services subscribe to the RabbitMQ job queues, parse the workitem JSON, do whatever and post the modified/amended JSON back to RabbitMQ, default queue is named “ruote_workitems”, which is what the RuoteAMQP receiver listens on.
In this post, I’ll demonstrate how a DaemonKit generated daemon script consumes the RabbitMQ job messages and how we construct a DaemonKit compatible Ruote process definition.
Generate DaemonKit project
Make daemon listen to correct AMQP queues by editing ruote.yml config
Edit participant class by adding the following 2 methods
Let’s start everything up
Now let’s work out how we wire everything up by carefully crafting a process definition.
Then launch it! If everything goes well(it should!), you’ll see no processes listed under the ruotekit app interface. And you’ll have 4 queues listed under RabbitMQ’s management interface.
email_job, 0 job
ldap_job, 0 job
notify_job, 1 job
ruote_workitems, 0 job
By popping the message out of the notify_job queue, you’ll see the serialised JSON string contains ldap done and email done key-value pairs. It shows me the job is done, and all participants are exercised correctly.
Now, we go back a step and explain a little on the process definition we crafted.
If a remote participant will be processed by a DaemonKit daemon script, we need to give each of those participants a hash, which contains a :command key. The value for :command key needs to follow a certain convention too. The convention is “/participant_class_name/method_name”. DaemonKit will classify and constantize “participant_class_name” in to ParticipantClassName object, and “method_name” will be sent to it. So in our example, when the daemon script sees command “/sample/ldap”, it’ll invoke a call to “Sample#ldap”.
The value we entered into the workitem fields textbox is simply be merged into the initial workitem hash, and it’ll be sent along to all participants.
That is it. Hope it all makes sense, and please tweet me if you found I’ve got any bits laid out wrongly or explained wrongly.
At MYOB, I am assigned the task to build a component based workflow application. There are several requirements this application has to address. Here are a few
Every single piece of the application needs to be scalable
A messaging based system becomes somewhat a natural choice to address the decoupling, distributable and scalable issue. While in the hunt of a good workflow system, I was pointed to a Ruby gem called Ruote by @jmettraux. Ruote has also got several companion gems. One of them is ruote-amqp.
Rails Sample Ruote AMQP is the most complete example I could find on Github. This excellent sample project almost covers all aspect. However its Rails default README file doesn’t do its justice. I had to dig hard to figure out how all the pieces are put together.
Enough mumbling from me. The following are the steps I implemented to get an end-to-end Ruote + RabbitMQ going on my MBP. As prerequisites, I have Homebrew and RVM installed.
This is rather simple with the help from Homebrew.
Add ruote kit initializer. As you could see, the file shown is a work in progress.
Add ruote worker rake task
Last not least, mount RuoteKit to our Rails app by adding the following to the routes file
This completes first half of the story. We now have a running RabbitMQ instance with admin monitoring, and a RuoteKit enabled Rails app. The Rails app has several RuoteAMQP participants registered, a ruote rake task ready to run Ruote workers, and of course the RuoteKit rack app that allows us to manually launch Ruote jobs.
In the next post, I’ll complete the full picture by implementing a DaemonKit generated Ruote daemon script, which processes the AMQP jobs published by the ruote worker running on the Rails app side.
One night, I was studying some code written by Aleksey. I spotted his usage of Ruby string’s “%” notation. It shows me how elegant Ruby can be, given knowing all those Ruby basics.
To confess, I learned (and still learning) Ruby from learning Rails. At this moment, I defintely think it’s a bad idea! Basics should always be taught/learned before the magical frameworks. So, I’ll start a series of posts to go through some of these basics.
Ruby string % notation
%Q - Interpolated string. Character used after %Q will be used as the new string delimeter, hence it should be balanced. This makes normal string delimeters such as “ and ‘ become auto-escaped. If the new delimeter also appears in the string, it only needs to be manually escaped if it’s unbalanced.
%r - Similar to %Q, but constructs a Regexp object. No need to escape those slashes!
%W - Feed it with a string of words separated by spaces, get back an array of words.
%x - Interpolated shell commands. Same as using backticks.
Because OS X crashes every 2nd day, I thought it’s time to give Ubuntu another good spin. First task is to setup my Ruby working environment.
On a fresh Ubuntu 11.10 VM, I firstly installed curl and git via apt-get
I then installed RVM using the normal RVM installation command
Then I tried to install Ruby 1.9.3, I ran into all sorts of issues, readline not available, yaml failed to build, etc. After some fooling around, I found that all I needed to do was to RTFM! Running the following gives me all required packages needed to install an MRI (and others) ruby…
Believe or not, after doing the sudo apt-get install line from rvm requirements, RVM is happy as!
Lesson learnt: before start blaming a tool (especially a free one!), let’s check what the README says first!