Archive for April, 2009

Rails Prototype JS and TinyMCE Autosave

Posted 30 Apr 2009 — by admin
Category Programming, Ruby on Rails

TinyMCE is a nice little WYSIWYG for text processing online. It uses iFrames and Javascript callbacks to manipulate textarea form fields. Using it with Rails can be somewhat problematic if you want to set up an observer on a field that TinyMCE is managing. The reason is that TinyMCE uses an iFrame and a callback to update the textarea before the form is submitted.

More detailed information on the TinyMCE specifics can be found at this site <a href=”http://www.crossedconnections.org/w/?p=88″>

In Rails, there is a nifty helper function called “observe_field” that will generate Javascript which listens for changes on form fields. However, because TinyMCE only updates the field after the form is submitted the contents of the textarea are not updated when you type in it. Therefore, your observe_field function is listening but doesn’t see anything new. The iFrame is a kind of buffer that will write to the textarea later.

A simple solution to this problem is to call the function that writes to the textarea. This will update the textarea and the observer_field function will notice the changes. You can use prototype “PeriodicalExecuter” to trigger a function that will contain the TinyMCE callback function. Below is the code.

script type="text/javascript" charset="utf-8"
  function triggerTinyMCE(){
    tinyMCE.triggerSave(true, true);
  }
  new PeriodicalExecuter(triggerTinyMCE, 30);
/script

<%= observe_field( :post_body,
        :frequency => 1,
        :update => :update_status,
        :url => { :action => :update_body } ) %>

However, the only problem with this approach is that you’re kind of running two functions that do the same thing. Instead it would make more sense to get rid of the observe_field function altogether and have the PeriodicalExecuter trigger a function that makes the ajax request at the same time. This would look something like

script type="text/javascript" charset="utf-8"
  function triggerTinyMCE(){
    tinyMCE.triggerSave(true, true);
    var content = escape($F('post_body'));
    var url = "/posts/update_body";
    var params = "post_body="+content;

    var aRequest = new Ajax.Request(url,
    {
      method: 'post',
      parameters: params,
      onSuccess: function(data){
        $("update_status").innerHTML = data.responseText;
      }
   });
}
new PeriodicalExecuter(triggerTinyMCE, 10);
/script

Using jQuery and Prototype Javascript Together with jQuery.noConflict();

Posted 29 Apr 2009 — by admin
Category Programming

To use the jQuery javascript framework in a Rails application, that also uses the Prototype framework for the same application, you’ll need to reassign the $() function for jQuery to another variable. This is very simple to do. Just make sure to include the jQuery library after you load your prototype defaults.

Here is the javascript to alias the $() function

script type="text/javascript"
  var $_ = jQuery.noConflict();
  $_(document).ready(function(){
  $_("a").click(function(){
  //... do something
  });
});
/script

Set Cron Job to Run Every Five Minutes for a Ruby on Rails Rake Task

Posted 21 Apr 2009 — by admin
Category Programming, Ruby on Rails

First off you’ll need to edit your cron file. Normally, the cron files are kept under /etc/cron.daily or /etc/cron.hourly but we can just use the command line tool, crontab and pass it the -e flag, so that we can edit the file without any fuss.

sudo crontab -e

If this is the first cron you’re installing you should see a blank file or something that looks like this

# m h  dom mon dow   command

Essentially this is telling you the order of the arguments you need to specify. Each asterisk represents an interval of time. In this order they are

Minute, Hour, Day of Month, Month, Day of Week and then the path to your command. So to set up our cron to run once every five minutes we’ll write

*/5 * * * * /path/to/my/script

It’s important to note that it is */5 and not just 5. The interval for minute is 0 – 59, meaning that if you just enter a 5, you’ll run your cron job only once an hour but at the 5th minute of that hour. To specify that we want to run it every 5 minutes we need the */5.  Also, note that the cron will execute your command via the path. If you need an interpreter like ruby, rake or php, don’t forget to put that as a part of your command. For instance this will set a rake task to run every five minutes on a Ubuntu box.

*/5 * * * * cd /var/www/my_ror_application  && /usr/bin/rake RAILS_ENV=development db:migrate

You can see that my command uses cd, changing directories to my application. I then specify the full path to the rake program, /usr/bin/rake and give it arguments, including the environment and then of course, the task I want to execute. In this case I’m migrating the database. Which is obviously pointless. Maybe you’ll want to email forum news or send out activation emails.

