tag:blogger.com,1999:blog-6761142148052793737Fri, 16 Mar 2018 11:27:30 +0000javascriptruby on railsnewsgoogle maps apipresentationcssmysqlrubywebgearsyuirestrmagickWeb DevelopmentWeb 2.0, Ruby, Rails, TDD, BDD, <br>rSpec, XMPP, BOSH, REST,<br>Javascript, Ajax, Google Maps API, <br>Google Gears API, CSS, <br>Java, C#, Social Network, RMagick, Nginxhttp://chamnapchhorn.blogspot.com/noreply@blogger.com (chamnap)Blogger103125tag:blogger.com,1999:blog-6761142148052793737.post-3132186931082736371Wed, 23 May 2012 12:56:00 +00002012-05-24T09:54:26.301+07:00My blog is moved!<div dir="ltr" style="text-align: left;" trbidi="on"><span style="font-size: x-large;">I stopped using blogger to do blogging. My new blog is&nbsp;<a href="http://chamnap.github.com/">chamnap.github.com</a>.</span><br /><span style="font-size: x-large;"><br /></span><br /><span style="font-size: x-large;">See you there!</span></div><img src="http://feeds.feedburner.com/~r/blogspot/chamnap/~4/Tqn8GahaSyY" height="1" width="1" alt=""/>http://feedproxy.google.com/~r/blogspot/chamnap/~3/Tqn8GahaSyY/blog-moved.htmlnoreply@blogger.com (chamnap)79http://chamnapchhorn.blogspot.com/2012/05/blog-moved.htmltag:blogger.com,1999:blog-6761142148052793737.post-8404703751548354636Mon, 02 May 2011 02:24:00 +00002011-05-02T09:26:38.926+07:00High Performance Website Presentation at HackerspaceppI’m a little bit disappointed in myself. What I intended to do presentation is about Web Scaling, but I ended up with go through the front end side. This presentation will focus on how to make your website faster on the front end side. I did focus on some aspects on HTTP concept as well. Those are rules from Steve Souders, but I modify and adjust to make it clear to the audience.<br /><br /><div style="width:425px" id="__ss_7783873"> <strong style="display:block;margin:12px 0 4px"><a href="http://www.slideshare.net/cchamnap/high-performance-website-7783873" title="High performance website">High performance website</a></strong> <iframe src="http://www.slideshare.net/slideshow/embed_code/7783873" width="425" height="355" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"></iframe> <div style="padding:5px 0 12px"> View more <a href="http://www.slideshare.net/">presentations</a> from <a href="http://www.slideshare.net/cchamnap">Chamnap Chhorn</a> </div> </div><img src="http://feeds.feedburner.com/~r/blogspot/chamnap/~4/vYx4zHw4qmY" height="1" width="1" alt=""/>http://feedproxy.google.com/~r/blogspot/chamnap/~3/vYx4zHw4qmY/high-performance-website-presentation.htmlnoreply@blogger.com (chamnap)22http://chamnapchhorn.blogspot.com/2011/05/high-performance-website-presentation.htmltag:blogger.com,1999:blog-6761142148052793737.post-7641631831709968702Tue, 29 Mar 2011 03:42:00 +00002011-03-29T10:56:32.420+07:00REST Presenation on DevCamp, HackerspaceppLast sunday, I talked to some people, around 10 software developers, about how to build web services using REST architecture. However, I didn't talk on <a href="http://www.slideshare.net/cchamnap/rest-web-services-in-rails">my previous slide presentation</a>. I took on <a href="www.slideshare.net/kjbuckley/doing-rest-right-3385800">Doing REST Right</a> by Kerry Buckley. I decided to choose this slide because I feel I learnt something new and it's recommended by my boss, Chris. Actually, I were not well-prepared, but the presentation went well. I missed some slides before I went to do this presentation.<br /><br /><div style="width:425px" id="__ss_3385800"> <strong style="display:block;margin:12px 0 4px"><a href="http://www.slideshare.net/kjbuckley/doing-rest-right-3385800" title="Doing REST Right">Doing REST Right</a></strong> <object id="__sse3385800" width="425" height="355"> <param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=doingrestright-100310081847-phpapp01&stripped_title=doing-rest-right-3385800&userName=kjbuckley" /> <param name="allowFullScreen" value="true"/> <param name="allowScriptAccess" value="always"/> <embed name="__sse3385800" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=doingrestright-100310081847-phpapp01&stripped_title=doing-rest-right-3385800&userName=kjbuckley" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"></embed> </object> <div style="padding:5px 0 12px"> View more <a href="http://www.slideshare.net/">presentations</a> from <a href="http://www.slideshare.net/kjbuckley">Kerry Buckley</a> </div> </div><img src="http://feeds.feedburner.com/~r/blogspot/chamnap/~4/YLRvFAvXbwU" height="1" width="1" alt=""/>http://feedproxy.google.com/~r/blogspot/chamnap/~3/YLRvFAvXbwU/rest-presenation-on-devcamp.htmlnoreply@blogger.com (chamnap)25http://chamnapchhorn.blogspot.com/2011/03/rest-presenation-on-devcamp.htmltag:blogger.com,1999:blog-6761142148052793737.post-6963897337485578850Mon, 30 Aug 2010 03:26:00 +00002010-09-04T15:58:46.974+07:00ruby on railsLoad Balancer Algorithm ExplainedI've been googling around 2 days just want to know the best way that heavy-load rails sites was handled. I'm having trouble with mongrel clusters, one of which usually dies because of some heavy requests and nginx still forwards request to that frozen mongrel (using nginx simple load balancer). I was curious what are the options to solve this. I have looked at various solutions: <span style="font-weight:bold;">simple nginx load balancer</span>, <span style="font-weight:bold;">fair nginx load balancer</span>, <span style="font-weight:bold;">HAProxy</span>, and finally <span style="font-weight:bold;">Phusion Passenger</span>. However, I didn't go through JRuby for deploy rails app and Unicorn.<br /><br /><span style="font-weight:bold;">Simple Load Balancer</span><br />By default, nginx is only a simple robin-round load balancer. What it does is just send those requests to one of those backends (mongrel in this case) in simple manner (a,b,a,b, ...). The round-robin algorithm is often an acceptable tool: if every request finishes within a few milliseconds, there’s no problem. In this scenario, each backend has its own queue for processing concurrent requests. Therefore, if the heavy request comes in, the queue requests in that backend will be waiting and is able to process until that long-running request finishes. So what if that heavy request process longer than 60 seconds, those queue requests will never be able to process because it has been timeout.<br />Another problem is that nginx would flood mongrels with too many requests and mongrel's request queue was not solid and it would quickly get stuck with too many queued requests.<br /><br />Here is the <a href="http://wiki.nginx.org/NginxLoadBalanceExample">configuration </a>of nginx simple load balancer.<br /><pre>http {<br /> upstream myproject {<br /> server 127.0.0.1:8000;<br /> server 127.0.0.1:8001;<br /> server 127.0.0.1:8002; <br /> server 127.0.0.1:8003;<br /> }<br /> <br /> server {<br /> listen 80;<br /> server_name www.domain.com;<br /> location / {<br /> proxy_pass http://myproject;<br /> }<br /> }<br />}</pre><br /><span style="font-weight:bold;">Fair Load Balancer</span><br />Seeing this problem, a guy from Engine Yard wrote a <a href="http://nginx.localdomain.pl/wiki/UpstreamFair">personal patch</a> by adding a module in nginx called <span style="font-weight:bold;">fair load balancer</span>. What it basically does it know many requests each backend is processing and it will avoid sending further requests to already busy backends. By default, fair load balancer will assign request to idle backend first, when all are busy it will use <span style="font-weight:bold;">weighted least-connection round-robin</span> (WLC-RR) algorithm, meaning that it will assign the requests using a score that depends on both the number of requests assigned to the peer (as most important) and if all equal, to the peer that had the earliest assignment.<br />Another mode is whenever the first backend is idle, it's going to get the next request. If it's busy, the request will go to the second backend unless it's busy too etc. <br /><br />As you can see, the backend still has its queue requests, and it will run into this scenario:<br />Suppose we have 3 backends which have 3 requests in their queue, except for the first backend which has only 1 request in its queue.<br />Backend process A: [* ] (1 request in queue)<br />Backend process B: [*** ] (3 requests in queue)<br />Backend process C: [*** ] (3 requests in queue)<br />Backend process D: [*** ] (3 requests in queue)<br /><br />Next, new request comes in, so backend A will have 2 requests where X is the new request.<br />Backend process A: [*X ] (2 request in queue)<br />Backend process B: [*** ] (3 requests in queue)<br />Backend process C: [*** ] (3 requests in queue)<br />Backend process D: [*** ] (3 requests in queue)<br /><br />Assuming that B, C and D are still processing its queues, the next request comes in (called Y), it will be forwarded to backend A because it has the least number of request queues.<br />Backend process A: [*XY ] (3 requests in queue)<br />Backend process B: [*** ] (3 requests in queue)<br />Backend process C: [*** ] (3 requests in queue)<br />Backend process D: [*** ] (3 requests in queue)<br /><br />The problem arises if Backend A needs 60 seconds to process X. Y will never be processed because it has been timeout. It would be much better if Y was forward to other Backends.<br /><br />Here is the configuration:<br /><pre>upstream mongrel {<br /> fair;<br /> server 127.0.0.1:5000;<br /> server 127.0.0.1:5001;<br /> server 127.0.0.1:5002;<br /> }</pre><br /><br /><span style="font-weight:bold;">HAProxy</span><br />Rails was traditionally and mostly deployed using Apache or nginx with either a built-in or standalone proxy (like <a href="http://haproxy.1wt.eu/">HAProxy</a>) against a cluster of Mongrels or Unicorns.<br /><blockquote>HAProxy is a free, very fast and reliable solution offering high availability, load balancing, and proxying for TCP and HTTP-based applications.</blockquote><br /><br />If using HAProxy, the setup is similar to this:<br /><br /> <span style="font-weight:bold;">Web </span>=> <span style="font-weight:bold;">Nginx </span>=> <span style="font-weight:bold;">HAProxy </span>=> <span style="font-weight:bold;">Mongrel</span><br /><br />In this setup nginx just proxies to a single haproxy instance and haproxy has all registered mongrels configured. HAProxy queue is much more stable and it better balances all the requests between backends than nginx does. HAProxy has better support for upstream ok/fail detection and can also limit each app server to 1 connection (maxconn directive) which is key for mongrel. HAProxy limits the number of requests sent to mongrel instead of blindly forward requests. The fact that mongrel has only 1 request to process makes the application more scalable since the previous problem never happens. If there is one heavy request, processing that request won't affect on other requests since HAProxy only forwards request to the idle mongrel.<br /><br />One downside of using this is that it brings any additional latencies.<br />Another thing is that it's more complicated to setup and administrate than using <a href="http://www.modrails.com/">Phusion Passenger</a> a.k.a. modrails or modrack.<br /><br />Just to take the advantage of the <span style="font-weight:bold;">maxconn</span> directive, try <a href="http://github.com/ry/nginx-ey-balancer">nginx-ey-balancer</a>. One thing to keep in mind is that the maxconn is per nginx worker.<br /><pre>upstream mongrels {<br /> server 127.0.0.1:8001;<br /> server 127.0.0.1:8002;<br /> max_connections 1;<br /> }</pre><br /><span style="font-weight:bold;">Phusion Passenger</span><br /><blockquote>Phusion Passenger is an Nginx module, which makes deploying Ruby and Ruby on Rails applications on Nginx a breeze.</blockquote><br />It's a great tool for me to deploy rails and rack-based ruby applications. Passenger has both nginx and apache module. Passenger comes with feature called <a href="http://www.modrails.com/documentation/Users%20guide%20Nginx.html#PassengerUseGlobalQueue">global queuing</a>, which works similar to what I mentioned above.<br /><br />The good thing about passenger, it's easier to configure than HAProxy. It has a couple of strategies to load rails application (smart, smart-lv2, conservative). It can even reduce memory to 33% if using <a href="http://www.rubyenterpriseedition.com/">Ruby Enterprise Edition</a>. The installation process is to install passenger gem, which is quite up-to-date and support ruby 1.9.<br /><br />I won't dig into detail about passenger, you might go through the <a href="http://www.modrails.com/documentation.html">documentation </a>by yourself.<img src="http://feeds.feedburner.com/~r/blogspot/chamnap/~4/pel3tvwIEP0" height="1" width="1" alt=""/>http://feedproxy.google.com/~r/blogspot/chamnap/~3/pel3tvwIEP0/load-balancer-algorithm-explained.htmlnoreply@blogger.com (chamnap)10http://chamnapchhorn.blogspot.com/2010/08/load-balancer-algorithm-explained.htmltag:blogger.com,1999:blog-6761142148052793737.post-2503661580222697536Tue, 17 Aug 2010 03:13:00 +00002010-08-23T13:41:04.479+07:00presentationrubyRuby Object ModelI conduct a training on Ruby Object Model this week. I start talking about Ruby from scratch then the object model of Ruby. At the same time, I discussed about JavaScript object model.<br /><br /><div style="width:425px" id="__ss_4978263"><strong style="display:block;margin:12px 0 4px"><a href="http://www.slideshare.net/cchamnap/ruby-object-model-4978263" title="Ruby object model">Ruby object model</a></strong><object id="__sse4978263" width="425" height="355"><param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=rubyobjectmodel-100816032824-phpapp01&stripped_title=ruby-object-model-4978263" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed name="__sse4978263" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=rubyobjectmodel-100816032824-phpapp01&stripped_title=ruby-object-model-4978263" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"></embed></object><div style="padding:5px 0 12px">View more <a href="http://www.slideshare.net/">presentations</a> from <a href="http://www.slideshare.net/cchamnap">cchamnap</a>.</div></div><img src="http://feeds.feedburner.com/~r/blogspot/chamnap/~4/Pcmn3iRfTZc" height="1" width="1" alt=""/>http://feedproxy.google.com/~r/blogspot/chamnap/~3/Pcmn3iRfTZc/ruby-object-model.htmlnoreply@blogger.com (chamnap)4http://chamnapchhorn.blogspot.com/2010/08/ruby-object-model.htmltag:blogger.com,1999:blog-6761142148052793737.post-8469432277758439455Sat, 31 Jul 2010 01:50:00 +00002010-08-20T08:54:12.708+07:00javascriptpresentationwebCross-Domain SolutionsRecently, I found a presentation on how to solve cross domain issues. I think it's quite useful for web developers.<br /><br /><div style="width:425px" id="__ss_1636202"><strong style="display:block;margin:12px 0 4px"><a href="http://www.slideshare.net/mehmetakin/ajax-world" title="Solving Cross-Domain Issues When Building Mashups">Solving Cross-Domain Issues When Building Mashups</a></strong><object id="__sse1636202" width="425" height="355"><param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=ajaxworld-090624204735-phpapp01&stripped_title=ajax-world" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed name="__sse1636202" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=ajaxworld-090624204735-phpapp01&stripped_title=ajax-world" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"></embed></object><div style="padding:5px 0 12px">View more <a href="http://www.slideshare.net/">presentations</a> from <a href="http://www.slideshare.net/mehmetakin">mehmetakin</a>.</div></div><img src="http://feeds.feedburner.com/~r/blogspot/chamnap/~4/5P9_Y3S0uR8" height="1" width="1" alt=""/>http://feedproxy.google.com/~r/blogspot/chamnap/~3/5P9_Y3S0uR8/cross-domain-solutions.htmlnoreply@blogger.com (chamnap)99http://chamnapchhorn.blogspot.com/2010/07/cross-domain-solutions.htmltag:blogger.com,1999:blog-6761142148052793737.post-8799523426899345039Fri, 16 Jul 2010 03:46:00 +00002010-08-20T08:54:19.019+07:00presentationrestruby on railsREST and RAILSI made a presentation to InStedd guys recently on REST. This slide cover most parts related to REST and RAILS. Hope it could help.<br /><br /><div style="width:425px" id="__ss_4758443"><strong style="display:block;margin:12px 0 4px"><a href="http://www.slideshare.net/cchamnap/rest-web-services-in-rails" title="Rest and Rails">Rest and Rails</a></strong><object id="__sse4758443" width="425" height="355"><param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=restwebservicesinrails-100715000911-phpapp01&stripped_title=rest-web-services-in-rails" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed name="__sse4758443" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=restwebservicesinrails-100715000911-phpapp01&stripped_title=rest-web-services-in-rails" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"></embed></object><div style="padding:5px 0 12px">View more <a href="http://www.slideshare.net/">presentations</a> from <a href="http://www.slideshare.net/cchamnap">cchamnap</a>.</div></div><img src="http://feeds.feedburner.com/~r/blogspot/chamnap/~4/a_HFZmnv5Vw" height="1" width="1" alt=""/>http://feedproxy.google.com/~r/blogspot/chamnap/~3/a_HFZmnv5Vw/rest-and-rails.htmlnoreply@blogger.com (chamnap)2http://chamnapchhorn.blogspot.com/2010/07/rest-and-rails.htmltag:blogger.com,1999:blog-6761142148052793737.post-5301529849123717727Mon, 31 May 2010 07:01:00 +00002010-08-20T16:51:27.701+07:00rubyruby alias_method for class methodsGenerally, a ruby programmer could alias instance methods of a ruby object, but how could he alias class methods instead? The answer is he needs to understand how "self" works in ruby. If not yet knows, check out my <a href="http://www.slideshare.net/cchamnap/ruby-object-model-4978263">presentation</a>.<br /><br /><pre name="code" class="ruby"><br />class Foo<br /> def a; 'a'; end<br /> alias_method :alias_for_a, :a<br /><br /> def self.b; 'b'; end<br /> class &lt;&lt;self<br /> alias_method :alias_for_b, :b<br /> end<br />end<br /><br />puts Foo.new.a<br />puts Foo.new.alias_for_a<br /><br />puts Foo.b<br />puts Foo.alias_for_b<br /></pre><img src="http://feeds.feedburner.com/~r/blogspot/chamnap/~4/PX1yMdjUoTI" height="1" width="1" alt=""/>http://feedproxy.google.com/~r/blogspot/chamnap/~3/PX1yMdjUoTI/ruby-aliasmethod-for-class-methods.htmlnoreply@blogger.com (chamnap)10http://chamnapchhorn.blogspot.com/2010/05/ruby-aliasmethod-for-class-methods.htmltag:blogger.com,1999:blog-6761142148052793737.post-4129043679609270801Fri, 19 Feb 2010 10:50:00 +00002010-09-05T08:57:07.849+07:00javascriptrubyMeta-programming in Ruby and JavaScriptRecently, I have been working with writing a ruby gem, Yoolk API Gem. What is really interesting for me is I do some meta programming and object-oriented programming in Ruby which I have never experienced before. A few month later, there is a requirement that my team needs to write in JavaScript, but I don't want to touch JavaScript really much. Therefore, my team member took over this task. Whenever I write code in Ruby, I just try to think how to do it in JavaScript as well. Several things that came up to my mind with some from my team member:<br /><br />1. Defer class from a variable.<br /><pre name="code" class="javascript"><br />// JavaScript<br />var klass = "Person";<br />p = new window[klass]; //class without namespace<br />p = new yoolk[klass]; //class with namespace<br /></pre><br /><pre name="code" class="ruby"><br /># Ruby<br />klass = "Person"<br />p = Object.const_get(klass).new #class without namespace<br />p = Yoolk.const_get(klass).new #class with namespace<br /></pre><br />2. Access class method from instance object<br /><pre name="code" class="javascript"><br />// JavaScript<br />var p = new Person();<br />p.constructor.getCount();<br /></pre><br /><pre name="code" class="ruby"><br />#Ruby<br />p = Person.new<br />p.class.count<br /></pre><br />3. Define method of an object<br /><pre name="code" class="javascript"><br />//JavaScript<br />var p = new Person();<br />p.hello = function() {<br /> alert('hello');<br />};<br /></pre><br /><pre name="code" class="ruby"><br />//Ruby<br />p = Person.new<br />def p.hello<br /> puts "hello"<br />end<br /></pre><br />4. Define class methods<br /><pre name="code" class="javascript"><br />//JavaScript<br />Person.hello = function() {<br /> alert('hello');<br />};<br /></pre><br /><pre name="code" class="ruby"><br />//Ruby<br />def Person.hello<br /> puts "hello"<br />end<br /></pre><img src="http://feeds.feedburner.com/~r/blogspot/chamnap/~4/0MXP-NLE_ng" height="1" width="1" alt=""/>http://feedproxy.google.com/~r/blogspot/chamnap/~3/0MXP-NLE_ng/meta-programming-in-ruby-and-javascript.htmlnoreply@blogger.com (chamnap)8http://chamnapchhorn.blogspot.com/2010/02/meta-programming-in-ruby-and-javascript.htmltag:blogger.com,1999:blog-6761142148052793737.post-4360924167161407139Wed, 14 Oct 2009 07:16:00 +00002009-10-19T11:46:25.984+07:00ruby on railsScript Console TricksScript console in rails helps me very much to debug my applications. However, I usually encounter an annoying problem with ActiveRecord. I want to see the generated SQL that has been executed. I never have enough time to figure out this until last week. Just add the following code to your environment.rb, you could see the generated SQL statement.<br /><br /><pre name="code" class="rails"><br />if "irb" == $0<br /> ActiveRecord::Base.logger = Logger.new(STDOUT) # ActiveRecord<br /> ActiveResource::Base.logger = Logger.new(STDOUT) # ActiveResource<br />end<br /></pre><br /><br />For more information:<br /><a href="http://weblog.jamisbuck.org/2007/1/31/more-on-watching-activerecord">http://weblog.jamisbuck.org/2007/1/31/more-on-watching-activerecord</a><br /><a href="http://railscasts.com/episodes/48-console-tricks">http://railscasts.com/episodes/48-console-tricks</a><img src="http://feeds.feedburner.com/~r/blogspot/chamnap/~4/bqcq5RV8aPE" height="1" width="1" alt=""/>http://feedproxy.google.com/~r/blogspot/chamnap/~3/bqcq5RV8aPE/script-console-tricks.htmlnoreply@blogger.com (chamnap)10http://chamnapchhorn.blogspot.com/2009/10/script-console-tricks.htmltag:blogger.com,1999:blog-6761142148052793737.post-419767841573897220Thu, 08 Oct 2009 04:26:00 +00002010-08-20T08:54:33.369+07:00presentationwebMy Presentation at Barcamp Phnom Penh 2009I did two presentations at Barcampp in last week. One is for people who starts learning about the web. I talked on many basic concepts, the history, and how the web works. Some of friends complained me that my slide is too much. Anyway, I think I missed several main points. I just feel it is a prime concept of the web, and it drives me really well since I started learning it. The other is about JavaScript in OOP way. It is the same topic but very compact as I used to do presentation in my office. I did fairly good with borey since some of the audiences interest my presentation.<br /><br /><div style="width:425px;text-align:left" id="__ss_2046225"><a style="font:14px Helvetica,Arial,Sans-serif;display:block;margin:12px 0 3px 0;text-decoration:underline;" href="http://www.slideshare.net/cchamnap/introduction-to-web-architecture" title="Introduction to Web Architecture">Introduction to Web Architecture</a><object style="margin:0px" width="425" height="355"><param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=introductiontowebarchitecture-090922221506-phpapp01&stripped_title=introduction-to-web-architecture" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=introductiontowebarchitecture-090922221506-phpapp01&stripped_title=introduction-to-web-architecture" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"></embed></object><div style="font-size:11px;font-family:tahoma,arial;height:26px;padding-top:2px;">View more <a style="text-decoration:underline;" href="http://www.slideshare.net/">presentations</a> from <a style="text-decoration:underline;" href="http://www.slideshare.net/cchamnap">cchamnap</a>.</div></div><img src="http://feeds.feedburner.com/~r/blogspot/chamnap/~4/_5pkPuLAdIY" height="1" width="1" alt=""/>http://feedproxy.google.com/~r/blogspot/chamnap/~3/_5pkPuLAdIY/my-presentation-at-barcamp-phnom-penh.htmlnoreply@blogger.com (chamnap)0http://chamnapchhorn.blogspot.com/2009/10/my-presentation-at-barcamp-phnom-penh.htmltag:blogger.com,1999:blog-6761142148052793737.post-7037022000664296624Sat, 05 Sep 2009 04:33:00 +00002010-08-20T08:53:56.690+07:00presentationPrinciples in RefactoringThis week, in my office we did a study group, and vorleak and I were moderators in that session. We studied the book from Refactoring the Existing Code by Martin Fowler. Here is the slide I prepared.<br /><br /><div style="width:425px;text-align:left" id="__ss_1961578"><a style="font:14px Helvetica,Arial,Sans-serif;display:block;margin:12px 0 3px 0;text-decoration:underline;" href="http://www.slideshare.net/cchamnap/principles-in-refactoring" title="Principles in Refactoring">Principles in Refactoring</a><object style="margin:0px" width="425" height="355"><param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=principlesinrefactoring-090906230021-phpapp01&stripped_title=principles-in-refactoring" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=principlesinrefactoring-090906230021-phpapp01&stripped_title=principles-in-refactoring" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"></embed></object><div style="font-size:11px;font-family:tahoma,arial;height:26px;padding-top:2px;">View more <a style="text-decoration:underline;" href="http://www.slideshare.net/">presentations</a> from <a style="text-decoration:underline;" href="http://www.slideshare.net/cchamnap">cchamnap</a>.</div></div><img src="http://feeds.feedburner.com/~r/blogspot/chamnap/~4/dNH6usJBVPo" height="1" width="1" alt=""/>http://feedproxy.google.com/~r/blogspot/chamnap/~3/dNH6usJBVPo/principles-in-refactoring.htmlnoreply@blogger.com (chamnap)1http://chamnapchhorn.blogspot.com/2009/09/principles-in-refactoring.htmltag:blogger.com,1999:blog-6761142148052793737.post-5801985646602093655Sat, 29 Aug 2009 08:29:00 +00002010-08-20T08:54:53.957+07:00ruby on railsAction CachingRecently, I have been working with RESTful web services. I came to a caching stage where I need to cache some requests that map to my actions. The problem is that I have actions with multiple possible routes, therefore those routes should be cached differently. For example:<br /><br /><pre name="code" class="rails"><br />/people/1?display=details<br />/people/1?display=summary<br />/people/1?display=details&format=xml<br />/people/1?display=summary&format=json<br /></pre><br /><br />Fortunately, there is an option inside caches_action called :cache_path. All you need to do is to pass a proc object and return the path you want to cache. It is called with the current controller instance. In this case,<br /><pre name="code" class="rails"><br /> caches_action :index, :show, :cache_path => Proc.new { |c|<br /> request_url = { :controller => c.params[:controller], :action => c.params[:action] }.merge(c.request.query_parameters)<br /> c.url_for request_url<br /> }<br /></pre><br /><br />There is another problem when the request is coming without format, the cache returns the result with content-type: text/html. To solve this, add a before_filter inside application controller to assign the headers['Content-type'].<br /><br /><pre name="code" class="rails"><br /> def set_default_response_format<br /> response.headers['Content-type'] = 'application/xml; charset=utf-8' if params[:format].nil?<br /> end<br /></pre><img src="http://feeds.feedburner.com/~r/blogspot/chamnap/~4/D6PVrxPAB2k" height="1" width="1" alt=""/>http://feedproxy.google.com/~r/blogspot/chamnap/~3/D6PVrxPAB2k/action-caching.htmlnoreply@blogger.com (chamnap)0http://chamnapchhorn.blogspot.com/2009/08/action-caching.htmltag:blogger.com,1999:blog-6761142148052793737.post-1543620890150642532Sat, 22 Aug 2009 02:30:00 +00002010-08-20T08:55:01.947+07:00webMVCMany Rails newcomers, even some people who know MVC quite well, often confuse how to code in the right way. The controller are usually fat, and the logic spreads across the whole application. The views still messy because it contains logic and even worse people often code like a controller (query to db). However, the model are usually skinny. I could say there is no restrictions in the way you code. It is a set of disciplines that every developers must know in order to have a cheaper maintenance.<br /><br />MVC has been successful for many reasons, and some of those reasons are “readability”, “maintainability”, “modularity”, and “separation of concerns”. You’d like your code to have those properties, right? The rules of thumb are:<br /><br />1. Controller should be skinny. This is what it means to have a controller know what to do without knowing the details of how to do it. <br />2. Any complexity related to building a business logic will be specified and implemented in the Model.<br />3. Inside View, access to instance variables that have been defined in Controller. Try not to use if-else condition or loop as much as possible.<br /><br />By putting everything in the right place, you would benefit from a lot of MVC pattern.<br /><br />Good example can be found on:<br /><a href="http://www.therailsway.com/2007/6/1/railsconf-recap-skinny-controllers">http://www.therailsway.com/2007/6/1/railsconf-recap-skinny-controllers</a><br /><a href="http://weblog.jamisbuck.org/2006/10/18/skinny-controller-fat-model">http://weblog.jamisbuck.org/2006/10/18/skinny-controller-fat-model</a><img src="http://feeds.feedburner.com/~r/blogspot/chamnap/~4/us9PXi00334" height="1" width="1" alt=""/>http://feedproxy.google.com/~r/blogspot/chamnap/~3/us9PXi00334/this-is-what-it-means-to-have.htmlnoreply@blogger.com (chamnap)0http://chamnapchhorn.blogspot.com/2009/08/this-is-what-it-means-to-have.htmltag:blogger.com,1999:blog-6761142148052793737.post-7544957222579683619Tue, 21 Jul 2009 10:08:00 +00002009-07-25T17:36:12.684+07:00ruby on railsSending mail to developer about exception errorsI want my application to send me a mail about any errors that occurs during production. Basically, I want to see a detail report like in development environment. All I have to do is to override <code>rescue_action_in_public</code>. This method by default calls <code>render_optional_error_file</code> method to render a static page based on status code thrown. <code>rescue_action_locally</code> method by default will render details diagnostics from a controller action. Therefore, I just combine all of these methods into rescue_action_in_public and add some code to send mail.<br /><pre name="code" class="rails"><br />def rescue_action_in_public(exception)<br />&nbsp;&nbsp;&nbsp;render_optional_error_file response_code_for_rescue(exception)<br /><br />&nbsp;&nbsp;&nbsp;@template.instance_variable_set("@exception", exception)<br />&nbsp;&nbsp;&nbsp;@template.instance_variable_set("@rescues_path", RESCUES_TEMPLATE_PATH)<br />&nbsp;&nbsp;&nbsp;@template.instance_variable_set("@contents",<br />&nbsp;&nbsp;&nbsp;@template.render(:file => template_path_for_local_rescue(exception)))<br /><br /> # send mail to developers<br />&nbsp;&nbsp;&nbsp;mail = ExceptionNotifier.create_sent(@template)<br />&nbsp;&nbsp;&nbsp;mail.set_content_type("text/html")<br />&nbsp;&nbsp;&nbsp;ExceptionNotifier.deliver(mail)<br />end<br /></pre><br />Here is my ExceptionNotifier class, just extract needed variable to be available inside my view.<br /><pre name="code" class="rails"><br />class ExceptionNotifier < ActionMailer::Base<br /> <br />&nbsp;&nbsp;&nbsp;def sent(template)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@subject = 'Bug Reports'<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@body["request"] = template.request<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@body["response"] = template.response<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@body["exception"] = template.instance_variable_get("@exception")<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@body["rescues_path"] = template.instance_variable_get("@rescues_path")<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@recipients = ['chamnapchhorn@gmail.com', 'ungsophy@gmail.com']<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@from = 'noreply@gmail.com'<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@headers = {}<br />&nbsp;&nbsp;&nbsp;end<br /><br />end<br /></pre><br />Here is my view, the default view for exception. I just change to locate new variables only.<br /><pre name="code" class="html"><br />&lt;h1&gt;<br />&nbsp;&nbsp;&nbsp;<%=h @exception.class.to_s %><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<% if @request.parameters['controller'] %><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;in <%=h @request.parameters['controller'].humanize %>Controller<% if @request.parameters['action'] %>#<%=h @request.parameters['action'] %><% end %><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<% end %><br />&lt;/h1&gt;<br />&lt;pre&gt;<%=h @exception.clean_message %>&lt;/pre&gt;<br /><br /><%= render :file => @rescues_path["rescues/_trace.erb"] %><br /><br /><%= render :file => @rescues_path["rescues/_request_and_response.erb"], :locals => { :request => @request, :response => @response } %><br /></pre><img src="http://feeds.feedburner.com/~r/blogspot/chamnap/~4/8a-xdRT120k" height="1" width="1" alt=""/>http://feedproxy.google.com/~r/blogspot/chamnap/~3/8a-xdRT120k/sending-report-developer.htmlnoreply@blogger.com (chamnap)3http://chamnapchhorn.blogspot.com/2009/07/sending-report-developer.htmltag:blogger.com,1999:blog-6761142148052793737.post-2672112506476727939Fri, 10 Jul 2009 09:55:00 +00002009-07-25T17:42:39.274+07:00ruby on railsHandling Exception at the Application Level in RailsAt last the point of the project, I found one more important thing that is quite useful and it could reduce the code 20%. That's when I did a handling service error on both server and client. I find myself have been repeating the code on the way. Luckily, after discussion with my colleague, I came up with idea to handle in application controller. It means that instead of handle exception on all of my controllers, I could just handle in a single place whenever exception has raised from these controllers.<br />Basically, there are two methods (<code>rescue_action</code> and <code>rescue_action_in_public</code>) that you would need to override based on your needs. By default, these two methods do the best job to handle exception both in development and production mode. <code>rescue_action</code> method will be called with an exception parameter that raises inside an action method. <code>rescue_action_in_public method</code>, however, is used for public exception handling (for requests answering false to <code>local_request?</code>). <code>local_request?</code> method tells which rescue_*** method to call.<br /><br /><a href="http://api.rubyonrails.org/classes/ActionController/Rescue.html">http://api.rubyonrails.org/classes/ActionController/Rescue.html</a><br /><br />More importantly, we can handle exceptions for specific controller instead of the whole. All you need to do is to override one of these methods inside that controller.<br /><pre name="code" class="rails"><br />class PostsController < ApplicationController<br />&nbsp;&nbsp;&nbsp;def rescue_action_in_public(exception)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case(exception)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;when ActiveRecord::RecordNotFound then render :file => '/bad_record'<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;when NoMethodError then render :file => '/no_method'<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else render :file => '/error'<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end<br />&nbsp;&nbsp;&nbsp;end<br />end<br /></pre><br /><br />We can even handle them in a much cleaner way rather than if/else statement by using rescue_from. What it does is that it maps an exception type to handler method. This handler method can take either an exception parameter or a non-argument. We can even specify a proc or block.<br /><pre name="code" class="rails"><br />class PostsController < ApplicationController<br /><br />&nbsp;&nbsp;&nbsp;# Declare exception to handler methods<br />&nbsp;&nbsp;&nbsp;rescue_from ActiveRecord::RecordNotFound, :with => :bad_record<br />&nbsp;&nbsp;&nbsp;rescue_from NoMethodError, :with => :show_error<br /><br />&nbsp;&nbsp;&nbsp;def bad_record; render :file => '/bad_record'; end<br />&nbsp;&nbsp;&nbsp;def show_error(exception); render :text => exception.message; end<br /><br />end<br /></pre><br /><a href="http://ryandaigle.com/articles/2007/9/24/what-s-new-in-edge-rails-better-exception-handling">http://ryandaigle.com/articles/2007/9/24/what-s-new-in-edge-rails-better-exception-handling</a><img src="http://feeds.feedburner.com/~r/blogspot/chamnap/~4/KZCvB5p8kak" height="1" width="1" alt=""/>http://feedproxy.google.com/~r/blogspot/chamnap/~3/KZCvB5p8kak/handling-exception-at-application-level.htmlnoreply@blogger.com (chamnap)1http://chamnapchhorn.blogspot.com/2009/07/handling-exception-at-application-level.htmltag:blogger.com,1999:blog-6761142148052793737.post-3156078894202383489Sat, 27 Jun 2009 11:05:00 +00002009-07-27T11:08:18.571+07:00javascriptMaintaining Javascript Pop-Up Window Communication Across Window Opener Page LoadsI came across a blog post that talks how to maintain a reference to javascript popup window while the parent window has been navigated away. This scenario doesn't want to reload the child popup window. I just quoted out from <a href="http://www.1pixelout.net/2006/12/15/cross-window-javascript-communication-20/">1 Pixel Out</a>. There is a really nick trick.<br /><br />In the main window:<br /><pre name="code" class="javascript"><br />var popupWin = null;<br /><br />function openPopup() {<br />&nbsp;&nbsp;&nbsp;var url = "popup.htm";<br />&nbsp;&nbsp;&nbsp;popupWin = open( "", "popupWin", "width=500,height=400" );<br />&nbsp;&nbsp;&nbsp;if( !popupWin || popupWin.closed || !popupWin.doSomething ) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;popupWin = window.open( url, "popupWin", "width=500,height=400" );<br />&nbsp;&nbsp;&nbsp;} else {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;popupWin.focus();<br />&nbsp;&nbsp;&nbsp;}<br />}<br /><br />function doSomething() {<br />&nbsp;&nbsp;&nbsp;openPopup();<br />&nbsp;&nbsp;&nbsp;popupWin.doSomething();<br />}<br /></pre><br /><br />In the popup:<br /><pre name="code" class="javascript"><br />self.focus();<br /><br />function doSomething() {<br />&nbsp;&nbsp;&nbsp;alert("I'm doing something");<br />}<br /></pre><br /><br /><a href="http://www.bennadel.com/blog/89-Maintaining-Javascript-Pop-Up-Window-Communication-Across-Window-Opener-Page-Loads.htm">http://www.bennadel.com/blog/89-Maintaining-Javascript-Pop-Up-Window-Communication-Across-Window-Opener-Page-Loads.htm</a><br /><a href="http://www.1pixelout.net/2005/04/19/cross-window-javascript-communication/">http://www.1pixelout.net/2005/04/19/cross-window-javascript-communication/</a><br /><a href="http://www.1pixelout.net/2006/12/15/cross-window-javascript-communication-20/">http://www.1pixelout.net/2006/12/15/cross-window-javascript-communication-20/</a><br /><a href="http://www.1pixelout.net/wp-content/downloads/popups20.zip">http://www.1pixelout.net/wp-content/downloads/popups20.zip</a><img src="http://feeds.feedburner.com/~r/blogspot/chamnap/~4/NCR2zrEr16s" height="1" width="1" alt=""/>http://feedproxy.google.com/~r/blogspot/chamnap/~3/NCR2zrEr16s/maintaining-javascript-pop-up-window.htmlnoreply@blogger.com (chamnap)3http://chamnapchhorn.blogspot.com/2009/06/maintaining-javascript-pop-up-window.htmltag:blogger.com,1999:blog-6761142148052793737.post-8426930390371482210Sat, 27 Jun 2009 07:10:00 +00002009-07-27T11:10:14.969+07:00javascriptCross-window Javascript communicationIt reminds me about uploading via iframe that I did a year ago when my colleague asked me to help with login openid in a popup window. It's a similar story with this problem. Actually, login with openid could not place in a iframe because you could the code that prevents this.<br /><pre name="code" class="javascript"><br />&lt;script type="text/javascript"&gt;if(top == self) { document.write(""); } else { top.location.href = "http://www.yahoo.com"; }&lt;/script&gt;<br /></pre><br />Now, let's see a quick summary on this basic communication.<br /><br />Communication from parent to child window, you need to a reference of the child window so that can call any function in the child window.<br /><pre name="code" class="javascript"><br />// Create a new popup window<br />var popupWin = window.open(url, "popupWin");<br /><br />// To call functions defined in the popup:<br />popupWin.doSomething();<br /></pre><br />Communication from child to parent window, you need to use this way:<br /><pre name="code" class="javascript"><br />window.opener.doSomethingOnParent();<br /></pre><br />Here is the problem, the parent window needs to know when the uploading (in iframe) or logging in (in popup window) is done. The only way that the parent window can notified by the child window after finish processing. Usually, for uploading and logging in with openid, the action in your controller would render a view back. The trick is here on the onload of the body, you could notify the parent window.<br /><pre name="code" class="rails"><br />def login<br /> @status = "something"<br />end<br /><br />#view<br />&lt;html&gt;&lt;head&gt;&lt;/head&gt;<br />&lt;body onload="window.opener.handleOpenIDResponse('" + @status + "');window.close();"&gt;<br />&lt;/body&gt;<br />&lt;/html&gt;<br /></pre><br />That would solve the problem, and you could send any information back through your view.<img src="http://feeds.feedburner.com/~r/blogspot/chamnap/~4/armXt65b69s" height="1" width="1" alt=""/>http://feedproxy.google.com/~r/blogspot/chamnap/~3/armXt65b69s/cross-window-javascript-communication.htmlnoreply@blogger.com (chamnap)0http://chamnapchhorn.blogspot.com/2009/06/cross-window-javascript-communication.htmltag:blogger.com,1999:blog-6761142148052793737.post-8509927370996612874Thu, 18 Jun 2009 08:46:00 +00002009-07-27T11:16:22.953+07:00ruby on railshas_and_belongs_to_many or has_many :through?Well, I had been quite confusing about these two topics before I read some rails books. These are just different ways to do many to many relationships in ActiveRecord.<br /><br /><b>has_and_belongs_to_many (habtm)</b><br />habtm is the very old way since rails 1.2. It creates a link between associated models through an intermediate join table.<br /><pre name="code" class="rails"><br />class CreateProjectsProgrammers < ActiveRecord::Migration<br />&nbsp;&nbsp;&nbsp;def self.up<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;create_table :projects_programmers, :id => false do |t|<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t.column :project_id, :integer, :null => false<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t.column :programmer_id, :integer, :null => false<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end<br />&nbsp;&nbsp;&nbsp;end<br />&nbsp;&nbsp;&nbsp;def self.down<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;drop_table :projects_programmers<br />&nbsp;&nbsp;&nbsp;end<br />end<br />class Programmer < ActiveRecord::Base<br />&nbsp;&nbsp;&nbsp;has_and_belongs_to_many :projects # foreign keys in the join table<br />end<br />class Project < ActiveRecord::Base<br />&nbsp;&nbsp;&nbsp;has_and_belongs_to_many :programmers # foreign keys in the join table<br />end<br /></pre><br />Note that an id primary key is not needed in the join table and there is no join model, only join table. Here we will face a problem when we want to add extra columns on the join table. If it is in rails 1.2, we would have used <code>push_with_attributes</code> to do this. However, <code>push_with_attributes</code> has been deprecated in favor of a far more powerful technique, where regular Active Record models are used as join tables (remember that with habtm, the join table is not an Active Record object).<br /><br />To conclude, habtm is a simple way to do a many-to-many relationship using a join table when the join table doesn't have extra columns. You will need to upgrade the relationship to use <code>has_many :through</code> once you need to add additional columns.<br /><br /><b>has_many :through</b><br />Records in the join table of habtm implementation has no independent existence. Later, we will find it very soon that the join table has a life of its own and should have a model when we add extra columns on that join table. Let's talk about relationship between article, user, and the join model is reading.<br /><br />When a user reads an article, we can record the fact.<br /><pre name="code" class="javascript"><br />class Article < ActiveRecord::Base<br />&nbsp;&nbsp;&nbsp;has_many :readings<br />end<br />class User < ActiveRecord::Base<br />&nbsp;&nbsp;&nbsp;has_many :readings<br />end<br />class Reading < ActiveRecord::Base<br />&nbsp;&nbsp;&nbsp;belongs_to :article<br />&nbsp;&nbsp;&nbsp;belongs_to :user<br />end<br /><br />reading = Reading.new<br />reading.rating = params[:rating]<br />reading.read_at = Time.now<br />reading.article = current_article<br />reading.user = session[:user]<br />reading.save<br /></pre><br /><br />Here we lost what habtm solved. We could not ask a user which articles that they has read and vice versa. To solve this, use :through options inside has_many.<br /><pre name="code" class="javascript"><br />class Article < ActiveRecord::Base<br />&nbsp;&nbsp;&nbsp;has_many :readings<br />&nbsp;&nbsp;&nbsp;has_many :users, :through => :readings<br />end<br />class Reading < ActiveRecord::Base<br />&nbsp;&nbsp;&nbsp;belongs_to :article<br />&nbsp;&nbsp;&nbsp;belongs_to :user<br />end<br />class User < ActiveRecord::Base<br />&nbsp;&nbsp;&nbsp;has_many :readings<br />&nbsp;&nbsp;&nbsp;has_many :articles, :through => :readings<br />end<br /></pre><br />Now, you could do query both direction:<br /><pre name="code" class="javascript"><br />readers = an_article.users<br />articles = a_reader.articles<br /></pre><br /><br />Unlike a normal has_many, ActiveRecord won’t let us add an object to the the has_many :through association if both ends of the relationship are unsaved records. The create method saves the record before adding it, so it does work as expected, provided the parent object isn’t unsaved itself. To add extra attributes:<br /><br /><pre name="code" class="javascript"><br />user.readings.create(:read_at => Time.now,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:rating => params[:rating],<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:article => Article.new)<br /></pre><br /><br />Choosing which way to build a many-to-many relationship is not always simple. If you need to work with the relationship model as its own entity, use has_many :through. Use has_and_belongs_to_many when working with legacy schemas or when you never work directly with the relationship itself.<br /><br /><a href="http://blog.hasmanythrough.com/2006/4/20/many-to-many-dance-off">http://blog.hasmanythrough.com/2006/4/20/many-to-many-dance-off</a><br /><a href="http://blog.hasmanythrough.com/2006/4/17/join-models-not-proxy-collections">http://blog.hasmanythrough.com/2006/4/17/join-models-not-proxy-collections</a><img src="http://feeds.feedburner.com/~r/blogspot/chamnap/~4/xviTAcPEs2c" height="1" width="1" alt=""/>http://feedproxy.google.com/~r/blogspot/chamnap/~3/xviTAcPEs2c/hasandbelongstomany-or-hasmany-through.htmlnoreply@blogger.com (chamnap)2http://chamnapchhorn.blogspot.com/2009/06/hasandbelongstomany-or-hasmany-through.htmltag:blogger.com,1999:blog-6761142148052793737.post-2856585702419930140Wed, 03 Jun 2009 01:23:00 +00002009-07-27T11:12:21.377+07:00ruby on railsProper use of sessionConsider the following scenario, you want to store information about current user. After successful login, you might do this.<br /><pre name="code" class="javascript"><br />user = User.authenticate(params[:user_name], params[:password])<br />if user<br />&nbsp;&nbsp;&nbsp;session[:current_user] = user.attributes<br />else<br />&nbsp;&nbsp;&nbsp;flash[:notice] = "Email and password do not match."<br />&nbsp;&nbsp;&nbsp;redirect_to :controller => "login"<br />end<br /></pre><br /><br />Everything would work as you expected except when you try to change the structure of your session. This would make sessions of online users invalid while they are using your web application. For example, they will feel annoying while they are adding items to their wish lists. Another problem is that you want to make that session invalid after you delete that user account, for example. That won't work because you stored the entire record in his session. The only way to do is to add before_filter in application controller to check the existence of the current user. That would make another job to do it.<br /><br />The best practice is store only simple data in the session: strings, numbers, and so on. Keep your application objects in the database, and then reference them using their primary keys from the session data. <br /><pre name="code" class="javascript"><br />class ApplicationController < ActionController::Base<br />&nbsp;&nbsp;&nbsp;before_filter :get_current_user<br /><br />&nbsp;&nbsp;&nbsp;private<br />&nbsp;&nbsp;&nbsp;def get_current_user<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@current_user = User.find_by_id(session[:user_id])<br />&nbsp;&nbsp;&nbsp;end<br />end<br /></pre><br />Here you can access @current_user everywhere in your application and solve many issues during development.<img src="http://feeds.feedburner.com/~r/blogspot/chamnap/~4/jcyT8Zbwd9A" height="1" width="1" alt=""/>http://feedproxy.google.com/~r/blogspot/chamnap/~3/jcyT8Zbwd9A/proper-use-of-session.htmlnoreply@blogger.com (chamnap)0http://chamnapchhorn.blogspot.com/2009/06/proper-use-of-session.htmltag:blogger.com,1999:blog-6761142148052793737.post-7762041590822974093Thu, 14 May 2009 04:03:00 +00002009-07-27T11:15:16.358+07:00ruby on railsCustom Rake TasksI came across to write a custom rake script for my rails application. Because my application is rich client side application and doesn't use id for any of my models. Instead, it used UUID as a primary key. I got some problems while changing this, and one of them is rails rake commands such as rake <code>db:test:prepare, rake test:functionals</code>, .... For my application, these two commands didn't work really well since it makes my test database messed with autonumber id of all tables. Here, my rake script to load to my test database. Pay attention to mysql command, in this case, I need to run several commands inside mysql command.<br /><br /><pre name="code" class="rails"><br /> task :load_test_db do<br /> #load data to development<br /> Rake::Task["db:fixtures:load"].invoke<br /> <br /> #clone development to test<br /> Rake::Task["db:test:clone_structure"].invoke<br /> <br /> #pull data from development<br /> sh "mysqldump > test.sql development_ncdd_templates -u root"<br /><br /> sh "mysql -u root << EOF<br /> use test_ncdd_templates;<br /> source test.sql;<br /> exit<br /> EOF"<br /> end<br /></pre><br /><br />If you want to run bash command, take this as an example. I'm not a expert of shell script, but it works for me anyway.<br /><br /> sh "#!/bin/bash<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cd lib<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ruby to_yml.rb<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cd .."<br /><br />Here are some excellent sources:<br /><a href="http://www.railsenvy.com/2007/6/11/ruby-on-rails-rake-tutorial">http://www.railsenvy.com/2007/6/11/ruby-on-rails-rake-tutorial</a><br /><a href="http://railscasts.com/episodes/66-custom-rake-tasks">http://railscasts.com/episodes/66-custom-rake-tasks</a><img src="http://feeds.feedburner.com/~r/blogspot/chamnap/~4/xZG8Z0kQ_V4" height="1" width="1" alt=""/>http://feedproxy.google.com/~r/blogspot/chamnap/~3/xZG8Z0kQ_V4/custom-rake-tasks.htmlnoreply@blogger.com (chamnap)2http://chamnapchhorn.blogspot.com/2009/05/custom-rake-tasks.htmltag:blogger.com,1999:blog-6761142148052793737.post-4515566835543181045Wed, 13 May 2009 03:59:00 +00002009-05-13T11:08:03.262+07:00javascriptJavaScript in Object-Oriented WayI conducted a training to some developers in my office about one full day, yesterday. It is quite exhausted anyway, but everyone seems understand really well. This slide covers many advanced features of JavaScript: Function, Object, Closure,.... Some other points I have pointed out in this slide are about how to make private variable, public variable, static variable, privileged variable and how to do inheritance. I took about 20 different sources as my references and three famous authors. It took me two weeks, at every weekend, to finish this slide.<br /><br /><div style="width:425px;text-align:left" id="__ss_1426608"><a style="font:14px Helvetica,Arial,Sans-serif;display:block;margin:12px 0 3px 0;text-decoration:underline;" href="http://www.slideshare.net/cchamnap/javascript-in-objectoriented-way?type=powerpoint" title="JavaScript in Object-Oriented Way">JavaScript in Object-Oriented Way</a><object style="margin:0px" width="425" height="355"><param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=javascriptinobject-orientedway-090512225827-phpapp02&stripped_title=javascript-in-objectoriented-way" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=javascriptinobject-orientedway-090512225827-phpapp02&stripped_title=javascript-in-objectoriented-way" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"></embed></object><div style="font-size:11px;font-family:tahoma,arial;height:26px;padding-top:2px;">View more <a style="text-decoration:underline;" href="http://www.slideshare.net/">presentations</a> from <a style="text-decoration:underline;" href="http://www.slideshare.net/cchamnap">cchamnap</a>.</div></div><img src="http://feeds.feedburner.com/~r/blogspot/chamnap/~4/i9A3dShRbxU" height="1" width="1" alt=""/>http://feedproxy.google.com/~r/blogspot/chamnap/~3/i9A3dShRbxU/javascript-in-object-oriented-way.htmlnoreply@blogger.com (chamnap)2http://chamnapchhorn.blogspot.com/2009/05/javascript-in-object-oriented-way.htmltag:blogger.com,1999:blog-6761142148052793737.post-5429879078678621629Thu, 07 May 2009 04:41:00 +00002009-06-14T15:50:38.107+07:00javascriptJavaScript MixinsI have just reviewed JavaScript Design Patterns, and I think it is good to mention this.<br /><br />It is possible to do a mixin class in JavaScript as in Ruby. This is another way to make our code reuse without inheritance. Consider you have a function, and you wish to use in many classes. In practice, you create a class that contains your general-purpose methods, and then use it to augment other classes. Class with these general-purpose methods is called Mixin class. It is generally not instantiated or called directly, instead it exists to provide methods to other classes.<br /><br /><code><br />var Mixin = function() {};<br />Mixin.prototype = {<br />&nbsp;&nbsp;&nbsp;serialize: function() {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var output = [];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for(key in this) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;output.push(key + ': ' + this[key]);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return output.join(', ');<br />&nbsp;&nbsp;&nbsp;}<br />};<br /></code><br /><br />This sort of method could potentially be useful in many different types of classes, but it doesn’t make sense to have each of these classes inherit from Mixin. Similarly, duplicating the code in each class doesn’t make much sense either. The best approach is to use the augment function to add this method to each class that needs it:<br /><br /><code><br />augment(Author, Mixin);<br /><br />var author = new Author('Ross Harmes', ['JavaScript Design Patterns']);<br />var serializedString = author.serialize();<br /></code><br /><br />This can be thought of as a way to implement multiple inheritance in JavaScript.<br /><br /><code><br />/* Augment function. */<br />function augment(receivingClass, givingClass) {<br />&nbsp;&nbsp;&nbsp;for(methodName in givingClass.prototype) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(!receivingClass.prototype[methodName]) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;receivingClass.prototype[methodName] = givingClass.prototype[methodName];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;}<br />}<br /></code><br /><br />A more robust augment allows copying one or two of them over to another class.<br /><code><br />/* Augment function, improved. */<br />function augment(receivingClass, givingClass) {<br />&nbsp;&nbsp;&nbsp;if(arguments[2]) { // Only give certain methods.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for(var i = 2, len = arguments.length; i < len; i++) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;receivingClass.prototype[arguments[i]] = givingClass.prototype[arguments[i]];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;else { // Give all methods.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for(methodName in givingClass.prototype) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(!receivingClass.prototype[methodName]) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;receivingClass.prototype[methodName] = givingClass.prototype[methodName];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;}<br />}<br /></code><br /><br />You can now write augment(Author, Mixin, 'serialize'); to only augment Author with the single serialize method.<br /><br />In other times, you don't have to need this augment function in order to do Mixins. You could do this by using apply or call method inside constructor function.<br /><br /><code><br />var Author = function(name, books) {<br />&nbsp;&nbsp;&nbsp;this.name = name || "";<br />&nbsp;&nbsp;&nbsp;this.books = books || [];<br /><br />&nbsp;&nbsp;&nbsp;Mixin.apply(this);<br />};<br /></code><br /><br />Often it makes more sense to augment a class with a few methods than it does to make<br />one class inherit from another. This is a lightweight way to prevent code duplication. Unfortunately, there aren’t many situations where it can be used. Only methods general enough to be used in very dissimilar classes make good candidates for sharing (if the classes aren’t that dissimilar, normal inheritance is often a better choice).<img src="http://feeds.feedburner.com/~r/blogspot/chamnap/~4/8DSAEbZeL1k" height="1" width="1" alt=""/>http://feedproxy.google.com/~r/blogspot/chamnap/~3/8DSAEbZeL1k/javascript-mixins.htmlnoreply@blogger.com (chamnap)110http://chamnapchhorn.blogspot.com/2009/05/javascript-mixins.htmltag:blogger.com,1999:blog-6761142148052793737.post-8560760159261924Thu, 07 May 2009 04:40:00 +00002010-01-11T09:52:47.042+07:00javascriptPrototypal Inheritance vs. Classical InheritanceWhile it is possible to emulate classical inheritance like Java or C#, it is clear that we do prototypal inheritance by taking advantages of prototype lookup chains. Each has its own advantages and disadvantages. Here I quoted from JavaScript Design Patterns:<br /><br />The classical approach to creating an object is to (a) define the structure of the object, using<br />a class declaration, and (b) instantiate that class to create a new object. Objects created in this<br />manner have their own copies of all instance attributes, plus a link to the single copy of each<br />of the instance methods.<br /><br />In prototypal inheritance, instead of defining the structure through a class, you simply<br />create an object. This object then gets reused by new objects, thanks to the way that prototype<br />chain lookups work. It is called the <span style="font-style:italic;">prototype object</span> because it provides a prototype for what the other objects should look like.<br /><br />Instead of using a constructor function named Person to define the class structure, Person<br />is now an object literal. It is the prototype object for any other Person-like objects that you want to create. Define all attributes and methods you want these objects to have, and give them<br />default values. <br /><br /><code><br />/* Person Prototype Object. */<br />var Person = {<br /> name: 'default name',<br /> getName: function() {<br /> return this.name;<br /> }<br />};<br /><br />var reader = clone(Person);<br />alert(reader.getName()); // This will output 'default name'.<br />reader.name = 'John Smith';<br />alert(reader.getName()); // This will now output 'John Smith'.<br /></code><br /><br />To create a new Person-like object, use the clone function. This provides an empty object with<br />the prototype attribute set to the prototype object. This means that if any method or attribute<br />lookup on this object fails, that lookup will instead look to the prototype object.<br />To create Author, you make a clone.<br /><br /><code><br />/* Author Prototype Object. */<br />var Author = clone(Person);<br />Author.books = []; // Default value.<br />Author.getBooks = function() {<br /> return this.books;<br />}<br /><br />var author0 = clone(Author);<br />author0.name = 'Dustin Diaz';<br />author0.books = ['JavaScript Design Patterns'];<br />var author1 = clone(Author);<br />author1.name = 'Ross Harmes';<br />author1.books = ['JavaScript Design Patterns'];<br /></code><br />Here is the clone function. First the clone function creates a new and empty function, F. It then sets the prototype attribute of F to the prototype object. Lastly, the function creates a new object by calling the new operator on F. The cloned object that is returned is completely empty, except for the prototype attribute, which is (indirectly) pointing to the prototype object, by way of the F object.<br /><code><br />/* Clone function. */<br />function clone(object) {<br /> function F() {}<br /> F.prototype = object;<br /> return new F;<br />}<br /></code><br /><br />In classical inheritance, each instance of Author has its own copy of the books array. You could add to it by writing author1.books.push('New Book Title'). That is not initially possible with the object you created using prototypal inheritance because of the way prototype chaining works. A clone is not a fully independent copy of its prototype object; it is a new empty object with its prototype attribute set to the prototype object. When it is just created, author1.name is actually a link back to the primitive Person.name. When you write to author1.name, you are defining a new attribute directly on the author1 object.<br /><br /><code><br />var authorClone = clone(Author);<br />alert(authorClone.name); // Linked to the primative Person.name, which is the<br /> // string 'default name'.<br />authorClone.name = 'new name'; // A new primative is created and added to the<br /> // authorClone object itself.<br />alert(authorClone.name); // Now linked to the primative authorClone.name, which<br /> // is the string 'new name'.<br />authorClone.books.push('new book'); // authorClone.books is linked to the array<br /> // Author.books. We just modified the<br /> // prototype object's default value, and all<br /> // other objects that link to it will now<br /> // have a new default value there.<br />authorClone.books = []; // A new array is created and added to the authorClone<br /> // object itself.<br />authorClone.books.push('new book'); // We are now modifying that new array.<br /></code><br /><br />Classical inheritance is well understood, both in JavaScript and the programmer commu-<br />nity in general. Almost all object-oriented code written in JavaScript uses this paradigm. If you<br />are creating an API for widespread use, or if there is the possibility that other programmers not<br />familiar with prototypal inheritance will be working on your code, it is best to go with classical.<br /><br />JavaScript is the only popular, widely used language that uses prototypal inheritance, so odds<br />are most people will never have used it before. It can also be confusing to have an object with<br />links back to its prototype object. Programmers who don’t fully understand prototypal inheri-<br />tance will think of this as some sort of reverse inheritance, where the parent inherits from its<br />children. Even though this isn’t the case, it can still be a very confusing topic. But since this<br />form of classical inheritance is only imitating true class-based inheritance, advanced JavaScript<br />programmers need to understand how prototypal inheritance truly works at some point any-<br />way. Some would argue that hiding this fact does more harm than good.<img src="http://feeds.feedburner.com/~r/blogspot/chamnap/~4/4OrxwJxVsKE" height="1" width="1" alt=""/>http://feedproxy.google.com/~r/blogspot/chamnap/~3/4OrxwJxVsKE/prototypal-inheritance-vs-classical.htmlnoreply@blogger.com (chamnap)0http://chamnapchhorn.blogspot.com/2009/05/prototypal-inheritance-vs-classical.htmltag:blogger.com,1999:blog-6761142148052793737.post-3190805459986718748Wed, 29 Apr 2009 01:33:00 +00002009-05-23T09:57:06.203+07:00ruby on railsActiveRecord::DirtyAnother powerful feature of ActiveRecord is dirty objects. This module tracks unsaved attribute changes. This feature is available probably since <a href="http://ryandaigle.com/articles/2008/3/31/what-s-new-in-edge-rails-dirty-objects">March, 2008</a>. See examples below:<br /><br /><b>A newly instantiated object is unchanged:</b><br /><code><br /> person = Person.find_by_name('uncle bob')<br /> person.changed? # => false<br /></code><br /><b>Change the name:</b><br /><code><br /> person.name = 'Bob'<br /> person.changed? # => true<br /> person.name_changed? # => true<br /> person.name_was # => 'uncle bob'<br /> person.name_change # => ['uncle bob', 'Bob']<br /> person.name = 'Bill'<br /> person.name_change # => ['uncle bob', 'Bill']<br /></code><br /><b>Save the changes:</b><br /><code><br /> person.save<br /> person.changed? # => false<br /> person.name_changed? # => false<br /></code><br /><b>Assigning the same value leaves the attribute unchanged:</b><br /><code><br /> person.name = 'Bill'<br /> person.name_changed? # => false<br /> person.name_change # => nil<br /></code><br /><b>Which attributes have changed?</b><br /><code><br /> person.name = 'bob'<br /> person.changed # => ['name']<br /> person.changes # => { 'name' => ['Bill', 'bob'] }<br /></code><br /><b>Before modifying an attribute in-place:</b><br /><code><br /> person.name_will_change!<br /> person.name << 'by'<br /> person.name_change # => ['uncle bob', 'uncle bobby']<br /></code><img src="http://feeds.feedburner.com/~r/blogspot/chamnap/~4/EzShHrQeQ3k" height="1" width="1" alt=""/>http://feedproxy.google.com/~r/blogspot/chamnap/~3/EzShHrQeQ3k/activerecorddirty.htmlnoreply@blogger.com (chamnap)2http://chamnapchhorn.blogspot.com/2009/04/activerecorddirty.htmlen-us