tag:blogger.com,1999:blog-75555179685321876302024-03-05T13:21:53.128-08:00From Java To Rubyand everything in between...Brian Zotterhttp://www.blogger.com/profile/04192905791773751598noreply@blogger.comBlogger27125tag:blogger.com,1999:blog-7555517968532187630.post-49746798282502505602008-12-30T08:20:00.001-08:002008-12-30T08:31:04.003-08:00Rails and Merb combine!No on saw this one coming. On December 23rd it was announced that Rails 3 will be the product of merging Rails and Merb frameworks. <br /><br />Check out these links for more information<br /><br /><a href="http://rubyonrails.org/merb">http://rubyonrails.org/merb</a><br /><a href="http://yehudakatz.com/2008/12/23/rails-and-merb-merge/">http://yehudakatz.com/2008/12/23/rails-and-merb-merge/</a>Robert Zotterhttp://www.blogger.com/profile/12655900249195026957noreply@blogger.com0tag:blogger.com,1999:blog-7555517968532187630.post-62617940736795494192008-12-02T17:16:00.000-08:002008-12-02T18:09:39.448-08:00IE File Download - Security Warning<pre name='code'>File Download - Security Warning<br />Do you want to save this file, or find a program online to open it....</pre><br />Have you ever seen this error when making an ajax request in IE? In particular this seems to happen when using the remote_form_for or remote_form_tag helper and try submitting the form via javascript. The expected result would be that the form would be submitted via ajax and then a RJS file would execute some Javascript on the client's page. Instead we get a stupid IE download popup.<br /><br />This one always comes back to bite me when I add a new features to a site and I've been blissfully programming away in FF neglecting the red headed stepchild IE. Then comes the head scratching followed by some screaming when Google fails to return any sort of valuable search results on this subject. I am going to post the issue and resolution for myself and hopefully it will help some other people out there.<br /><br />Here is an example of the HTML generated from remote_form_for.<br /><br /><pre name='code' class='ruby'><form method="post" id="user_form" action="/users"<br />onsubmit="new Ajax.Request('/users', {<br /> asynchronous:true, <br /> evalScripts:true, <br /> parameters:Form.serialize(this)}); <br /> return false;"></form></pre><br />And here is some javascript function that would submit that form.<br /><br /><pre name='code' class='ruby'>$('user_form').submit();</pre><br />First off when you submit this form in IE it seems that it sends out an ajax request because the full page does not reload. As it turns out when you call $('user_form').submit() in IE it never calls the onsubmit handler so it never has a chance to return false and prevent a full page submission. Since the form is not submitted via ajax IE thinks you want to download the response, ie the RJS file, hence the popup. What makes this even more tricky is that the RJS you wanted to execute actually gets executed so it looks like it was an actual ajax submission but it in fact was not.<br /><br />The simple solution is when you are trying to submit a remote form via javascript you should explicitly call the onsubmit handler like this.<br /><br /><pre name='code' class='ruby'>$('user_form').onsubmit();</pre><br />Doing it this way ensures that you are submitting the form via ajax and behavior will be consistent across all browsers.<br /><br />"Im a PC and I handle form submissions differently"Robert Zotterhttp://www.blogger.com/profile/12655900249195026957noreply@blogger.com2tag:blogger.com,1999:blog-7555517968532187630.post-33294468806921734272008-11-17T12:00:00.000-08:002008-11-17T15:21:02.768-08:00ActionMailer with Gmail. Must issue a STARTTLS command firstIf you ever tried sending e-mail via ActionMailer with gmail settings you may have received the following error:<br /><br /><pre>530 5.7.0 Must issue a STARTTLS command first. k41sm7289021rvb.4</pre><br />The problem is that Gmail requires TLS authentication but the standard Ruby net/smtp library doesn't support TLS. <br /><br />Of course there is a helpful plugin created by Marc Chung to overcome this barrier. You can find it <a href="http://code.openrain.com/rails/action_mailer_tls/">here</a> and manually add it to your project or you can export it to your plugin directory.<br /><br /><pre name='code' class='ruby'>$ cd vendor/plugins<br />$ svn export http://code.openrain.com/rails/action_mailer_tls/</pre><br />Either way make sure you require 'smtp_tls'<br /><br />Now all you need is to update your smtp_settings if you haven't done so already.<br /><br /><pre name='code' class='ruby'><br />ActionMailer::Base.smtp_settings = {<br /> :address => "smtp.gmail.com",<br /> :port => 587,<br /> :domain => "domain.com",<br /> :user_name => "user@domain.com",<br /> :password => "password",<br /> :authentication => :plain<br />}<br /></pre><br />You can now enjoy the benefits of a free email server.Robert Zotterhttp://www.blogger.com/profile/12655900249195026957noreply@blogger.com7tag:blogger.com,1999:blog-7555517968532187630.post-80835435246878533932008-11-16T18:09:00.000-08:002008-11-16T18:28:35.421-08:00What happened to Save the Developers from IE6 movement?WTF?<br /><br />Awhile back we found a nice site called <a href="http://www.savethedevelopers.org/">Save The Developers</a> that was dedicated to rid the world of IE6. The site was hosting some javascript that you could use to throw down a nice "Save the developers and upgrade your IE" message to the IE6 users of your site. <br /><br />Well as of sometime recently that <a href="http://www.savethedevelopers.org/">url</a> redirects you to a Microsoft support site? WTF? Did Mr. Softy just crush these guys? If you have info on this I would love to know.<br /><br />Conspiracy Theory? :)<br /><br /><span style="font-weight:bold;">Update<span style="font-style:italic;"></span></span><br /><br /><a href="http://www.stopie6.org/" title="Stop IE6 campaign"><img src="http://www.stopie6.org/img/badges/120_60.gif" alt="Stop IE6 campaign logo" width="120" height="60"></a><br /><br /><a href="http://www.stopie6.org">Stop IE 6</a>. Another campaign against IE6.<br /><br />Free the Web! Good luck guys.Brian Zotterhttp://www.blogger.com/profile/04192905791773751598noreply@blogger.com0tag:blogger.com,1999:blog-7555517968532187630.post-42917388072948792052008-11-16T17:53:00.000-08:002008-11-16T22:39:26.107-08:00IE6 hangs when downloading compressed images from AWS S3Like many new sites we store uploaded user images to S3. We are always trying to improve the experience of users so recently we started compressing these images using gzip. <br /><br />Well, it turns out that for some reason IE6 completely freezes for about 10 minutes when trying to download one of these files. Of course no problems in any other browser. <br /><br />Luckily IE6 is only 12% of our user base, so now we are forced to have zipped and unzipped images.<br />Argh IE6! Save the developers!<br /><br />I hope this helps someone as it drove us nuts trying to figure it out.Brian Zotterhttp://www.blogger.com/profile/04192905791773751598noreply@blogger.com0tag:blogger.com,1999:blog-7555517968532187630.post-50491747441834476462008-11-06T15:21:00.000-08:002008-11-06T16:10:51.750-08:00Hotmail in Ubuntu fixNot too long ago there was an update to <a href="http://www.hotmail.com/">Hotmail</a> basically rendering it unusable in Ubuntu. This is just one more item to add to the list of reasons why Microsoft sucks. Personally I prefer <a href="http://www.gmail.com/">Gmail</a> but I have a legacy account on Hotmail that I must check every now and then.<br /><br />After searching around for awhile I came across several solutions to get Hotmail working. One required opening up the about:config settings and changing the general.useragent.vendor from <span style="font-style: italic;">Ubuntu</span> to <span style="font-style: italic;">Firefox</span>. This works but it is required every time you restart your browser. There was also another solution that involved creating some .js script and placing it in your profile folder?!? Finally I found a somewhat decent solution. This should work in any Linux type system.<br /><br />First you need to install the <a href="https://addons.mozilla.org/en-US/firefox/addon/59">User Agent Switcher</a> add on.<br /><br />Then you need to create a new User Agent profile by going to<br /><span style="font-style: italic;">Tools -> User Agent Switcher -> Options -> Options</span><br /><br />Then click on <span style="font-style:italic;">User Agents</span> tab and hit the <span style="font-style:italic;">Add</span> button.<br /><br />Add the following fields:<br /><br /><pre>Description : [whatever]<br />User Agent : Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3<br />App Name : Mozilla Firefox<br />App Version : 5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3<br />Vendor : [blank]<br />Vendor Sub : [blank]<br /></pre><br /><br />Here is what it should look like (some of the characters got cut off at the end)<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-6KXauRo5PNAWZFdW_7srlRx4z2kInV-SGlGfbkqpjrn2psDLYx9c5Iv66lHw-4LO9vWvWrrLVEaIFEirBk-xcD3M-E0J2XIbbkukuww7SuK394Pcf_U8etAow9J0G2b5YaJUMFhRWSo/s1600-h/screenshot14.png"><img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 400px; height: 194px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-6KXauRo5PNAWZFdW_7srlRx4z2kInV-SGlGfbkqpjrn2psDLYx9c5Iv66lHw-4LO9vWvWrrLVEaIFEirBk-xcD3M-E0J2XIbbkukuww7SuK394Pcf_U8etAow9J0G2b5YaJUMFhRWSo/s400/screenshot14.png" alt="" id="BLOGGER_PHOTO_ID_5265696942893270498" border="0" /></a><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br />Then click on <span style="font-style:italic;">OK</span> <span style="font-style:italic;">OK</span><br /><br />Now when you want to use Hotmail you can just quickly switch the User Agent Profile to the newly created one. When you are done, simply switch back to the Default Profile.Robert Zotterhttp://www.blogger.com/profile/12655900249195026957noreply@blogger.com11tag:blogger.com,1999:blog-7555517968532187630.post-4014007226672073222008-10-31T11:18:00.000-07:002008-10-31T11:43:28.301-07:00Capistrano Subversion passwordRecently I ran into a problem with <a href="http://www.capify.org/">Capistrano</a> asking for my password when performing a svn+ssh checkout even though I had my SSH keys configured correctly. <br /><br />Capistrano hits the svn twice when performing a checkout. The first time it queries the most recent revision number and the second time to perform the actual checkout. It was during this second request that I was being asked for my password. After searching for awhile and trying multiple suggestions I finally came across a solution.<br /><br />In app/config/deploy.rb :<br /><br /><pre name='code' class='ruby'><br />ssh_options[:keys] = ["#{ENV['HOME']}/.ssh/id_rsa"] #Obviously needed<br />#default_run_options[:pty] = true #Didn't work for me<br />#ssh_options[:paranoid] = false #Didn't work for me<br />ssh_options[:forward_agent] = true #Ah hah.. Success!<br /></pre><br />Basically the <span style="font-style:italic;">ssh_options[:forward_agent] = true</span> option forwards the first authenticated ssh session (the one that queries the revision number) to the second one (the one that performs the checkout). <br /><br />If you are seeing the same problem this may just be the fix for you are looking for!Robert Zotterhttp://www.blogger.com/profile/12655900249195026957noreply@blogger.com3tag:blogger.com,1999:blog-7555517968532187630.post-36654698046673338472008-10-29T14:31:00.000-07:002008-10-29T14:43:12.864-07:00Quick Tip - Console GoodiesI just want to mention two quick little goodies for the rails console.<br /><br /><span style="font-weight:bold;">Tip #1 - Reloading</span><br /><br />Have you ever been running the console and after modifying your source you notice that the console has not picked up your changes? This usually occurs when you adding/removing/editing associations on a model, messing around with your vendor or lib directory, changed an environment config or anything else that only gets loaded once. <br /><br />Luckily there is a way to quickly reload your whole console environment without having to quit and restart saving you precious seconds. Actually when I used to develop in a windows environment starting up the console would take a very long time so this would save more than just a few seconds.<br /><br /><pre name='code' class='ruby'><br />$ ruby script/console <br />Loading development environment (Rails 2.1.1)<br />>> User.first.posts<br />NoMethodError: undefined method `posts' for #<Class:0xb6f55a08><br /># Now add the posts association on User<br />>> reload!<br />Reloading...<br />=> true<br />>> User.first.posts<br />=> [#<Post id: 1 ....>]<br /></pre><br />As you can see you just need to run the unsubtle command <span style="font-style:italic;">reload!</span> to reload the environment.<br /><br /><span style="font-weight:bold;">Tip #2 - Sandbox</span><br /><br />Have you ever want to muck around in your development database or dare I say production database and wished your temporary changes would not persist? Perhaps you wanted to test that new :dependent => :destroy association or perhaps you wanted to be evil (if only for a second) and destroy all the existing users just to make you feel powerful. Here's how to do it.<br /><br /><pre name='code' class='ruby'><br />$ ruby script/console production --sandbox<br />Loading production environment in sandbox (Rails 2.1.1)<br />Any modifications you make will be rolled back on exit<br />>> User.count<br />=> 214<br />>> User.destroy_all #Insert evil laugh here<br />=> [#<User id: .... ]<br />>> User.count<br />=> 0<br />>> exit<br /><br />$ ruby script/console production --sandbox<br />Loading production environment in sandbox (Rails 2.1.1)<br />Any modifications you make will be rolled back on exit<br />>> User.count<br />=> 214<br /></pre><br />All you need to do here is add the <span style="font-style:italic;">--sandbox</span> flag when starting up the console. Its basically like having a huge transaction block around your whole console session and by exiting you are throwing and exception and everything gets rolled back.Robert Zotterhttp://www.blogger.com/profile/12655900249195026957noreply@blogger.com0tag:blogger.com,1999:blog-7555517968532187630.post-54346260646120257962008-10-28T14:45:00.000-07:002008-11-09T13:12:55.068-08:00Delgation Pattern in RubyThe <a href="http://en.wikipedia.org/wiki/Delegation_pattern">Delegation Pattern</a> is a common pattern in all OO programming languages and is generally preferred over the use of inheritance. The beautiful thing about Ruby/RoR is that there are many ways to go about implementing this pattern.<br /><br />Say we have the following classes:<br /><br /><pre name='code' class='ruby'><br />class User<br /> attr_accessor :first_name, :last_name<br /> <br /> def initialize(first_name, last_name)<br /> @first_name = first_name<br /> @last_name = last_name<br /> end<br />end<br /><br />class Whatever<br /> def initialize(user)<br /> @user = user<br /> end<br />end<br /></pre><br />And for whatever reason we want to be able to access the object user's first and last name attributes from the object whatever like the following:<br /><br /><pre name='code' class='ruby'><br />>> user = User.new("Rob", "Zotter")<br />=> #User:0xb7bf3b98... <br />>> whatever = Whatever.new(user)<br />=> #Whatever:0xb7bf1a14...<br />>> whatever.first_name<br />=> Robert<br />>> whatever.last_name<br />=> Zotter<br /></pre><br />Here are some ways to go about doing this.<br /><br /><span style="font-weight:bold;">Solution #1 : Wrapper Methods</span><br /><br />We could simply add wrapper methods to the Whatever class that simply delegate the calls to the @user object.<br /><br /><pre name='code' class='ruby'><br />class Whatever<br /> def initialize(user)<br /> @user = user<br /> end<br /><br /> def first_name<br /> @user.first_name<br /> end<br /><br /> def last_name<br /> @user.last_name<br /> end<br />end<br /></pre><br />As you can see this quickly gets tiring as more and more methods are added to the User class that we would want to delegate. It also bloats the Whatever class.<br /><br /><span style="font-weight:bold;">Solution #2 : Method Missing</span><br /><br /><pre name='code' class='ruby'><br />class Whatever<br /> def initialize(user)<br /> @user = user<br /> end<br /><br /> def method_missing(method, *args, &block)<br /> if @user.respond_to?(method) <br /> @user.send(method, *args, &block)<br /> else<br /> raise NoMethodError<br /> end<br /> end<br />end<br /></pre><br />He were eliminate the need to continuously update Whatever class with wrapper methods when the User class changes by utilizing <a href="http://www.ruby-doc.org/core/classes/Kernel.html#M005951">Kernel#method_missing</a>. Now when the object whatever is sent a message that it does not know it will check the @user object to see if it responds to it and if it does it will delegate that method to it otherwise throwing a NoMethodError. Although this is an improvement over solution #1 it still has its drawbacks. First it is slower since it needs to search the whole Whatever class hierarchy before it reaches method_missing. Second, we do not have control over which methods can be delegated, they simply all get delegated to @user if @user responds to it. Third, whenever using method_missing it is always a little harder for anyone reading your source code to determine exactly what you are trying to do.<br /><br /><span style="font-weight:bold;">Solution #3 : SimpleDelegator</span><br /><br /><pre name='code' class='ruby'><br />require 'delegate'<br /><br />class Whatever < SimpleDelegator<br /> def initialize(user)<br /> super(user)<br /> end<br />end<br /></pre><br />Here we are using <a href="http://docs.huihoo.com/rdoc/ruby/stdlib/libdoc/delegate/rdoc/classes/SimpleDelegator.html">SimpleDelegator</a> which is an implementation of the <a href="http://www.ruby-doc.org/stdlib/libdoc/delegate/rdoc/index.html">Delegator</a> interface. We just have to pass in the user to super during instantiation and all methods on user will be available on whatever. This is a little more transparent then using method_missing but by subclassing SimpleDelegator we are preventing ourselves from being able to subclass any other class in the future. We also do not have control over which methods get delegated. Lastly, this way uses inheritance to accomplish composition?!?<br /><br /><span style="font-weight:bold;">Solution #4 : Forwardable</span><br /><br /><pre name='code' class='ruby'><br />require 'forwardable'<br /><br />class Whatever<br /> extend Forwardable<br /> def_delegators :@user, :first_name, :last_name<br /><br /> def initialize(user)<br /> @user = user<br /> end<br />end<br /></pre><br />Here we are using the <a href="http://www.ruby-doc.org/stdlib/libdoc/forwardable/rdoc/index.html">Forwardable</a> module. We just have to simply extend our class with the Forwardable module and we explicitly set which methods to delegate using the def_delegators method. As you can see the first argument to that method is the object to which to delegate to and then the following arguments are which methods to delegate to that object.<br /><br />Finally one last example using <a href="http://caboo.se/doc/classes/Module.html#M004107">ActiveSupport#delegate</a> which you get by default if you are running RoR. <br /><br /><span style="font-weight:bold;">Solution #5 : ActiveSupport Delegate</span><br /><br /><pre name='code' class='ruby'><br />class Whatever<br /> delegate :first_name, :last_name, :to => :@user<br /> <br /> def initialize(user)<br /> @user = user<br /> end<br />end<br /></pre><br />This is very similar to the previous example but I prefer this over the former because I think it just reads a little nicer. In this example you list the methods to delegate first then you define what object to delegate to using the :to option. ActiveSupport extends Module with the delegate method so there is no need to extend the Whatever class before using it.<br /><br />Solutions #4, #5 use metaprogramming techniques to dynamically add class methods to the Whatever class using class_eval which essentially make the class look like it does in solution #1. <br /><br />As you can see there are many ways to implement the Delegation pattern in Ruby and I'm sure there are plenty more ways that aren't mentioned here. Like the old saying goes theres is more than one way to skin a cat and Ruby certainly gives you more than enough sharp pointy objects to do it with.Robert Zotterhttp://www.blogger.com/profile/15716085865026231274noreply@blogger.com4tag:blogger.com,1999:blog-7555517968532187630.post-715334117721884172008-10-23T13:39:00.000-07:002008-10-27T21:04:51.456-07:00Big Day for Amazon EC2Today Amazon Web Services made some big <a href="http://aws.typepad.com/aws/2008/10/big-day-for-ec2.html">announcements</a>. We've been using AWS for over a year now and have been very happy with it. <br /><br /> <span style="font-weight:bold;">* Amazon EC2 is now in full production. The beta label is gone.<br /> * There's now an SLA (Service Level Agreement) for EC2. </span><br /><br />Finally! This will make our customers and investors sleep better at night! It's nice to see something not in a perpetual beta. <br /><br /> <span style="font-weight:bold;"> * Microsoft Windows is now available in beta form on EC2.<br /> * Microsoft SQL Server is now available in beta form on EC2.</span><br /><br />Yawn... Microsoft in the cloud doesn't excite me much.<br /><br /> <span style="font-weight:bold;"> * We plan to release an interactive AWS management console.</span><br /><br />I think the command line tools are just fine, but OK.<br /><br /> <span style="font-weight:bold;">* We plan to release new load balancing, automatic scaling, and cloud monitoring services.<br /></span><br /><br />Oh Yeah! To me, this has been the last piece of the puzzle. <br /><br />Load balancing in the cloud has been a "roll you own solution". The current solution is to use a software load balancer like HAProxy. However, this requires more machines, more management, and more hops and therefore more money. Round Robin DNS is a poor man's solution, do not even go there. <br /><br />My wish list.<ul><br /><li>Better reliability than S3, please!</li><br /><li>L4 load balancing</li> <br /><li>L7 content switching/filtering - Sticky Sessions</li> <br /><li>HTTP rewrite and compression</li> <br /><li>SSL acceleration</li><br /><li>Cheap - cheaper than having small instances running a software load balancer</li><br /><li>An easy web service API to configure all this</li><br /></ul>Kudos to the AWS team!Brian Zotterhttp://www.blogger.com/profile/04192905791773751598noreply@blogger.com0tag:blogger.com,1999:blog-7555517968532187630.post-7203478353025572402008-10-20T14:25:00.000-07:002008-10-28T15:26:15.607-07:00Ruby Syntax Highlighting in Blogger using Google syntaxhighlighterIn a previous <a href="http://www.fromjavatoruby.com/2008/06/test.html">post</a> I used the syntax gem to get ruby syntax highlighting for this blog.<br /><br />Well I just found a better way! Enter the <a href="http://code.google.com/p/syntaxhighlighter/">syntaxhighlighter</a> on Google Code.<br /><br />It 100% Javascript based so there is no need to mess around with html yourself. Only drawback is that you need a place to host the files.<br /><br /><h3>Getting it to work in Blogger</h3><br />Go to Layout -> Edit Html and place the following right before the closing </head>. <br /><pre name='code' class='xml'><br /><link href='http://.../stylesheets/syntax/SyntaxHighlighter.css' rel='stylesheet' type='text/css'/><br /><script language='javascript' src='http://.../javascripts/syntax/shCore.js'/><br /><script language='javascript' src='http://.../javascripts/syntax/shBrushRuby.js'/><br /><script language='javascript' src='http://.../javascripts/syntax/shBrushXml.js'/><br /><script language='javascript' src='http://.../javascripts/syntax/shBrushJava.js'/><br /></pre>and then at the bottom after the closing </body> tag add:<br /><pre name='code' class='xml'><br /><script language='javascript'><br />//<![CDATA[<br />dp.SyntaxHighlighter.ClipboardSwf = 'http://.../flash/syntax/clipboard.swf';<br />dp.SyntaxHighlighter.BloggerMode();<br />dp.SyntaxHighlighter.HighlightAll('code');<br />//]]><br /></script><br /></pre><br />Then in your posting you just surround the code in a pre tag with the class name set to the language you are displaying:<br /><br /> <pre name='code' class='ruby'><br /> ...<br /> </pre><br /><br />The html above was put in a <pre name='code' class='xml'> tag. ;) Remember to escape your opening brackets with &lt;.<br /><br />Now isn't that nice.Brian Zotterhttp://www.blogger.com/profile/04192905791773751598noreply@blogger.com1tag:blogger.com,1999:blog-7555517968532187630.post-77266075879821418052008-10-19T14:15:00.000-07:002008-10-24T08:59:34.284-07:00Multiple rake tasks. Running rake tasks from a task<a href="http://rake.rubyforge.org/">Rake</a> is a very useful ruby build tool very similar to that of <a href="http://ant.apache.org/">Ant</a> for Java.<br /><br />Sometimes you may want to run several rake tasks in succession and today I will go over several ways you can go about doing this.<br /><br />Say we want to completely drop our existing database, recreate it and populate it with some sample data via a custom rake task called 'populate' (not shown here).<br /><br />A naive way of accomplishing this would be to do the following:<br /><br /><pre> $ rake db:drop<br /> (in /home/rob/project/)<br /> $ rake db:create<br /> (in /home/rob/project/)<br /> $ rake db:migrate<br /> (in /home/rob/project/)<br /> $ rake db:populate</pre><br /><br />Besides just being horribly repetitive, this method requires you to wait to the completion of each migration before typing the next thus preventing you from grabbing the o so needed cup of coffee while your db is migrating. This method also reloads the rails environment before each migration which is completely useless and time consuming.<br /><br />"Ok" you say, "I got the answer" and type the following:<br /><br /><pre>$ rake db:drop && rake db:create && rake db:migrate && rake db:populate</pre><br /><br />This is one step better as you do not have to wait to the completion of each task before typing in the next, but we still have the problem of typing all of those commands as well as reloading the environment each time.<br /><br />Sounds like its time for a custom rake task.<br />Lets create a rake file called db.rake and place it in our [project-root]/lib/task/ directory.<br /><br /><pre>namespace :db do<br /> task :everything => [:environment, :drop, :create, :migrate, :populate]<br /> desc "Recreate everything from scratch including pre-populated data"<br /> end<br /> end</pre><br /><br />You can then just run one command<br /><br /><pre>$ rake db:everything</pre><br /><br />For those of you familiar with Java you will noticed that the rake syntax of 'task :everything => [:environment, :drop, :create, :migrate, :populate]' is exactly like <a href="http://ant.apache.org/">Ant's</a> depends attribute.<br /><br />For those of you not familiar with <a href="http://ant.apache.org/">Ant</a> ill quickly explain. Basically what 'task :everything => [:environment, :drop, :create, :migrate, :populate]' means is that the the task 'everything' depends on these other tasks so run those first.<br /><br />Ok, so now we greatly improved our initial version in that we do not have to type all of the individual commands or wait for the completion of each task before continuing. We also get the benefit of not having to reload the environment before each task (other than the first time of course).<br /><br />A problem arises though when we want to do anything else with this migration. For example, say we want to execute some logic or print out a simple message before and after each task execution. To accomplish this we would have to move all of the tasks out of the prerequisites section and move them into the actual task block. But how can we run another rake task from within a rake task? The <a href="http://rake.rubyforge.org/">Rake::Task</a> api will help us find the answer we are looking for.<br /><br /><pre> task :everything => :environment do<br /> desc "Recreate everything from scratch, including test data"<br /> %w(drop create migrate populate).each do |task|<br /> puts "Performing task #{task}"<br /> #Some logic could go here<br /> <span style="font-weight:bold;"> Rake::Task["db:#{task}"].invoke </span><br /> end<br /> end</pre><br /><br />The key to take out of this last example is the <a href="http://rake.rubyforge.org/classes/Rake/Task.html#M000119">Rake::Task#invoke</a> method. The method accepts a task (or tasks) and well... invokes it (or them).<br /><br />So with the help of rake and <a href="http://rake.rubyforge.org/classes/Rake/Task.html#M000119">Rake::Task#invoke</a> we have a nice clean way of running multiple rake tasks.Robert Zotterhttp://www.blogger.com/profile/15716085865026231274noreply@blogger.com1tag:blogger.com,1999:blog-7555517968532187630.post-87753619749425471022008-10-14T20:39:00.000-07:002008-10-22T22:09:56.927-07:00Autotest notifications in Ubuntu, Mac and WindowsAutotest part of the ZenTest package is a great testing tool that will automatically run your <a href="http://rspec.info/">RSpec</a> tests when you make a change to any of the source files. <br /><br />If you don't know about <a href="http://rspec.info/">RSpec</a> then you must have been living in a cave and I suggest you check that out first.<br /><br />Today I am going to teach you how to setup <a href="http://github.com/carlosbrando/autotest-notification/tree/master">automatic notifications</a> in Ubuntu that will allow you to display the results of your tests in nice little window like so.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7Bb0sjNnfZ23aUJs8P1h08ekc4r1mysFDcCUhJVg688R099UO_JpQ40dkM4Iut7rOPK23ju-j4nhRkIoE0N2E4qDgmQ9uRPUoBm3yTTQplDOt44FJJbCbKFOQz56lmWY9Nc_FThC9u7Og/s1600-h/autotest.png"><img style="margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7Bb0sjNnfZ23aUJs8P1h08ekc4r1mysFDcCUhJVg688R099UO_JpQ40dkM4Iut7rOPK23ju-j4nhRkIoE0N2E4qDgmQ9uRPUoBm3yTTQplDOt44FJJbCbKFOQz56lmWY9Nc_FThC9u7Og/s320/autotest.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5257229400742390658" /></a><br /><br />First make sure you have the libnotify binaries installed.<br /><br /><pre>$ sudo apt-get install libnotify-bin</pre><br />Then you'll need to install the actual autotest notification gem<br /><br /><pre>$ sudo gem install carlosbrando-autotest-notification --source=http://gems.github.com</pre><br />Easy enough. Ok now for the hard part of configuring it.... oh wait, did I say hard? I meant ridiculously easy.<br /><br /><pre>$ sudo an-install</pre><br />The above command will first backup then overwrite your ~/.autotest config file so you may just want to manually append the following if you have any existing configurations.<br /><br /><pre># ~.autotest<br />require 'autotest_notification'<br />SPEAKING = false<br />DOOM_EDITION = false<br />BUUF = false<br />PENDING = false<br />STICKY = false</pre><br />As you can see there are a few extra options you can play with till your little heart is content. You can even get notified by voice if you install <a href="http://espeak.sourceforge.net/">espeak</a> and pass a '-s' switch to an-install.<br /><br />An alternative to automatic notifications in Ubuntu is <a href="http://www.mumbles-project.org/download/">mumbles</a> which you may want to check. <br /><br /><span style="font-weight:bold;">What about Mac and Windows?</span><br /><br />The best thing about automatic notifications is that is fully compatible with Mac OS and Windows.<br /><br />For Mac you'll need to install <a href="http://growl.info/">Growl</a> and in Windows you'll need <a href="http://sourceforge.net/projects/snarl/">Snarl</a>. Installation is just as easy but slightly different in these enviroments so consult the <a href="http://github.com/carlosbrando/autotest-notification/tree/master">README.txt</a> for detailed instructions.<br /><br />EnjoyRobert Zotterhttp://www.blogger.com/profile/15716085865026231274noreply@blogger.com0tag:blogger.com,1999:blog-7555517968532187630.post-68338708335121506632008-06-15T13:25:00.000-07:002008-10-22T22:18:24.302-07:00IRB/Console tweaksToday ill explain how you can tweak your irb and rails console. First you'll need an irb configuration file called '.irbrc' which should be placed in your home directory. You'll need to create one if it doesn't already exist. Now you can add the following.<br /><br /><pre>#Load the readline module.<br />IRB.conf[:USE_READLINE] = true<br /><br />#Remove the annoying irb(main):001:0 and replace with >><br />IRB.conf[:PROMPT_MODE] = :SIMPLE<br /><br />#Always nice to have auto indentation<br />IRB.conf[:AUTO_INDENT] = true<br /><br />#History configuration<br />IRB.conf[:SAVE_HISTORY] = 100<br />IRB.conf[:HISTORY_FILE] = "#{ENV['HOME']}/.irb-save-history"<br /><br />#Load modules if not already loaded<br />IRB.conf[:LOAD_MODULES] = [] unless IRB.conf.key?(:LOAD_MODULES)<br />unless IRB.conf[:LOAD_MODULES].include?('irb/completion')<br /> IRB.conf[:LOAD_MODULES] << 'irb/completion' #Autocompletion of keywords<br /> IRB.conf[:LOAD_MODULES] << 'irb/ext/save-history' #Persist history across sessions<br />end <br /></pre><br />The comments should be pretty much self-explanatory. By fat the most useful feature has to be the auto-completion of keywords. So now you can just hit tab tab to display all methods of on an object.<br /><br />The next biggest feature has to be the persistence of the history across sessions. Anything that helps me save a few repetitious keystrokes is a big gain in my book. <br /><br />Since console is just basically irb on steroids you will have all this functionality there too!<br /><br />You can also add rails/console configurations here. Just make sure you are in the right environment before trying anything rails specific so irb doesnt blow up.<br /><br /><pre>if ENV['RAILS_ENV']<br /> #do something rails specific<br />end</pre><br /><br />A good way to separate out your rails specific configurations is to include it in another file and just load it from .irbrc This idea and the following are slight modifications of the snack recipes from the great book <a href="http://www.amazon.com/Advanced-Rails-Recipes-Mike-Clark/dp/0978739221/ref=sr_1_1?ie=UTF8&s=books&qid=1223837251&sr=8-1">Advanced Rails Recipes</a> (Authors of the recipe are at <a href="http://www.errtheblog.com">errtheblog.com</a>). You'll need to create a file called .railsrc in your home directory.<br /><br /><pre>if ENV['RAILS_ENV']<br /> load "#{ENV['HOME']}/.railsrc"<br />end</pre><br /><br />One helpful method I like to have in .railsrc is the ability to turn on and off ActiveRecord logging to the console to help analyze/debug my sql.<br /><br /><pre>#Enable ActiveRecord logging<br />def loud_logger(enable = true)<br /> logger = (enable == true ? Logger.new(STDOUT) : nil)<br /> ActiveRecord::Base.logger = logger<br /> ActiveRecord::Base.clear_active_connections!<br />end</pre><br /><br />Now you can easily turn on and off your ActiveRecord logging.<br /><br /><pre>>> SomeModel.first<br />=> # < SomeModel id: 1.. ><br />>> loud_logger <br />>> SomeModel.first<br /> SomeModel Load (0.000442) SELECT * FROM some_models LIMIT 1<br />>> loud_logger false<br />>> SomeModel.first<br />=> # < SomeModel id: 1.. ><br /></pre>Robert Zotterhttp://www.blogger.com/profile/15716085865026231274noreply@blogger.com2tag:blogger.com,1999:blog-7555517968532187630.post-81575877873694124252008-06-03T11:10:00.000-07:002008-10-03T12:12:38.364-07:00MySQL NULL sort orderSay we have an application that keeps track of tasks that need to be completed.<br /><br />A task will have a name, description and an optional expiration date.<br /><br />A possible schema could look something like the following.<br /> <br /><pre><span class=ident>create_table</span> <span class=symbol>:tasks</span> <span class=keyword>do</span> <span class=punct>|</span><span class=ident>t</span><span class=punct>|</span><br /> <span class=ident>t</span><span class=punct>.</span><span class=ident>column</span> <span class=symbol>:name</span><span class=punct>,</span> <span class=symbol>:string</span><span class=punct>,</span> <span class=symbol>:null</span> <span class=punct>=></span> <span class=constant>false</span><br /> <span class=ident>t</span><span class=punct>.</span><span class=ident>column</span> <span class=symbol>:description</span><span class=punct>,</span> <span class=symbol>:text</span><br /> <span class=ident>t</span><span class=punct>.</span><span class=ident>column</span> <span class=symbol>:expiration</span><span class=punct>,</span> <span class=symbol>:datetime</span><br /><span class=keyword>end</span></pre><br /><br />Now lets try to display all Tasks ordering by their expiration. We will just display the expiration for the sake of brevity.<br /><br /><pre><span class=punct>>></span> <span class=ident>puts</span> <span class=constant>Tasks</span><span class=punct>.</span><span class=ident>all</span><span class=punct>(</span><span class=symbol>:order</span> <span class=punct>=></span> <span class=punct>'</span><span class=string>expiration ASC</span><span class=punct>').</span><span class=ident>map</span><span class=punct>(&</span><span class=symbol>:expiration</span><span class=punct>)</span><br /><span class=constant>nil</span><br /><span class=constant>nil</span><br /><span class=constant>nil</span><br /><span class=constant>Fri</span> <span class=constant>June</span> <span class=number>4</span><span class=ident>th</span> <span class=number>00</span><span class=punct>:</span><span class=number>00</span><span class=punct>:</span><span class=number>00</span><br /><span class=constant>Sat</span> <span class=constant>June</span> <span class=number>5</span><span class=ident>th</span> <span class=number>00</span><span class=punct>:</span><span class=number>00</span><span class=punct>:</span><span class=number>00</span></pre><br /><br />The problem here is that by default null values appear at the top of the list. How can we display this list in ASC order but null values at the bottom of the list? After scouring around for awhile I finally came across a solution. It turns out that MySQL has a way to control the sorting of NULL values by adding a '-' before the field.<br /><br /><pre><span class=punct>>></span> <span class=ident>puts</span> <span class=constant>Tasks</span><span class=punct>.</span><span class=ident>all</span><span class=punct>(</span><span class=symbol>:order</span> <span class=punct>=></span> <span class=punct>'</span><span class=string><heavy>-</heavy>expiration <heavy>DESC</heavy></span><span class=punct>').</span><span class=ident>map</span><span class=punct>(&</span><span class=symbol>:expiration</span><span class=punct>)</span><br /><span class=constant>Fri</span> <span class=constant>June</span> <span class=number>4</span><span class=ident>th</span> <span class=number>00</span><span class=punct>:</span><span class=number>00</span><span class=punct>:</span><span class=number>00</span><br /><span class=constant>Sat</span> <span class=constant>June</span> <span class=number>5</span><span class=ident>th</span> <span class=number>00</span><span class=punct>:</span><span class=number>00</span><span class=punct>:</span><span class=number>00</span><br /><span class=constant>nil</span><br /><span class=constant>nil</span><br /><span class=constant>nil</span></pre><br /><br />Now we can list all Tasks ordered by their expiration date with NULL values at the bottom.Robert Zotterhttp://www.blogger.com/profile/15716085865026231274noreply@blogger.com0tag:blogger.com,1999:blog-7555517968532187630.post-58746591703801105202008-05-02T11:09:00.000-07:002008-10-22T22:18:42.024-07:00Cheating is fun with the cheat gem!<a href="http://www.errtheblog.com">errtheblog.com</a> released a great gem called cheat.<br /><br />Installation is a snap<br /><br /><pre>$ sudo gem install cheat</pre><br />Now you have access to a wide array of cheat sheets. Cheat sheets are basically like wiki pages that can be accessed from the command line, editable and all. Don't believe me? Give it a try<br /><br /><pre>$ cheat rspec | less<br /><br />rspec:<br /> INSTALL<br /> =======<br /> INSTALL rspec<br /> =============<br /> $ sudo gem install rspec<br /> OR <br /> $ ./script/plugin install git://github.com/dchelimsky/rspec.git<br /> <br /> INSTALL rspec_on_rails plugin<br /> =============================<br /> $ ./script/plugin install git://github.com/dchelimsky/rspec-rails.git<br /> <br /> <br /> BOOTSTRAP THE APP<br /> =================<br /> $ ./script/generate rspec<br /> create spec<br /> create spec/spec_helper.rb<br /> create spec/spec.opts<br /> create previous_failures.txt<br /> create script/spec_server<br /> create script/spec<br /><br /> ....<br /></pre><br />Cheat is not even rails specific. There are a whole slue of helpful commands that you can refer to as you go about your everyday programming. Just use the cheat sheets command to list them all.<br /><br /><pre>$ cheat sheets<br />All Cheat Sheets:<br /> acts_as_authenticated<br /> acts_as_state_machine<br /> acts_as_taggable_on<br /> address<br /> administrateme<br /> agile<br /> alias<br /> ambition<br /> ansi<br /> arts<br /> as3_formulas<br /> ascii<br /> assert<br /> assertions<br /> assert_block<br /><br /> ....and it keeps going and going<br /></pre>Robert Zotterhttp://www.blogger.com/profile/15716085865026231274noreply@blogger.com0tag:blogger.com,1999:blog-7555517968532187630.post-82133198171462886982008-05-02T10:28:00.000-07:002008-10-24T14:47:06.743-07:00Include vs ExtendA common cause of confusion in Ruby is discerning the difference between <a href="http://www.ruby-doc.org/core/classes/Module.html#M001661">Module#include</a> and <a href="http://ruby-doc.org/core/classes/Object.html#M000337">Object#extend</a> and when to use one over the other.<br /><br />A few examples will help us understand. Lets create a file example.rb<br /><br /><pre>cd module Coolness<br /> def cool_method<br /> puts "This is one cool method!"<br /> end<br />end<br /><br />class A<br /> include Coolness<br />end<br /><br />a = A.new<br />a.cool_method</pre><br /><br />Then we run it<br /><br /><pre>$ ruby example.rb<br />This is one cool method!</pre><br /><br />When you include a module from another module (remember all classes are modules) you are in essence adding in all of the included module's constants, methods, and module variables to the module that is including it. It's a mouthful, I know. So all of the methods of the module are available as instance methods. Now lets see what happens when we modify our file and use extend instead.<br /><br /><pre>class A<br /> extend Coolness<br />end<br /><br />a = A.new<br />a.cool_method</pre><br /><br /><pre>$ ruby example.rb<br />example.rb:14: undefined method `cool_method' for #<a:0xb7ce2888> (NoMethodError)</pre><br /><br />When you use extend you are adding the modules methods to the instance from which it is called on. In our case we are extending the module from the singelton class A so all the modules methods are available on the singelton class A, not on the instances of class A. I know, its another mouthful. So when you use extend in this way you are in essence adding the modules methods as class methods, not instance methods. So to execute cool_method we must call it as a method the class A itself.<br /><br /><pre>class A<br /> extend Coolness<br />end<br /><br />A.cool_method</pre><br /><br /><pre>$ ruby example.rb<br />This is one cool method!</pre><br /><br />If we wanted cool_method to be available to an instance of class A we need to explicitly extend the instance.<br /><br /><pre>class A<br /> extend Coolness<br />end<br /><br />a = A.new<br />a.extend(Coolness)<br />a.cool_method</pre><br /><br /><pre>$ ruby example.rb<br />This is one cool method!</pre><br /><br />So to summarize if you wanted to add instance methods to a class you should use include. If you want to add class methods to a class you should use extend. And finally, if you want to add instance methods to one particular instance of a class you should use extend on the instance itself.<br /><br />Let me know if you have any questions.Robert Zotterhttp://www.blogger.com/profile/15716085865026231274noreply@blogger.com0tag:blogger.com,1999:blog-7555517968532187630.post-12021839730257512932008-04-18T10:43:00.000-07:002008-10-03T14:03:32.620-07:00ActsAsFerret and computed ferret fieldsThe ActsAsFerret plugin automatically indexes your model when saving.<br /><br />The acts_as_ferret method takes a whole slew parameters which includes the fields to be indexed. For example say we have a User model:<br /><br /><pre> <span class="ident">acts_as_ferret</span> <span class="symbol">:fields</span> <span class="punct">=></span> <span class="punct">{</span> <br /> <span class="symbol">:last_name</span> <span class="punct">=></span> <span class="punct">{</span><span class="symbol">:boost</span> <span class="punct">=></span> <span class="number">10</span><span class="punct">,</span><span class="symbol">:store</span> <span class="punct">=></span> <span class="symbol">:yes</span><span class="punct">},</span> <br /> <span class="symbol">:first_name</span> <span class="punct">=></span> <span class="punct">{</span><span class="symbol">:boost</span> <span class="punct">=></span> <span class="number">1</span><span class="punct">,</span> <span class="symbol">:store</span> <span class="punct">=></span> <span class="symbol">:yes</span><span class="punct">},</span> <br /> <span class="symbol">:title</span> <span class="punct">=></span> <span class="punct">{</span><span class="symbol">:boost</span> <span class="punct">=></span> <span class="number">1</span><span class="punct">,</span> <span class="symbol">:store</span> <span class="punct">=></span> <span class="symbol">:yes</span><span class="punct">},</span><br /> <span class="symbol">:introduction</span> <span class="punct">=></span> <span class="punct">{</span><span class="symbol">:boost</span> <span class="punct">=></span> <span class="number">10</span><span class="punct">,</span><span class="symbol">:store</span> <span class="punct">=></span> <span class="symbol">:yes</span><span class="punct">}</span><br /> <span class="punct">},</span> <span class="symbol">:ferret</span> <span class="punct">=></span> <span class="punct">{</span><span class="symbol">:or_default</span> <span class="punct">=></span> <span class="constant">true</span><span class="punct">},</span> <span class="symbol">:remote</span> <span class="punct">=></span> <span class="constant">true</span> </pre><br /><br />This will add last_name, first_name, title and introduction to the index. These fields are just database columns. The symbol for field is really just a method call and so this how we can add computed or nested ferret fields for indexing.<br /><br />Suppose the user has a set tags with a simple 'has_many :tags' declaration. <br /><br />Then we can create a simple method in the user model like this.<br /><pre><span class="keyword">def </span><span class="method">user_tags</span><br /> <span class="ident">tags</span><span class="punct">.</span><span class="ident">map</span><span class="punct">(&</span><span class="symbol">:name</span><span class="punct">).</span><span class="ident">join</span><span class="punct">('</span><span class="string">,</span><span class="punct">')</span><br /><span class="keyword">end</span></pre><br /><br />and add this method(field) to the acts_as_ferret method<br /><br /><pre> <span class="ident">acts_as_ferret</span> <span class="symbol">:fields</span> <span class="punct">=></span> <span class="punct">{</span> <br /> <span class="symbol">:last_name</span> <span class="punct">=></span> <span class="punct">{</span><span class="symbol">:boost</span> <span class="punct">=></span> <span class="number">10</span><span class="punct">,</span><span class="symbol">:store</span> <span class="punct">=></span> <span class="symbol">:yes</span><span class="punct">},</span> <br /> <span class="symbol">:first_name</span> <span class="punct">=></span> <span class="punct">{</span><span class="symbol">:boost</span> <span class="punct">=></span> <span class="number">1</span><span class="punct">,</span> <span class="symbol">:store</span> <span class="punct">=></span> <span class="symbol">:yes</span><span class="punct">},</span> <br /> <span class="symbol">:title</span> <span class="punct">=></span> <span class="punct">{</span><span class="symbol">:boost</span> <span class="punct">=></span> <span class="number">1</span><span class="punct">,</span> <span class="symbol">:store</span> <span class="punct">=></span> <span class="symbol">:yes</span><span class="punct">},</span><br /> <span class="symbol">:introduction</span> <span class="punct">=></span> <span class="punct">{</span><span class="symbol">:boost</span> <span class="punct">=></span> <span class="number">10</span><span class="punct">,</span><span class="symbol">:store</span> <span class="punct">=></span> <span class="symbol">:yes</span><span class="punct">},</span><br /> <span class="symbol">:user_tags</span> <span class="punct">=></span> <span class="punct">{</span><span class="symbol">:boost</span> <span class="punct">=></span> <span class="number">10</span><span class="punct">,</span><span class="symbol">:store</span> <span class="punct">=></span> <span class="symbol">:yes</span><span class="punct">}</span> <br /> <span class="punct">},</span> <span class="symbol">:ferret</span> <span class="punct">=></span> <span class="punct">{</span><span class="symbol">:or_default</span> <span class="punct">=></span> <span class="constant">true</span><span class="punct">},</span> <span class="symbol">:remote</span> <span class="punct">=></span> <span class="constant">true</span> </pre><br /><br />Now we have the user's tags in the User index.Brian Zotterhttp://www.blogger.com/profile/04192905791773751598noreply@blogger.com0tag:blogger.com,1999:blog-7555517968532187630.post-32225786263577736052008-04-11T13:36:00.000-07:002008-10-10T15:52:42.005-07:00Quick Tip - extract_options!ActiveSupport added a helpful method named <a href="http://api.rubyonrails.com/classes/ActiveSupport/CoreExtensions/Array/ExtractOptions.html">'extract_options!'</a> that<br /><br />"Extracts options from a set of arguments. Removes and returns the last element in the array if it‘s a hash, otherwise returns a blank hash."<br /><br />So when we have a method that can accept multiple attributes the last of which could be a hash of options, instead of doing...<br /><br /><pre><span class=keyword>def </span><span class=method>some_method</span><span class=punct>(*</span><span class=ident>attributes</span><span class=punct>)</span><br /> <span class=ident>configuration</span> <span class=punct>=</span> <span class=punct>{</span><br /> <span class=symbol>:some_default</span> <span class=punct>=></span> <span class=punct>'</span><span class=string>value</span><span class=punct>'</span><br /> <span class=punct>}</span><br /> <span class=ident>configuration</span><span class=punct>.</span><span class=ident>update</span><span class=punct>(</span><span class=ident>attributes</span><span class=punct>.</span><span class=ident>pop</span><span class=punct>)</span> <span class=keyword>if</span> <span class=ident>attributes</span><span class=punct>.</span><span class=ident>last</span><span class=punct>.</span><span class=ident>is_a?</span><span class=punct>(</span><span class=constant>Hash</span><span class=punct>)</span><br /> <span class=punct>.......</span><br /><span class=ident>end</span></pre><br />We have the more elegant...<br /><br /><pre><br /><span class=keyword>def </span><span class=method>some_method</span><span class=punct>(*</span><span class=ident>attributes</span><span class=punct>)</span><br /> <span class=ident>configuration</span> <span class=punct>=</span> <span class=punct>{</span><br /> <span class=symbol>:some_default</span> <span class=punct>=></span> <span class=punct>'</span><span class=string>value</span><span class=punct>'</span><br /> <span class=punct>}</span><br /> <span class=ident>configuration</span><span class=punct>.</span><span class=ident>update</span><span class=punct>(</span><span class=ident>attributes</span><span class=punct>.</span><span class=ident>extract_options!</span><span class=punct>)</span><br /> <span class=punct>.......</span><br /><span class=ident>end</span></pre>Robert Zotterhttp://www.blogger.com/profile/15716085865026231274noreply@blogger.com0tag:blogger.com,1999:blog-7555517968532187630.post-52581947962543120302008-04-09T15:44:00.000-07:002008-10-26T07:19:34.679-07:00Missing host to link to! Please provide :host parameter or set default_url_options[:host]When using a link_to or url_for in an ActionMailer and you need to set the host.<br /><br />In production.rb or the appropriate env config file.<br /><br /><pre><span class=ident>config</span><span class=punct>.</span><span class=ident>action_mailer</span><span class=punct>.</span><span class=ident>default_url_options</span> <span class=punct>=</span> <span class=punct>{</span> <span class=symbol>:host</span> <span class=punct>=></span> <span class=punct>'</span><span class=string>www.example.com</span><span class=punct>'</span> <span class=punct>}</span></pre>Brian Zotterhttp://www.blogger.com/profile/04192905791773751598noreply@blogger.com5tag:blogger.com,1999:blog-7555517968532187630.post-56253787769714585452008-03-15T12:35:00.000-07:002008-10-22T22:17:29.239-07:00When private is not privateIn Java if we have a class with a private class method like so...<br /><br /><pre><span class="ident">public</span> <span class="keyword">class </span><span class="class">MyJavaClass</span> <span class="punct">{</span><br /><span class="ident"> private</span> <span class="ident">static</span> <span class="ident">void</span> <span class="ident">privateMethod</span><span class="punct">()</span> <span class="punct">{</span><br /> <span class="constant"> System</span><span class="punct">.</span><span class="ident">out</span><span class="punct">.</span><span class="ident">println</span><span class="punct">("</span><span class="string">I am private method</span><span class="punct">");</span><br /><span class="punct"> }</span><br /><span class="punct">}</span></pre><br />Trying to call the 'privateMethod' class method is futile.<br /><br /><pre><span class="ident">public</span> <span class="keyword">class </span><span class="class">Testing</span> <span class="punct">{</span><br /><span class="ident"> public</span> <span class="ident">static</span> <span class="ident">void</span> <span class="ident">main</span><span class="punct">(</span><span class="constant">String</span> <span class="ident">args</span><span class="punct">[]){</span><br /> <span class="constant"> MyJavaClass</span><span class="punct">.</span><span class="ident">privateMethod</span><span class="punct">();</span> <span class="punct">/</span><span class="punct">/</span><span class="constant">This</span> <span class="ident">will</span> <span class="keyword">not</span> <span class="ident">work!</span><br /><span class="punct"> }</span><br /><span class="punct">}</span></pre><br />Matter of fact you can not even compile the above class!<br /><br /><pre><span class=constant>Testing</span><span class=punct>.</span><span class=ident>java</span><span class=punct>:</span><span class=number>3</span><span class=punct>:</span> <span class=ident>privateMethod</span><span class=punct>()</span> <span class=ident>has</span> <span class=ident>private</span> <span class=ident>access</span> <span class=keyword>in</span> <span class=constant>MyJavaClas</span><br /> <span class=constant>MyJavaClass</span><span class=punct>.</span><span class=ident>privateMethod</span><span class=punct>();</span></pre><br />If we have a similar Ruby class and call the private method there is no problem.<br /><br /><pre><span class=keyword>class </span><span class=class>MyRubyClass</span><br /> <span class=ident>private</span><br /> <span class=keyword>def </span><span class=method>self.private_method</span><br /> <span class=ident>puts</span> <span class=punct>"</span><span class=string>I am a private method</span><span class=punct>"</span><br /> <span class=keyword>end</span><br /><span class=keyword>end</span></pre><br /><pre><span class=punct>>></span> <span class=constant>MyRubyClass</span><span class=punct>.</span><span class=ident>private_method</span><br /><span class=constant>I</span> <span class=ident>am</span> <span class=ident>a</span> <span class=ident>private</span> <span class=ident>method</span><br /><span class=punct>=></span> <span class=constant>nil</span></pre><br />What gives?!<br /><br />As it turns out you can not simply create a class method in a private section and have it actually be private. Reading through the Ruby API I came across the solution to achieve the desired behavior. There is a method in Module called <a href="http://www.ruby-doc.org/core/classes/Module.html#M001671">'private_class_method'</a> with the following signature.<br /><br /><pre><span class=ident>mod</span><span class=punct>.</span><span class=ident>private_class_method</span><span class=punct>(</span><span class=ident>symbol</span><span class=punct>,</span> <span class=punct>...)</span> <span class=punct>=></span> <span class=ident>mod</span></pre><br />Now if we slightly modify our MyRubyClass we get the results we would expect.<br /><br /><pre><span class=keyword>class </span><span class=class>MyRubyClass</span><br /> <span class=ident>private</span><br /> <span class=keyword>def </span><span class=method>self.private_method</span><br /> <span class=ident>puts</span> <span class=punct>"</span><span class=string>I am a private method</span><span class=punct>"</span><br /> <span class=keyword>end</span><br /> <span class=ident>private_class_method</span> <span class=symbol>:private_method</span><br /><span class=keyword>end</span></pre><br /><pre><span class=punct>>></span> <span class=constant>MyRubyClass</span><span class=punct>.</span><span class=ident>private_method</span><br /><span class=constant>NoMethodError</span><span class=punct>:</span> <span class=ident>private</span> <span class=ident>method</span> <span class=punct>'</span><span class=string>private_method</span><span class=punct>'</span> <span class=ident>called</span> <span class=keyword>for</span> <span class=constant>MyRubyClass</span><span class=symbol>:Class</span><br /> <span class=ident>from</span> <span class=punct>(</span><span class=ident>irb</span><span class=punct>):</span><span class=number>26</span></pre><br /><br /><span style="font-weight:bold;">*Note: Private instance methods behave as expected without any modifications.</span>Robert Zotterhttp://www.blogger.com/profile/15716085865026231274noreply@blogger.com1tag:blogger.com,1999:blog-7555517968532187630.post-48757623575870147742008-03-10T14:30:00.000-07:002008-10-22T22:17:29.240-07:00Quick Tip - to_procWe all know that & (ampersand) is used to denote a block variable but what you may not know is that Rails ActiveSupport (and soon to be in ruby 1.9) has a nice extension on Symbol that can make use of this convention by adding a to_proc method.<br /><br />For example instead of:<br /><br /><pre><span class=punct>["</span><span class=string>This</span><span class=punct>",</span> <span class=punct>"</span><span class=string>blog</span><span class=punct>",</span> <span class=punct>"</span><span class=string>is</span><span class=punct>",</span> <span class=punct>"</span><span class=string>great</span><span class=punct>"].</span><span class=ident>map</span> <span class=punct>{|</span><span class=ident>w</span><span class=punct>|</span> <span class=ident>w</span><span class=punct>.</span><span class=ident>upcase</span><span class=punct>}</span><br /><span class=punct>=></span> <span class=punct>["</span><span class=string>THIS</span><span class=punct>",</span> <span class=punct>"</span><span class=string>BLOG</span><span class=punct>",</span> <span class=punct>"</span><span class=string>IS</span><span class=punct>",</span> <span class=punct>"</span><span class=string>GREAT</span><span class=punct>"]</span></pre><br /><br />We could simplify it by:<br /><br /><pre><span class=punct>["</span><span class=string>This</span><span class=punct>",</span> <span class=punct>"</span><span class=string>blog</span><span class=punct>",</span> <span class=punct>"</span><span class=string>is</span><span class=punct>",</span> <span class=punct>"</span><span class=string>great</span><span class=punct>"].</span><span class=ident>map</span><span class=punct>(&</span><span class=symbol>:upcase</span><span class=punct>)</span><br /><span class=punct>=></span> <span class=punct>["</span><span class=string>THIS</span><span class=punct>",</span> <span class=punct>"</span><span class=string>BLOG</span><span class=punct>",</span> <span class=punct>"</span><span class=string>IS</span><span class=punct>",</span> <span class=punct>"</span><span class=string>GREAT</span><span class=punct>"]</span></pre><br /><br />What ruby ends up do is calling the to_proc method on that symbol and it coerces into a block!<br /><br />Here is a <a href="http://api.rubyonrails.com/classes/Symbol.html">link to the documentatio</a>n and for those who are lazy I have posted the source below.<br /><br /><pre><span class=comment># File lib/extensions/symbol.rb, line 23</span><br /><span class=keyword>def </span><span class=method>to_proc</span><br /> <span class=ident>proc</span> <span class=punct>{</span> <span class=punct>|</span><span class=ident>obj</span><span class=punct>,</span> <span class=punct>*</span><span class=ident>args</span><span class=punct>|</span> <span class=ident>obj</span><span class=punct>.</span><span class=ident>send</span><span class=punct>(</span><span class=constant>self</span><span class=punct>,</span> <span class=punct>*</span><span class=ident>args</span><span class=punct>)</span> <span class=punct>}</span><br /><span class=keyword>end</span></pre>Robert Zotterhttp://www.blogger.com/profile/15716085865026231274noreply@blogger.com0tag:blogger.com,1999:blog-7555517968532187630.post-75130311353362860262008-02-09T10:32:00.000-08:002008-10-22T22:17:29.241-07:00Custom Rails Validations - Keeping it DRY(2)Last week I added a custom validation for zip/postal codes. Now we make that available to all ActiveRecord models.<br /><br />The best way is to create a plugin for all your custom validations. We have a plugin for all our ActiveRecord extensions. Its easier to test and its reusable across projects.<br /><br />So we have our Validations module location in 'vendor/plugins/active_record_ext/lib'<br /><br /><pre><span class="keyword">module </span><span class="module">ValidationSystem</span><br /> <span class="keyword">def </span><span class="method">self.included</span><span class="punct">(</span><span class="ident">base</span><span class="punct">)</span> <span class="comment"># :nodoc:</span><br /> <span class="ident">base</span><span class="punct">.</span><span class="ident">extend</span> <span class="constant">ClassMethods</span> <br /> <span class="keyword">end</span><br /> <br /> <span class="keyword">module </span><span class="module">ClassMethods</span> <br /> <span class="keyword">def </span><span class="method">validates_as_zip_code</span><span class="punct">(*</span><span class="ident">attr_names</span><span class="punct">)</span><br /> <span class="ident">configuration</span> <span class="punct">=</span> <span class="punct">{</span><br /> <span class="symbol">:message</span> <span class="punct">=></span> <span class="punct">'</span><span class="string">is an invalid zip code</span><span class="punct">',</span><br /> <span class="symbol">:with</span> <span class="punct">=></span> <span class="punct">/</span><span class="regex">(^<span class="escape">\d</span>{5}$)|(^<span class="escape">\d</span>{5}-<span class="escape">\d</span>{4}$)|(^[ABCEGHJKLMNPRSTVXY]<span class="escape">\d</span>[A-Z] <span class="escape">\d</span>[A-Z]<span class="escape">\d</span>)</span><span class="punct">/,</span><br /> <span class="symbol">:allow_nil</span> <span class="punct">=></span> <span class="constant">false</span><span class="punct">}</span><br /> <span class="ident">configuration</span><span class="punct">.</span><span class="ident">update</span><span class="punct">(</span><span class="ident">attr_names</span><span class="punct">.</span><span class="ident">pop</span><span class="punct">)</span> <span class="keyword">if</span> <span class="ident">attr_names</span><span class="punct">.</span><span class="ident">last</span><span class="punct">.</span><span class="ident">is_a?</span><span class="punct">(</span><span class="constant">Hash</span><span class="punct">)</span><br /> <span class="ident">validates_format_of</span> <span class="ident">attr_names</span><span class="punct">,</span> <span class="ident">configuration</span><br /> <span class="keyword">end</span><br /> <span class="keyword">end</span><br /> <br /><span class="keyword">end</span><br /></pre><br /><br />Now we just need to tell ActiveRecord to include this in Base so its available for all model classes.<br /><br />'vendor/plugins/active_record_ext/init.rb'<br /><br /><pre><span class="constant">ActiveRecord</span><span class="punct">::</span><span class="constant">Base</span><span class="punct">.</span><span class="ident">class_eval</span> <span class="keyword">do</span><br /> <span class="ident">include</span> <span class="constant">ValidationSystem</span><br /><span class="keyword">end</span></pre>Brian Zotterhttp://www.blogger.com/profile/04192905791773751598noreply@blogger.com0tag:blogger.com,1999:blog-7555517968532187630.post-74644303957525549902008-02-06T12:27:00.000-08:002008-10-22T22:17:29.241-07:00Require vs LoadIn ruby there are two main ways to include additional source files into working enviroment. One way is with the <a href="http://www.ruby-doc.org/core/classes/Kernel.html#M005966">Kernel#load</a> method and the other is with the <a href="http://www.ruby-doc.org/core/classes/Kernel.html#M005967">Kernel#require</a> method. <br /><br />So what are the main difference and when should one be used over the other?<br /><br />Some simple examples should clear up any confusion.<br /><br />Say we have a very useful file called 'useful.rb' that has the following contents.<br /><br /><pre>puts "This file is so useful I just want to use it everywhere!"</pre><br /><br />Now lets play in our nifty IRB and 'require' our destined to be hugely popular file.<br /><br /><pre>>> require 'useful'<br />This file is so useful I just want to use it everywhere!<br />=> true</pre><br /><br />Ahh all is well in the world. Now lets try to load it.<br /><br /><pre>>> load 'useful'<br />LoadError: no such file to load -- useful<br /> from (irb):2:in 'load'<br /> from (irb):2<br />>></pre><br /><br />As you can see 'load' was unable to locate the file. Lets try adding the .rb to extension and see what happens.<br /><br /><pre>>> load 'useful.rb'<br />This file is so useful I just want to use it everywhere!<br />=> true</pre><br /><br />There we go. So the first difference I want to point out is that 'load' requires that you explicitly add the file extension while 'require' does not. 'require' will automatically search your path for files with the given name and automatically append .rb, .so, .o and .dll extensions to try to locate the proper file. <br /><br />Now lets see what happens if we 'require' and 'include' our file a second time.<br /><br /><pre>>> require 'useful'<br />=> false<br />>> load 'useful.rb'<br />This file is so useful I just want to use it everywhere!<br />=> true</pre><br /><br />As you an see requiring the file a second time fails but including it passes. This is because when you 'require' a file it will not reload itself if it has already been loaded. This is in contrast to 'load' will always reload the file.<br /><br />Why would you ever use 'load' then? Well the truth is most of the time you will be using 'require' but there are circumstances where 'load' is preferably. Rails for example uses 'load' while in development mode as to guarantee any changes to the source will invalidate any existing cache that the web server may have thus always displaying your most recent changes.<br /><br />I hope this post clears up any confusion.Robert Zotterhttp://www.blogger.com/profile/15716085865026231274noreply@blogger.com14tag:blogger.com,1999:blog-7555517968532187630.post-31319572616061077922008-02-03T10:22:00.000-08:002008-10-22T22:15:05.261-07:00Custom Rails Validations - Keeping it DRYOne of the validations that keeps coming up for us is zip/postal code. Sure you can use 'validates_format_of' with a regexp but it's nice to keep that regexp logic all in one place. We recently had to support Canadian Postal Codes so it was nice to update it just in one spot.<br /><br /><pre> <span class="keyword">def </span><span class="method">validates_as_zip_code</span><span class="punct">(*</span><span class="ident">attr_names</span><span class="punct">)</span><br /> <span class="ident">configuration</span> <span class="punct">=</span> <span class="punct">{</span><br /> <span class="symbol">:message</span> <span class="punct">=></span> <span class="punct">'</span><span class="string">is an invalid zip code</span><span class="punct">',</span><br /> <span class="symbol">:with</span> <span class="punct">=></span> <span class="punct">/</span><span class="regex">(^<span class="escape">\d</span>{5}$)|(^<span class="escape">\d</span>{5}-<span class="escape">\d</span>{4}$)|(^[ABCEGHJKLMNPRSTVXY]<span class="escape">\d</span>[A-Z] <span class="escape">\d</span>[A-Z]<span class="escape">\d</span>)</span><span class="punct">/,</span><br /> <span class="symbol">:allow_nil</span> <span class="punct">=></span> <span class="constant">false</span><span class="punct">}</span><br /> <span class="ident">configuration</span><span class="punct">.</span><span class="ident">update</span><span class="punct">(</span><span class="ident">attr_names</span><span class="punct">.</span><span class="ident">pop</span><span class="punct">)</span> <span class="keyword">if</span> <span class="ident">attr_names</span><span class="punct">.</span><span class="ident">last</span><span class="punct">.</span><span class="ident">is_a?</span><span class="punct">(</span><span class="constant">Hash</span><span class="punct">)</span><br /> <span class="ident">validates_format_of</span> <span class="ident">attr_names</span><span class="punct">,</span> <span class="ident">configuration</span><br /> <span class="keyword">end</span></pre>Brian Zotterhttp://www.blogger.com/profile/04192905791773751598noreply@blogger.com0