For more information here is a great reference mkaz.com

Validate Uniqueness on Join Tables in Rails

Posted 17 Apr 2009 — by admin
Category Ruby on Rails

How to validate uniqueness in a :has_many :through relationship with Ruby on Rails. You’ll need three models in this example List, Subscriber and ListSubscriber. A list has many subscribers and a subscriber has many lists. Simple enough. Running the following code would create a new record in our database table “list_subscribers”. It will also create two records that are exactly the same.

@subscriber.lists << @list
@list.subscribers << @subscriber

We need to correct this so that a subscriber can't be put on a list twice. If we're emailing our list, this subscriber would get two copies and we need to avoid this for obvious reasons. We need to add a validates_uniqueness_of condition in the model that represents the join table in the many to many relationship, ListSubscriber. ListSubscriber will take advantage of the :scope declaration and assign the :list_id as the qualifier, and throw an exception if we attempt to add a subscriber twice. Below is all the code you need to validate that there are no duplicates. Keep in mind that this is still application logic and therefore won't add constraints to your database. It's possible you'll have duplicates in race conditions etc. This is a problem in general with validating uniquess in your application logic. Program it in your database to be certain!

class List < ActiveRecord::Base
  has_many :subscribers, :through => :list_subscribers
  has_many :list_subscribers
end

class Subscriber < ActiveRecord::Base
  has_many :lists
  has_many :lists, :through => :list_subscribers
end

class ListSubscriber< ActiveRecord::Base
  belongs_to :list
  belongs_to :subscriber

  validates_uniqueness_of :subscriber_id, :scope => :list_id
end

Facebook Dark Launch

Posted 08 Apr 2009 — by admin
Category Social Media
"Dark Launch"

"Dark Launch"

Facebook uses an interesting method for testing when rolling out new features. This method, which I first read about on the Facebook engineering blog, is refered to as a “dark launch”. It’s an interesting title and more interesting is that Facebook users are testing new feature rollouts without realizing it. Because Facebook has so many users it is difficult to stress test accurately. However, to simulate high load on new features, Facebook will pop some code on the users homepage and have it function off screen or render nothing at all. This simulates a lot of people using the product (because they are) and they can accurately, or more accurately, determine bottlenecks and work out kinks.

Both the launch of the Facebook Chat application and their integration with CNN for the 09 Innauguration of Barack Obama were “dark launch” products.

I’ve never heard the term before but it could be a well known strategy. Nonetheless, cool stuff Facebook.

The feed I got the info from was in my private profile so I don’t have a link. Join the “Engineering at Facebook” group to read the article. It might be publically available but I’m not sure.

YouTube Internal Server Error

Posted 08 Apr 2009 — by admin
Category Programming

Thought I’d share a snapshot of this error message from youtube.com. It’s nice to know that their monkeys are highly trained. I figured they just got those lazy monkeys who work for bananas.

500 Internal Server Error

Sorry, something went wrong.

A team of highly trained monkeys has been dispatched to deal with this situation.

When the cloud is a good idea

Posted 07 Apr 2009 — by admin
Category Business

A buddy of mine is a talented, but paranoid System Administrator for a small web company. He refuses to see the truth and the beauty in the wonderful world made possible by cloud computing services like Amazon’s EC2. Amazon is not the only game in town. There are other, and in my opinion more flexible, providers out there such as http://slicehost.com, http://joyent.com and http://rackspace.com.

cloud1

His main critique involves a lack of control over the physical disks, vague terms of service, in some cases  poor technical documentation and implementations that don’t replicate everything that you get when managing your own server. An example of this is when your server instance fails in the cloud and your data is not persisted, at least not with Amazon. This is no doubt a limitation and a serious one at that.

All these services offer a near identical product with price points at a small difference in dollars. You find on average, $70 a month for 1 Gig of RAM with 30 Gigs of hard drive space. Rackspace has the best offer with Mosso at $43 a month for 40 gigs of hard drive space and 1 gig RAM. You can get server instances as small as 256 Megs of RAM for about $10 a month. These costs don’t include bandwidth, but unless you’re doing a lot of traffic this won’t cost much. A full T1 will run you ~$350 a month with Mosso. As more and more players hop into the game, I wouldn’t be surprised to see prices go down even further.

Management of your server is simple with a nice web interface for rebuilding, rebooting, DNS configuration and scheduling backups. You can choose from the most popular operating systems such as Ubuntu, CentOS and even Windows, get full root access and can upgrade/downgrade at any time at a prorated cost. It’s wonderful and beautiful!

Just because something is easy doesn’t necessarily make it a good idea. But that doesn’t prove the opposite is true either. Just because something is easy doesn’t make it a bad idea. So why is using the ‘cloud’ a good idea, and more importantly, when is using the ‘cloud’ a good idea?

I watched a great presentation made by Mr. Bezos, Amazon’s CEO, in which he related the IT infrastructure at Amazon to the American electricity grid of the early 20th century. Bezos envisions a world where developers can just ‘plug’ in to an infrastructure that delivers everything you could possibly want from a dedicated hosting solution at a fraction of the cost. An infrastructure that maximizes power and efficiency and makes it easier to administrate your ’server’, not more complicated.

Amazon and the rest of the lot can do this because they deliver a service that a lot of people use in a similar way and can scale costs accordingly. Amazon in particular, with the infrastructure requirements for their flagship product, Amazon.com, gives them expert industry knowledge and a massive operating budget. Smaller hosting companies have taken advantage of open source technologies like the Xen Virtualization, to deliver scalable dedicated virtual boxes.

Bezo’s has a beautiful analogy. It does have its limits. Computing is not the same thing as electricity. Appliances for the household consume electricity in the exact same way. Applications for the web, however, do not consume compute power the same way.

Where cloud computing offers a lot is for the lone developer, small team or startup in the proof-of-concept stage. For those who understand software but not hardware. Where the investment of time and resources adds a burden that subtracts from the development of their product(s). And when the product(s) they deliver have nothing to do with the means they choose to deliver them. The developer or small team just require something that is secure, consistent and reliable.

I won’t argue that the cloud will ever be more secure, consistent and reliable than choosing to do it yourself, if you decide to do it right. Maintaining 100% control over the physical disks and having direct access to the physical collocation is more secure, consistent and reliable without a doubt. However, the caveat is that because you’ve decided to do it yourself you have to do it right! If you don’t do it right you’ll most likely have a setup that is neither secure, consistent and is very, very unreliable. So this asks the question how does one do it right and how much does it cost to do it right?

The cost can vary but it does involve hiring a System Administrator for 50 – 100 K a year and spending over 10 K on equipment and collocation facility hosting.

If you’re that lone developer, small team or startup in the proof-of-concept stage, you may or may not be able to afford these costs. You can of course contract out and the cost would be lower. But I’m comparing the cost of a setup that has someone fully dedicated to it. I’m also assuming that the developers, who know software, will be able to lean and manage the server remotely and thus my argument involves eliminating the formal role of System Admin. Because you no longer need to worry about the physical limitations of your setup, involving hard drive failures, new OS installs on new machine, UPS, basic redundancy and the rule of 3, developers can wear two hats.

How can the cloud be as consistent, secure and reliable? The answer is that Amazon and other cloud providers are hiring engineers who make six figures. Not just one or two, but tens or hundreds or even tens of hundreds, more than you can afford to hire. It make sense that they will have the resources, knowledge and experience to deliver a product that is consistent, secure and reliable.

Bugs and such are inevitable, after all humans are still doing the work. However, the bug risk isn’t eliminated just because you bring it in house. In fact, odds are that the risk is higher!  Who would you put your money on, 1 or 2 guys at a small company or the combined knowledge from all the engineers at Amazon.com? Now, that is an extreme comparison and of course there exists a middle ground. If you happen to find a great admin who does quality work and understands business goals etc, his consultation might be worth the price. However, if you’re not so lucky, a product from the cloud might be less risky than the infrastructure you invest in – the IT fort some employee constructs for job security!

You get what you pay for without a doubt. It’s just that in the cloud it’s not just you paying and therefore you get more for your dollar.

named_scope in Rails

Posted 04 Apr 2009 — by admin
Category Ruby on Rails

Take advantage of the named_scope method in your models and make find queries simple and beautiful!

#app/models/comment.rb
class Comment < ActiveRecord::Base
  belongs_to :post
  named_scope :pending, :conditions => ["pending = ?", true]
  named_scope :for, lambda { |*args| {:include => :post,
      :conditions => ["posts.account_id = ?", (args.first||0)] }}
end

#app/models/post.rb
class Post < ActiveRecord::Base
  has_many :comments
end

Now you can get all comments for your posts that are marked as pending with this method:

@comments = Comment.pending.for(@account.id)