<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2enclosuresfull.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0"><channel><atom:id>tag:blogger.com,1999:blog-6761142148052793737</atom:id><lastBuildDate>Thu, 12 Nov 2009 09:11:02 +0000</lastBuildDate><title>Web Development</title><description>Web 2.0, Ruby, Rails, TDD, BDD, &lt;br&gt;rSpec, XMPP, BOSH, REST,&lt;br&gt;Javascript, Ajax, Google Maps API, &lt;br&gt;Google Gears API, CSS, &lt;br&gt;Java, C#, Social Network, RMagick</description><link>http://chamnapchhorn.blogspot.com/</link><managingEditor>chamnapchhorn@gmail.com (chamnap)</managingEditor><generator>Blogger</generator><openSearch:totalResults>94</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/blogspot/chamnap" type="application/rss+xml" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6761142148052793737.post-4360924167161407139</guid><pubDate>Wed, 14 Oct 2009 07:16:00 +0000</pubDate><atom:updated>2009-10-19T11:46:25.984+07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">ruby on rails</category><title>Script Console Tricks</title><description>Script 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.&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="rails"&gt;&lt;br /&gt;if "irb" == $0&lt;br /&gt;  ActiveRecord::Base.logger = Logger.new(STDOUT)  # ActiveRecord&lt;br /&gt;  ActiveResource::Base.logger = Logger.new(STDOUT)  # ActiveResource&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;For more information:&lt;br /&gt;&lt;a href="http://weblog.jamisbuck.org/2007/1/31/more-on-watching-activerecord"&gt;http://weblog.jamisbuck.org/2007/1/31/more-on-watching-activerecord&lt;/a&gt;&lt;br /&gt;&lt;a href="http://railscasts.com/episodes/48-console-tricks"&gt;http://railscasts.com/episodes/48-console-tricks&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6761142148052793737-4360924167161407139?l=chamnapchhorn.blogspot.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/chamnap/~4/bqcq5RV8aPE" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/blogspot/chamnap/~3/bqcq5RV8aPE/script-console-tricks.html</link><author>chamnapchhorn@gmail.com (chamnap)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://chamnapchhorn.blogspot.com/2009/10/script-console-tricks.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6761142148052793737.post-419767841573897220</guid><pubDate>Thu, 08 Oct 2009 04:26:00 +0000</pubDate><atom:updated>2009-10-08T11:43:20.478+07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">web</category><title>My Presentation at Barcamp Phnom Penh 2009</title><description>I 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.&lt;br /&gt;&lt;br /&gt;&lt;div style="width:425px;text-align:left" id="__ss_2046225"&gt;&lt;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"&gt;Introduction to Web Architecture&lt;/a&gt;&lt;object style="margin:0px" width="425" height="355"&gt;&lt;param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=introductiontowebarchitecture-090922221506-phpapp01&amp;stripped_title=introduction-to-web-architecture" /&gt;&lt;param name="allowFullScreen" value="true"/&gt;&lt;param name="allowScriptAccess" value="always"/&gt;&lt;embed src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=introductiontowebarchitecture-090922221506-phpapp01&amp;stripped_title=introduction-to-web-architecture" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div style="font-size:11px;font-family:tahoma,arial;height:26px;padding-top:2px;"&gt;View more &lt;a style="text-decoration:underline;" href="http://www.slideshare.net/"&gt;presentations&lt;/a&gt; from &lt;a style="text-decoration:underline;" href="http://www.slideshare.net/cchamnap"&gt;cchamnap&lt;/a&gt;.&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6761142148052793737-419767841573897220?l=chamnapchhorn.blogspot.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/chamnap/~4/_5pkPuLAdIY" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/blogspot/chamnap/~3/_5pkPuLAdIY/my-presentation-at-barcamp-phnom-penh.html</link><author>chamnapchhorn@gmail.com (chamnap)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><enclosure url="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=introductiontowebarchitecture-090922221506-phpapp01&amp;stripped_title=introduction-to-web-architecture" length="121441" type="application/x-shockwave-flash" /><feedburner:origLink>http://chamnapchhorn.blogspot.com/2009/10/my-presentation-at-barcamp-phnom-penh.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6761142148052793737.post-7037022000664296624</guid><pubDate>Sat, 05 Sep 2009 04:33:00 +0000</pubDate><atom:updated>2009-09-07T13:17:53.090+07:00</atom:updated><title>Principles in Refactoring</title><description>This 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.&lt;br /&gt;&lt;br /&gt;&lt;div style="width:425px;text-align:left" id="__ss_1961578"&gt;&lt;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"&gt;Principles in Refactoring&lt;/a&gt;&lt;object style="margin:0px" width="425" height="355"&gt;&lt;param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=principlesinrefactoring-090906230021-phpapp01&amp;stripped_title=principles-in-refactoring" /&gt;&lt;param name="allowFullScreen" value="true"/&gt;&lt;param name="allowScriptAccess" value="always"/&gt;&lt;embed src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=principlesinrefactoring-090906230021-phpapp01&amp;stripped_title=principles-in-refactoring" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div style="font-size:11px;font-family:tahoma,arial;height:26px;padding-top:2px;"&gt;View more &lt;a style="text-decoration:underline;" href="http://www.slideshare.net/"&gt;presentations&lt;/a&gt; from &lt;a style="text-decoration:underline;" href="http://www.slideshare.net/cchamnap"&gt;cchamnap&lt;/a&gt;.&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6761142148052793737-7037022000664296624?l=chamnapchhorn.blogspot.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/chamnap/~4/dNH6usJBVPo" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/blogspot/chamnap/~3/dNH6usJBVPo/principles-in-refactoring.html</link><author>chamnapchhorn@gmail.com (chamnap)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><enclosure url="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=principlesinrefactoring-090906230021-phpapp01&amp;stripped_title=principles-in-refactoring" length="121520" type="application/x-shockwave-flash" /><feedburner:origLink>http://chamnapchhorn.blogspot.com/2009/09/principles-in-refactoring.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6761142148052793737.post-5801985646602093655</guid><pubDate>Sat, 29 Aug 2009 08:29:00 +0000</pubDate><atom:updated>2009-09-13T14:37:12.345+07:00</atom:updated><title>Action Caching</title><description>Recently, 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:&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="rails"&gt;&lt;br /&gt;/people/1?display=details&lt;br /&gt;/people/1?display=summary&lt;br /&gt;/people/1?display=details&amp;format=xml&lt;br /&gt;/people/1?display=summary&amp;format=json&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;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,&lt;br /&gt;&lt;pre name="code" class="rails"&gt;&lt;br /&gt;  caches_action :index, :show, :cache_path =&gt; Proc.new { |c|&lt;br /&gt;    request_url = { :controller =&gt; c.params[:controller], :action =&gt; c.params[:action] }.merge(c.request.query_parameters)&lt;br /&gt;    c.url_for request_url&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;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'].&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="rails"&gt;&lt;br /&gt;  def set_default_response_format&lt;br /&gt;    response.headers['Content-type'] = 'application/xml; charset=utf-8' if params[:format].nil?&lt;br /&gt;  end&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6761142148052793737-5801985646602093655?l=chamnapchhorn.blogspot.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/chamnap/~4/D6PVrxPAB2k" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/blogspot/chamnap/~3/D6PVrxPAB2k/action-caching.html</link><author>chamnapchhorn@gmail.com (chamnap)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://chamnapchhorn.blogspot.com/2009/08/action-caching.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6761142148052793737.post-1543620890150642532</guid><pubDate>Sat, 22 Aug 2009 02:30:00 +0000</pubDate><atom:updated>2009-09-13T13:50:40.356+07:00</atom:updated><title>MVC</title><description>Many 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.&lt;br /&gt;&lt;br /&gt;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:&lt;br /&gt;&lt;br /&gt;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. &lt;br /&gt;2. Any complexity related to building a business logic will be specified and implemented in the Model.&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;By putting everything in the right place, you would benefit from a lot of MVC pattern.&lt;br /&gt;&lt;br /&gt;Good example can be found on:&lt;br /&gt;&lt;a href="http://www.therailsway.com/2007/6/1/railsconf-recap-skinny-controllers"&gt;http://www.therailsway.com/2007/6/1/railsconf-recap-skinny-controllers&lt;/a&gt;&lt;br /&gt;&lt;a href="http://weblog.jamisbuck.org/2006/10/18/skinny-controller-fat-model"&gt;http://weblog.jamisbuck.org/2006/10/18/skinny-controller-fat-model&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6761142148052793737-1543620890150642532?l=chamnapchhorn.blogspot.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/chamnap/~4/us9PXi00334" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/blogspot/chamnap/~3/us9PXi00334/this-is-what-it-means-to-have.html</link><author>chamnapchhorn@gmail.com (chamnap)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://chamnapchhorn.blogspot.com/2009/08/this-is-what-it-means-to-have.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6761142148052793737.post-7544957222579683619</guid><pubDate>Tue, 21 Jul 2009 10:08:00 +0000</pubDate><atom:updated>2009-07-25T17:36:12.684+07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">ruby on rails</category><title>Sending mail to developer about exception errors</title><description>I 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 &lt;code&gt;rescue_action_in_public&lt;/code&gt;. This method by default calls &lt;code&gt;render_optional_error_file&lt;/code&gt; method to render a static page based on status code thrown. &lt;code&gt;rescue_action_locally&lt;/code&gt; 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.&lt;br /&gt;&lt;pre name="code" class="rails"&gt;&lt;br /&gt;def rescue_action_in_public(exception)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;render_optional_error_file response_code_for_rescue(exception)&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;@template.instance_variable_set("@exception", exception)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;@template.instance_variable_set("@rescues_path", RESCUES_TEMPLATE_PATH)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;@template.instance_variable_set("@contents",&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;@template.render(:file =&gt; template_path_for_local_rescue(exception)))&lt;br /&gt;&lt;br /&gt;    # send mail to developers&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;mail = ExceptionNotifier.create_sent(@template)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;mail.set_content_type("text/html")&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;ExceptionNotifier.deliver(mail)&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Here is my ExceptionNotifier class, just extract needed variable to be available inside my view.&lt;br /&gt;&lt;pre name="code" class="rails"&gt;&lt;br /&gt;class ExceptionNotifier &lt; ActionMailer::Base&lt;br /&gt;  &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;def sent(template)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@subject               = 'Bug Reports'&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@body["request"]       = template.request&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@body["response"]      = template.response&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@body["exception"]     = template.instance_variable_get("@exception")&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@body["rescues_path"]  = template.instance_variable_get("@rescues_path")&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@recipients = ['chamnapchhorn@gmail.com', 'ungsophy@gmail.com']&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@from       = 'noreply@gmail.com'&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@headers    = {}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;end&lt;br /&gt;&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Here is my view, the default view for exception. I just change to locate new variables only.&lt;br /&gt;&lt;pre name="code" class="html"&gt;&lt;br /&gt;&amp;lt;h1&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;%=h @exception.class.to_s %&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;% if @request.parameters['controller'] %&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;in &lt;%=h @request.parameters['controller'].humanize %&gt;Controller&lt;% if @request.parameters['action'] %&gt;#&lt;%=h @request.parameters['action'] %&gt;&lt;% end %&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;% end %&gt;&lt;br /&gt;&amp;lt;/h1&amp;gt;&lt;br /&gt;&amp;lt;pre&amp;gt;&lt;%=h @exception.clean_message %&gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;%= render :file =&gt; @rescues_path["rescues/_trace.erb"] %&gt;&lt;br /&gt;&lt;br /&gt;&lt;%= render :file =&gt; @rescues_path["rescues/_request_and_response.erb"], :locals =&gt; { :request =&gt; @request, :response =&gt; @response } %&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6761142148052793737-7544957222579683619?l=chamnapchhorn.blogspot.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/chamnap/~4/8a-xdRT120k" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/blogspot/chamnap/~3/8a-xdRT120k/sending-report-developer.html</link><author>chamnapchhorn@gmail.com (chamnap)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total><feedburner:origLink>http://chamnapchhorn.blogspot.com/2009/07/sending-report-developer.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6761142148052793737.post-2672112506476727939</guid><pubDate>Fri, 10 Jul 2009 09:55:00 +0000</pubDate><atom:updated>2009-07-25T17:42:39.274+07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">ruby on rails</category><title>Handling Exception at the Application Level in Rails</title><description>At 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.&lt;br /&gt;Basically, there are two methods (&lt;code&gt;rescue_action&lt;/code&gt; and &lt;code&gt;rescue_action_in_public&lt;/code&gt;) 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. &lt;code&gt;rescue_action&lt;/code&gt; method will be called with an exception parameter that raises inside an action method. &lt;code&gt;rescue_action_in_public method&lt;/code&gt;, however, is used for public exception handling (for requests answering false to &lt;code&gt;local_request?&lt;/code&gt;). &lt;code&gt;local_request?&lt;/code&gt; method tells which rescue_*** method to call.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://api.rubyonrails.org/classes/ActionController/Rescue.html"&gt;http://api.rubyonrails.org/classes/ActionController/Rescue.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;pre name="code" class="rails"&gt;&lt;br /&gt;class PostsController &lt; ApplicationController&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;def rescue_action_in_public(exception)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;case(exception)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;when ActiveRecord::RecordNotFound then render :file =&gt; '/bad_record'&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;when NoMethodError then render :file =&gt; '/no_method'&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else render :file =&gt; '/error'&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;end&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;end&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;pre name="code" class="rails"&gt;&lt;br /&gt;class PostsController &lt; ApplicationController&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;# Declare exception to handler methods&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;rescue_from ActiveRecord::RecordNotFound, :with =&gt; :bad_record&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;rescue_from NoMethodError, :with =&gt; :show_error&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;def bad_record; render :file =&gt; '/bad_record'; end&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;def show_error(exception); render :text =&gt; exception.message; end&lt;br /&gt;&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;a href="http://ryandaigle.com/articles/2007/9/24/what-s-new-in-edge-rails-better-exception-handling"&gt;http://ryandaigle.com/articles/2007/9/24/what-s-new-in-edge-rails-better-exception-handling&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6761142148052793737-2672112506476727939?l=chamnapchhorn.blogspot.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/chamnap/~4/KZCvB5p8kak" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/blogspot/chamnap/~3/KZCvB5p8kak/handling-exception-at-application-level.html</link><author>chamnapchhorn@gmail.com (chamnap)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://chamnapchhorn.blogspot.com/2009/07/handling-exception-at-application-level.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6761142148052793737.post-3156078894202383489</guid><pubDate>Sat, 27 Jun 2009 11:05:00 +0000</pubDate><atom:updated>2009-07-27T11:08:18.571+07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">javascript</category><title>Maintaining Javascript Pop-Up Window Communication Across Window Opener Page Loads</title><description>I 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 &lt;a href="http://www.1pixelout.net/2006/12/15/cross-window-javascript-communication-20/"&gt;1 Pixel Out&lt;/a&gt;. There is a really nick trick.&lt;br /&gt;&lt;br /&gt;In the main window:&lt;br /&gt;&lt;pre name="code" class="javascript"&gt;&lt;br /&gt;var popupWin = null;&lt;br /&gt;&lt;br /&gt;function openPopup() {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;var url = "popup.htm";&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;popupWin = open( "", "popupWin", "width=500,height=400" );&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;if( !popupWin || popupWin.closed || !popupWin.doSomething ) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;popupWin = window.open( url, "popupWin", "width=500,height=400" );&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;} else {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;popupWin.focus();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function doSomething() {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;openPopup();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;popupWin.doSomething();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;In the popup:&lt;br /&gt;&lt;pre name="code" class="javascript"&gt;&lt;br /&gt;self.focus();&lt;br /&gt;&lt;br /&gt;function doSomething() {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;alert("I'm doing something");&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.bennadel.com/blog/89-Maintaining-Javascript-Pop-Up-Window-Communication-Across-Window-Opener-Page-Loads.htm"&gt;http://www.bennadel.com/blog/89-Maintaining-Javascript-Pop-Up-Window-Communication-Across-Window-Opener-Page-Loads.htm&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.1pixelout.net/2005/04/19/cross-window-javascript-communication/"&gt;http://www.1pixelout.net/2005/04/19/cross-window-javascript-communication/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.1pixelout.net/2006/12/15/cross-window-javascript-communication-20/"&gt;http://www.1pixelout.net/2006/12/15/cross-window-javascript-communication-20/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.1pixelout.net/wp-content/downloads/popups20.zip"&gt;http://www.1pixelout.net/wp-content/downloads/popups20.zip&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6761142148052793737-3156078894202383489?l=chamnapchhorn.blogspot.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/chamnap/~4/NCR2zrEr16s" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/blogspot/chamnap/~3/NCR2zrEr16s/maintaining-javascript-pop-up-window.html</link><author>chamnapchhorn@gmail.com (chamnap)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><enclosure url="http://www.1pixelout.net/wp-content/downloads/popups20.zip" length="1969" type="application/zip" /><feedburner:origLink>http://chamnapchhorn.blogspot.com/2009/06/maintaining-javascript-pop-up-window.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6761142148052793737.post-8426930390371482210</guid><pubDate>Sat, 27 Jun 2009 07:10:00 +0000</pubDate><atom:updated>2009-07-27T11:10:14.969+07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">javascript</category><title>Cross-window Javascript communication</title><description>It 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.&lt;br /&gt;&lt;pre name="code" class="javascript"&gt;&lt;br /&gt;&amp;lt;script type="text/javascript"&amp;gt;if(top == self) { document.write(""); } else  { top.location.href = "http://www.yahoo.com"; }&amp;lt;/script&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now, let's see a quick summary on this basic communication.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;pre name="code" class="javascript"&gt;&lt;br /&gt;// Create a new popup window&lt;br /&gt;var popupWin = window.open(url, "popupWin");&lt;br /&gt;&lt;br /&gt;// To call functions defined in the popup:&lt;br /&gt;popupWin.doSomething();&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Communication from child to parent window, you need to use this way:&lt;br /&gt;&lt;pre name="code" class="javascript"&gt;&lt;br /&gt;window.opener.doSomethingOnParent();&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;pre name="code" class="rails"&gt;&lt;br /&gt;def login&lt;br /&gt;  @status = "something"&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;#view&lt;br /&gt;&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;&amp;lt;/head&amp;gt;&lt;br /&gt;&amp;lt;body onload="window.opener.handleOpenIDResponse('" + @status + "');window.close();"&amp;gt;&lt;br /&gt;&amp;lt;/body&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;That would solve the problem, and you could send any information back through your view.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6761142148052793737-8426930390371482210?l=chamnapchhorn.blogspot.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/chamnap/~4/armXt65b69s" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/blogspot/chamnap/~3/armXt65b69s/cross-window-javascript-communication.html</link><author>chamnapchhorn@gmail.com (chamnap)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://chamnapchhorn.blogspot.com/2009/06/cross-window-javascript-communication.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6761142148052793737.post-8509927370996612874</guid><pubDate>Thu, 18 Jun 2009 08:46:00 +0000</pubDate><atom:updated>2009-07-27T11:16:22.953+07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">ruby on rails</category><title>has_and_belongs_to_many or has_many :through?</title><description>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.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;has_and_belongs_to_many (habtm)&lt;/b&gt;&lt;br /&gt;habtm is the very old way since rails 1.2. It creates a link between associated models through an intermediate join table.&lt;br /&gt;&lt;pre name="code" class="rails"&gt;&lt;br /&gt;class CreateProjectsProgrammers &lt; ActiveRecord::Migration&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;def self.up&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;create_table :projects_programmers, :id =&gt; false do |t|&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;t.column :project_id, :integer, :null =&gt; false&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;t.column :programmer_id, :integer, :null =&gt; false&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;end&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;end&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;def self.down&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;drop_table :projects_programmers&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;end&lt;br /&gt;end&lt;br /&gt;class Programmer &lt; ActiveRecord::Base&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;has_and_belongs_to_many :projects       # foreign keys in the join table&lt;br /&gt;end&lt;br /&gt;class Project &lt; ActiveRecord::Base&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;has_and_belongs_to_many :programmers    # foreign keys in the join table&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;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 &lt;code&gt;push_with_attributes&lt;/code&gt; to do this. However, &lt;code&gt;push_with_attributes&lt;/code&gt; 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).&lt;br /&gt;&lt;br /&gt;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 &lt;code&gt;has_many :through&lt;/code&gt; once you need to add additional columns.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;has_many :through&lt;/b&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;When a user reads an article, we can record the fact.&lt;br /&gt;&lt;pre name="code" class="javascript"&gt;&lt;br /&gt;class Article &lt; ActiveRecord::Base&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;has_many :readings&lt;br /&gt;end&lt;br /&gt;class User &lt; ActiveRecord::Base&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;has_many :readings&lt;br /&gt;end&lt;br /&gt;class Reading &lt; ActiveRecord::Base&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;belongs_to :article&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;belongs_to :user&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;reading = Reading.new&lt;br /&gt;reading.rating = params[:rating]&lt;br /&gt;reading.read_at = Time.now&lt;br /&gt;reading.article = current_article&lt;br /&gt;reading.user = session[:user]&lt;br /&gt;reading.save&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;pre name="code" class="javascript"&gt;&lt;br /&gt;class Article &lt; ActiveRecord::Base&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;has_many :readings&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;has_many :users, :through =&gt; :readings&lt;br /&gt;end&lt;br /&gt;class Reading &lt; ActiveRecord::Base&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;belongs_to :article&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;belongs_to :user&lt;br /&gt;end&lt;br /&gt;class User &lt; ActiveRecord::Base&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;has_many :readings&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;has_many :articles, :through =&gt; :readings&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now, you could do query both direction:&lt;br /&gt;&lt;pre name="code" class="javascript"&gt;&lt;br /&gt;readers = an_article.users&lt;br /&gt;articles = a_reader.articles&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;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:&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="javascript"&gt;&lt;br /&gt;user.readings.create(:read_at =&gt; Time.now,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;:rating =&gt; params[:rating],&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;:article =&gt; Article.new)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://blog.hasmanythrough.com/2006/4/20/many-to-many-dance-off"&gt;http://blog.hasmanythrough.com/2006/4/20/many-to-many-dance-off&lt;/a&gt;&lt;br /&gt;&lt;a href="http://blog.hasmanythrough.com/2006/4/17/join-models-not-proxy-collections"&gt;http://blog.hasmanythrough.com/2006/4/17/join-models-not-proxy-collections&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6761142148052793737-8509927370996612874?l=chamnapchhorn.blogspot.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/chamnap/~4/xviTAcPEs2c" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/blogspot/chamnap/~3/xviTAcPEs2c/hasandbelongstomany-or-hasmany-through.html</link><author>chamnapchhorn@gmail.com (chamnap)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://chamnapchhorn.blogspot.com/2009/06/hasandbelongstomany-or-hasmany-through.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6761142148052793737.post-2856585702419930140</guid><pubDate>Wed, 03 Jun 2009 01:23:00 +0000</pubDate><atom:updated>2009-07-27T11:12:21.377+07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">ruby on rails</category><title>Proper use of session</title><description>Consider the following scenario, you want to store information about current user. After successful login, you might do this.&lt;br /&gt;&lt;pre name="code" class="javascript"&gt;&lt;br /&gt;user = User.authenticate(params[:user_name], params[:password])&lt;br /&gt;if user&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;session[:current_user] = user.attributes&lt;br /&gt;else&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;flash[:notice] = "Email and password do not match."&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;redirect_to :controller =&gt; "login"&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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. &lt;br /&gt;&lt;pre name="code" class="javascript"&gt;&lt;br /&gt;class ApplicationController &lt; ActionController::Base&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;before_filter :get_current_user&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;private&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;def get_current_user&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@current_user = User.find_by_id(session[:user_id])&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;end&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Here you can access @current_user everywhere in your application and solve many issues during development.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6761142148052793737-2856585702419930140?l=chamnapchhorn.blogspot.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/chamnap/~4/jcyT8Zbwd9A" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/blogspot/chamnap/~3/jcyT8Zbwd9A/proper-use-of-session.html</link><author>chamnapchhorn@gmail.com (chamnap)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://chamnapchhorn.blogspot.com/2009/06/proper-use-of-session.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6761142148052793737.post-7762041590822974093</guid><pubDate>Thu, 14 May 2009 04:03:00 +0000</pubDate><atom:updated>2009-07-27T11:15:16.358+07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">ruby on rails</category><title>Custom Rake Tasks</title><description>I 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 &lt;code&gt;db:test:prepare, rake test:functionals&lt;/code&gt;, .... 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.&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="rails"&gt;&lt;br /&gt;  task :load_test_db do&lt;br /&gt;    #load data to development&lt;br /&gt;    Rake::Task["db:fixtures:load"].invoke&lt;br /&gt;    &lt;br /&gt;    #clone development to test&lt;br /&gt;    Rake::Task["db:test:clone_structure"].invoke&lt;br /&gt;    &lt;br /&gt;    #pull data from development&lt;br /&gt;    sh "mysqldump &gt; test.sql development_ncdd_templates -u root"&lt;br /&gt;&lt;br /&gt;    sh "mysql -u root &lt;&lt; EOF&lt;br /&gt;       use test_ncdd_templates;&lt;br /&gt;       source test.sql;&lt;br /&gt;       exit&lt;br /&gt;    EOF"&lt;br /&gt;  end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;   sh "#!/bin/bash&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cd lib&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ruby to_yml.rb&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cd .."&lt;br /&gt;&lt;br /&gt;Here are some excellent sources:&lt;br /&gt;&lt;a href="http://www.railsenvy.com/2007/6/11/ruby-on-rails-rake-tutorial"&gt;http://www.railsenvy.com/2007/6/11/ruby-on-rails-rake-tutorial&lt;/a&gt;&lt;br /&gt;&lt;a href="http://railscasts.com/episodes/66-custom-rake-tasks"&gt;http://railscasts.com/episodes/66-custom-rake-tasks&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6761142148052793737-7762041590822974093?l=chamnapchhorn.blogspot.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/chamnap/~4/xZG8Z0kQ_V4" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/blogspot/chamnap/~3/xZG8Z0kQ_V4/custom-rake-tasks.html</link><author>chamnapchhorn@gmail.com (chamnap)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://chamnapchhorn.blogspot.com/2009/05/custom-rake-tasks.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6761142148052793737.post-4515566835543181045</guid><pubDate>Wed, 13 May 2009 03:59:00 +0000</pubDate><atom:updated>2009-05-13T11:08:03.262+07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">javascript</category><title>JavaScript in Object-Oriented Way</title><description>I 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.&lt;br /&gt;&lt;br /&gt;&lt;div style="width:425px;text-align:left" id="__ss_1426608"&gt;&lt;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"&gt;JavaScript in Object-Oriented Way&lt;/a&gt;&lt;object style="margin:0px" width="425" height="355"&gt;&lt;param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=javascriptinobject-orientedway-090512225827-phpapp02&amp;stripped_title=javascript-in-objectoriented-way" /&gt;&lt;param name="allowFullScreen" value="true"/&gt;&lt;param name="allowScriptAccess" value="always"/&gt;&lt;embed src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=javascriptinobject-orientedway-090512225827-phpapp02&amp;stripped_title=javascript-in-objectoriented-way" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div style="font-size:11px;font-family:tahoma,arial;height:26px;padding-top:2px;"&gt;View more &lt;a style="text-decoration:underline;" href="http://www.slideshare.net/"&gt;presentations&lt;/a&gt; from &lt;a style="text-decoration:underline;" href="http://www.slideshare.net/cchamnap"&gt;cchamnap&lt;/a&gt;.&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6761142148052793737-4515566835543181045?l=chamnapchhorn.blogspot.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/chamnap/~4/i9A3dShRbxU" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/blogspot/chamnap/~3/i9A3dShRbxU/javascript-in-object-oriented-way.html</link><author>chamnapchhorn@gmail.com (chamnap)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><enclosure url="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=javascriptinobject-orientedway-090512225827-phpapp02&amp;stripped_title=javascript-in-objectoriented-way" length="87056" type="application/x-shockwave-flash" /><feedburner:origLink>http://chamnapchhorn.blogspot.com/2009/05/javascript-in-object-oriented-way.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6761142148052793737.post-5429879078678621629</guid><pubDate>Thu, 07 May 2009 04:41:00 +0000</pubDate><atom:updated>2009-06-14T15:50:38.107+07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">javascript</category><title>JavaScript Mixins</title><description>I have just reviewed JavaScript Design Patterns, and I think it is good to mention this.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;var Mixin = function() {};&lt;br /&gt;Mixin.prototype = {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;serialize: function() {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var output = [];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for(key in this) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;output.push(key + ': ' + this[key]);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return output.join(', ');&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;};&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;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:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;augment(Author, Mixin);&lt;br /&gt;&lt;br /&gt;var author = new Author('Ross Harmes', ['JavaScript Design Patterns']);&lt;br /&gt;var serializedString = author.serialize();&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;This can be thought of as a way to implement multiple inheritance in JavaScript.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;/* Augment function. */&lt;br /&gt;function augment(receivingClass, givingClass) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;for(methodName in givingClass.prototype) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if(!receivingClass.prototype[methodName]) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;receivingClass.prototype[methodName] = givingClass.prototype[methodName];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;A more robust augment allows copying one or two of them over to another class.&lt;br /&gt;&lt;code&gt;&lt;br /&gt;/* Augment function, improved. */&lt;br /&gt;function augment(receivingClass, givingClass) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;if(arguments[2]) { // Only give certain methods.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for(var i = 2, len = arguments.length; i &lt; len; i++) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;receivingClass.prototype[arguments[i]] = givingClass.prototype[arguments[i]];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;else { // Give all methods.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for(methodName in givingClass.prototype) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if(!receivingClass.prototype[methodName]) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;receivingClass.prototype[methodName] = givingClass.prototype[methodName];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;You can now write augment(Author, Mixin, 'serialize'); to only augment Author with the single serialize method.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;var Author = function(name, books) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;this.name = name || "";&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;this.books = books || [];&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;Mixin.apply(this);&lt;br /&gt;};&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Often it makes more sense to augment a class with a few methods than it does to make&lt;br /&gt;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).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6761142148052793737-5429879078678621629?l=chamnapchhorn.blogspot.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/chamnap/~4/8DSAEbZeL1k" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/blogspot/chamnap/~3/8DSAEbZeL1k/javascript-mixins.html</link><author>chamnapchhorn@gmail.com (chamnap)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://chamnapchhorn.blogspot.com/2009/05/javascript-mixins.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6761142148052793737.post-8560760159261924</guid><pubDate>Thu, 07 May 2009 04:40:00 +0000</pubDate><atom:updated>2009-11-09T08:28:09.413+07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">javascript</category><title>Prototypal Inheritance vs. Classical Inheritance</title><description>While 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:&lt;br /&gt;&lt;br /&gt;The classical approach to creating an object is to (a) define the structure of the object, using&lt;br /&gt;a class declaration, and (b) instantiate that class to create a new object. Objects created in this&lt;br /&gt;manner have their own copies of all instance attributes, plus a link to the single copy of each&lt;br /&gt;of the instance methods.&lt;br /&gt;&lt;br /&gt;In prototypal inheritance, instead of defining the structure through a class, you simply&lt;br /&gt;create an object. This object then gets reused by new objects, thanks to the way that prototype&lt;br /&gt;chain lookups work. It is called the &lt;span style="font-style:italic;"&gt;prototype object&lt;/span&gt; because it provides a prototype for what the other objects should look like.&lt;br /&gt;&lt;br /&gt;Instead of using a constructor function named Person to define the class structure, Person&lt;br /&gt;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&lt;br /&gt;default values. &lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;/* Person Prototype Object. */&lt;br /&gt;var Person = {&lt;br /&gt;   name: 'default name',&lt;br /&gt;   getName: function() {&lt;br /&gt;     return this.name;&lt;br /&gt;   }&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;var reader = clone(Person);&lt;br /&gt;alert(reader.getName()); // This will output 'default name'.&lt;br /&gt;reader.name = 'John Smith';&lt;br /&gt;alert(reader.getName()); // This will now output 'John Smith'.&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;To create a new Person-like object, use the clone function. This provides an empty object with&lt;br /&gt;the prototype attribute set to the prototype object. This means that if any method or attribute&lt;br /&gt;lookup on this object fails, that lookup will instead look to the prototype object.&lt;br /&gt;To create Author, you make a clone.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;/* Author Prototype Object. */&lt;br /&gt;var Author = clone(Person);&lt;br /&gt;Author.books = []; // Default value.&lt;br /&gt;Author.getBooks = function() {&lt;br /&gt;  return this.books;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;var author0 = clone(Author);&lt;br /&gt;author0.name = 'Dustin Diaz';&lt;br /&gt;author0.books = ['JavaScript Design Patterns'];&lt;br /&gt;var author1 = clone(Author);&lt;br /&gt;author1.name = 'Ross Harmes';&lt;br /&gt;author1.books = ['JavaScript Design Patterns'];&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;code&gt;&lt;br /&gt;/* Clone function. */&lt;br /&gt;function clone(object) {&lt;br /&gt;    function F() {}&lt;br /&gt;    F.prototype = object;&lt;br /&gt;    return new F;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;var authorClone = clone(Author);&lt;br /&gt;alert(authorClone.name); // Linked to the primative Person.name, which is the&lt;br /&gt;                         // string 'default name'.&lt;br /&gt;authorClone.name = 'new name'; // A new primative is created and added to the&lt;br /&gt;                               // authorClone object itself.&lt;br /&gt;alert(authorClone.name); // Now linked to the primative authorClone.name, which&lt;br /&gt;                         // is the string 'new name'.&lt;br /&gt;authorClone.books.push('new book'); // authorClone.books is linked to the array&lt;br /&gt;                                    // Author.books. We just modified the&lt;br /&gt;                                    // prototype object's default value, and all&lt;br /&gt;                                    // other objects that link to it will now&lt;br /&gt;                                    // have a new default value there.&lt;br /&gt;authorClone.books = []; // A new array is created and added to the authorClone&lt;br /&gt;                        // object itself.&lt;br /&gt;authorClone.books.push('new book'); // We are now modifying that new array.&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Classical inheritance is well understood, both in JavaScript and the programmer commu-&lt;br /&gt;nity in general. Almost all object-oriented code written in JavaScript uses this paradigm. If you&lt;br /&gt;are creating an API for widespread use, or if there is the possibility that other programmers not&lt;br /&gt;familiar with prototypal inheritance will be working on your code, it is best to go with classical.&lt;br /&gt;&lt;br /&gt;JavaScript is the only popular, widely used language that uses prototypal inheritance, so odds&lt;br /&gt;are most people will never have used it before. It can also be confusing to have an object with&lt;br /&gt;links back to its prototype object. Programmers who don’t fully understand prototypal inheri-&lt;br /&gt;tance will think of this as some sort of reverse inheritance, where the parent inherits from its&lt;br /&gt;children. Even though this isn’t the case, it can still be a very confusing topic. But since this&lt;br /&gt;form of classical inheritance is only imitating true class-based inheritance, advanced JavaScript&lt;br /&gt;programmers need to understand how prototypal inheritance truly works at some point any-&lt;br /&gt;way. Some would argue that hiding this fact does more harm than good.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6761142148052793737-8560760159261924?l=chamnapchhorn.blogspot.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/chamnap/~4/4OrxwJxVsKE" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/blogspot/chamnap/~3/4OrxwJxVsKE/prototypal-inheritance-vs-classical.html</link><author>chamnapchhorn@gmail.com (chamnap)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://chamnapchhorn.blogspot.com/2009/05/prototypal-inheritance-vs-classical.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6761142148052793737.post-3190805459986718748</guid><pubDate>Wed, 29 Apr 2009 01:33:00 +0000</pubDate><atom:updated>2009-05-23T09:57:06.203+07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">ruby on rails</category><title>ActiveRecord::Dirty</title><description>Another powerful feature of ActiveRecord is dirty objects. This module tracks unsaved attribute changes. This feature is available probably since &lt;a href="http://ryandaigle.com/articles/2008/3/31/what-s-new-in-edge-rails-dirty-objects"&gt;March, 2008&lt;/a&gt;. See examples below:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;A newly instantiated object is unchanged:&lt;/b&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;  person = Person.find_by_name('uncle bob')&lt;br /&gt;  person.changed?       # =&gt; false&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;b&gt;Change the name:&lt;/b&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;  person.name = 'Bob'&lt;br /&gt;  person.changed?       # =&gt; true&lt;br /&gt;  person.name_changed?  # =&gt; true&lt;br /&gt;  person.name_was       # =&gt; 'uncle bob'&lt;br /&gt;  person.name_change    # =&gt; ['uncle bob', 'Bob']&lt;br /&gt;  person.name = 'Bill'&lt;br /&gt;  person.name_change    # =&gt; ['uncle bob', 'Bill']&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;b&gt;Save the changes:&lt;/b&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;  person.save&lt;br /&gt;  person.changed?       # =&gt; false&lt;br /&gt;  person.name_changed?  # =&gt; false&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;b&gt;Assigning the same value leaves the attribute unchanged:&lt;/b&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;  person.name = 'Bill'&lt;br /&gt;  person.name_changed?  # =&gt; false&lt;br /&gt;  person.name_change    # =&gt; nil&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;b&gt;Which attributes have changed?&lt;/b&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;  person.name = 'bob'&lt;br /&gt;  person.changed        # =&gt; ['name']&lt;br /&gt;  person.changes        # =&gt; { 'name' =&gt; ['Bill', 'bob'] }&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;b&gt;Before modifying an attribute in-place:&lt;/b&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;  person.name_will_change!&lt;br /&gt;  person.name &lt;&lt; 'by'&lt;br /&gt;  person.name_change    # =&gt; ['uncle bob', 'uncle bobby']&lt;br /&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6761142148052793737-3190805459986718748?l=chamnapchhorn.blogspot.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/chamnap/~4/EzShHrQeQ3k" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/blogspot/chamnap/~3/EzShHrQeQ3k/activerecorddirty.html</link><author>chamnapchhorn@gmail.com (chamnap)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://chamnapchhorn.blogspot.com/2009/04/activerecorddirty.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6761142148052793737.post-5671066014858289713</guid><pubDate>Tue, 28 Apr 2009 05:53:00 +0000</pubDate><atom:updated>2009-04-28T14:34:04.078+07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">ruby on rails</category><title>My Restful Rails Presentation</title><description>Last month, I did a presentation to my team about Restful Rails. I just uploaded to &lt;a href="http://www.slideshare.net/cchamnap/rest-in-rails"&gt;http://www.slideshare.net/cchamnap/rest-in-rails&lt;/a&gt;. It might be useful for newbie rails developer.&lt;br /&gt;&lt;div style="width:425px;text-align:left" id="__ss_1355315"&gt;&lt;a style="font:14px Helvetica,Arial,Sans-serif;display:block;margin:12px 0 3px 0;text-decoration:underline;" href="http://www.slideshare.net/cchamnap/rest-in-rails?type=powerpoint" title="Rest in Rails"&gt;Rest in Rails&lt;/a&gt;&lt;object style="margin:0px" width="425" height="355"&gt;&lt;param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=restinrails-090428004646-phpapp01&amp;stripped_title=rest-in-rails" /&gt;&lt;param name="allowFullScreen" value="true"/&gt;&lt;param name="allowScriptAccess" value="always"/&gt;&lt;embed src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=restinrails-090428004646-phpapp01&amp;stripped_title=rest-in-rails" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div style="font-size:11px;font-family:tahoma,arial;height:26px;padding-top:2px;"&gt;View more &lt;a style="text-decoration:underline;" href="http://www.slideshare.net/"&gt;presentations&lt;/a&gt; from &lt;a style="text-decoration:underline;" href="http://www.slideshare.net/cchamnap"&gt;cchamnap&lt;/a&gt;.&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6761142148052793737-5671066014858289713?l=chamnapchhorn.blogspot.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/chamnap/~4/OKLkFZ1IJh8" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/blogspot/chamnap/~3/OKLkFZ1IJh8/my-restful-rails-presentation.html</link><author>chamnapchhorn@gmail.com (chamnap)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total><enclosure url="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=restinrails-090428004646-phpapp01&amp;stripped_title=rest-in-rails" length="87056" type="application/x-shockwave-flash" /><feedburner:origLink>http://chamnapchhorn.blogspot.com/2009/04/my-restful-rails-presentation.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6761142148052793737.post-3907863284119657374</guid><pubDate>Sat, 11 Apr 2009 07:34:00 +0000</pubDate><atom:updated>2009-04-24T08:50:15.490+07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">javascript</category><category domain="http://www.blogger.com/atom/ns#">ruby on rails</category><category domain="http://www.blogger.com/atom/ns#">gears</category><title>Upload in Gears 0.5</title><description>Uploading in Gears is pretty easy since its HttpRequest object supports uploading imagery data. If you want that uploaded file could serve locally (in offline mode), you need to use LocalServer API. Moreover, it is feasible to upload in chunk for large files as well. It involves the use of Blob API as well as good handling on server side. I found two links that is able to achieve this: &lt;br /&gt;&lt;a href="http://snippets.dzone.com/posts/show/6175"&gt;http://snippets.dzone.com/posts/show/6175&lt;/a&gt;&lt;br /&gt;&lt;a href="http://uploadmovietool.appspot.com/"&gt;http://uploadmovietool.appspot.com/&lt;/a&gt;. However, I just show a simple implementation both server side script (Rails) and client side script (JavaScript).&lt;br /&gt;&lt;br /&gt;Let's start from select a file to upload with the help of &lt;a href="http://code.google.com/apis/gears/api_desktop.html"&gt;Desktop API&lt;/a&gt;, openFiles(). You need to pass the callback, and some option attributes like filter and singleFile. After user has selected a file, the callback will be invoked with one parameter that is a File object of that file. Notice that, this file object has two properties: name and blob. Thus, you can use LocalServer API to capture this file by calling captureBlob() and passing blob object, a unique url for accessing this file, and a content type. If you don't provide a content-type, the browser doesn't know how to view this file when it has intercepted by LocalServer. Usually, it will launch a download of this file. Oop! Don't forget to create a localserver object. I assume you understand gears api good enough.&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;var desktop = google.gears.factory.create('beta.desktop');&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;desktop.openFiles(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;function(files) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var file = files[0];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if(!file) return;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//capture file for serving locally&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;fileName = file.name;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;blobStore.captureBlob(file.blob, fileName, "image/JPEG");&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;},&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{ filter: ['.jpg'], singleFile: true }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;);&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Next, you need to create a HttpRequest object. Then, you do a post to your server side script. You can set some request headers like: 'Content-Disposition', 'Content-Type', and 'Content-Range'. Gears provides an event handler called onprogress. When this event is triggered, you would get ProgressEvent object. This object has 3 properties: total, loaded, and lengthComputable. These 3 properties are useful in updating UI. Last, you need to pass the blob object to send() of HttpRequest object. You can do this by calling getAsBlob() and passing the url that previously called by captureBlob().&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;function upload() {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var xhrUpload = google.gears.factory.create("beta.httprequest");&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;xhrUpload.open("POST", '/upload/files');&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;xhrUpload.setRequestHeader('Content-Disposition', 'attachment; filename="' + fileName + '"');&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;xhrUpload.setRequestHeader('Content-Type', 'image/JPEG');&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;xhrUpload.setRequestHeader('Content-Range', 'bytes ' + file.blob.length);&lt;br /&gt;&lt;br /&gt;    //Update UI&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;xhrUpload.upload.onprogress = function(progressEvent) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;document.getElementById("status").innerHTML = ((progressEvent.loaded/progressEvent.total)*100).toFixed(0) + "%";&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;};&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;xhrUpload.onreadystatechange = function() {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;switch(xhrUpload.readyState) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;case 4: //complete&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;document.getElementById("status").innerHTML = "done";&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;};&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;xhrUpload.send(blobStore.getAsBlob(fileName));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;In Rails, it is quite easy to handle actually. You just need to extract file name of request header 'HTTP_CONTENT_DISPOSITION'. Then, you perform an OS check to write a file of the whole request body. It is a method called raw_post of request object.&lt;br /&gt;&lt;code&gt;&lt;br /&gt;class UploadController &lt; ApplicationController&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;def files&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;path = request.env['HTTP_CONTENT_DISPOSITION'][/^attachment\; filename="([^\"]+)"$/, 1]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if RUBY_PLATFORM.index("win")&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;File.open("public/images/#{path}", "wb") { |f| f.write(request.raw_post) }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;File.open("public/images/#{path}", "w") { |f| f.write(request.raw_post) }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;end&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;end&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6761142148052793737-3907863284119657374?l=chamnapchhorn.blogspot.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/chamnap/~4/bG3c-0hPcDs" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/blogspot/chamnap/~3/bG3c-0hPcDs/upload-in-gears-05.html</link><author>chamnapchhorn@gmail.com (chamnap)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://chamnapchhorn.blogspot.com/2009/04/upload-in-gears-05.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6761142148052793737.post-1955150977911685380</guid><pubDate>Thu, 02 Apr 2009 09:03:00 +0000</pubDate><atom:updated>2009-04-26T10:28:05.288+07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">ruby on rails</category><title>JSON Handling Request in Rails</title><description>I have messed around for almost a day today just to find how to convert from json object to ruby object when posting a REST web service. However, I have known quite well a couple more features of Rails in depth like Migration, Testing, RSpec, ActiveResource,....&lt;br /&gt;&lt;br /&gt;There are three data format we can post through AJAX (from JavaScript): serialization, and xml. &lt;b&gt;Serialization&lt;/b&gt; is the process that formats a set of data so that the server can easily read&lt;br /&gt;it from javascript object or html form.&lt;br /&gt;&lt;code&gt;&lt;br /&gt;// Serialized form&lt;br /&gt;name=Chhorn&amp;last=Chamnap&amp;city=Cambridge&amp;zip=02140&lt;br /&gt;&lt;/code&gt;&lt;code&gt;&lt;br /&gt;//XML&lt;br /&gt;&amp;lt;name&amp;gt;Chhorn&amp;lt;/name&amp;gt;&lt;br /&gt;&amp;lt;last&amp;gt;Chamnap&amp;lt;/last&amp;gt;&lt;br /&gt;&amp;lt;city&amp;gt;Cambridge&amp;lt;/city&amp;gt;&lt;br /&gt;&amp;lt;zip&amp;gt;02140&amp;lt;/zip&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Rails automatically recognizes these format very well. In your controller, you can access from params[:name], params[:last],.... However, you would face difficulties when you do a post request with json object. In your params variable would be {"{\"first_name\":\"chamnap&lt;br /&gt;\",\"last_name\":\"chhorn\"}"=&gt;nil. Therefore, you must parse this string to ruby object. There are two possible solutions. First solution, I got from a &lt;a href="http://groups.google.com/group/rubyonrails-talk/t/e9758844a4769e29"&gt;discussion&lt;/a&gt;.&lt;br /&gt;&lt;code&gt;&lt;br /&gt;irb&gt; require 'rubygems'&lt;br /&gt;=&gt; true&lt;br /&gt;irb&gt; gem 'json'&lt;br /&gt;=&gt; true&lt;br /&gt;irb&gt; require 'json'&lt;br /&gt;=&gt; true&lt;br /&gt;irb&gt; raw = "{\"first_name\":\"chamnap\",\"last_name\":\"chhorn\"}"&lt;br /&gt;=&gt; "{\"first_name\":\"chamnap\",\"last_name\":\"chhorn\"}"&lt;br /&gt;irb&gt; puts raw&lt;br /&gt;{"first_name":"chamnap","last_name":"chhorn"}&lt;br /&gt;=&gt; nil&lt;br /&gt;irb&gt; JSON(raw)&lt;br /&gt;=&gt; {"first_name"=&gt;"chamnap", "last_name"=&gt;"chhorn"}&lt;br /&gt;irb&gt; cooked = JSON.parse(raw)&lt;br /&gt;=&gt; {"first_name"=&gt;"chamnap", "last_name"=&gt;"chhorn"}&lt;br /&gt;irb&gt; raw&lt;br /&gt;=&gt; "{\"first_name\":\"chamnap\",\"last_name\":\"chhorn\"}"&lt;br /&gt;irb&gt; cooked&lt;br /&gt;=&gt; {"first_name"=&gt;"chamnap", "last_name"=&gt;"chhorn"}&lt;br /&gt;irb&gt; raw.class&lt;br /&gt;=&gt; String&lt;br /&gt;irb&gt; cooked.class&lt;br /&gt;=&gt; Hash&lt;br /&gt;irb&gt; cooked["first_name"]&lt;br /&gt;=&gt; "chamnap"&lt;br /&gt;irb&gt; cooked[:first_name]&lt;br /&gt;=&gt; nil&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Secondly, I found by chance from my book by using &lt;code&gt;ActiveSupport::JSON.decode()&lt;/code&gt; method.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6761142148052793737-1955150977911685380?l=chamnapchhorn.blogspot.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/chamnap/~4/f5al0LTdH9M" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/blogspot/chamnap/~3/f5al0LTdH9M/json-handling-request-in-rails.html</link><author>chamnapchhorn@gmail.com (chamnap)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://chamnapchhorn.blogspot.com/2009/04/json-handling-request-in-rails.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6761142148052793737.post-9210570323714499421</guid><pubDate>Fri, 27 Mar 2009 04:03:00 +0000</pubDate><atom:updated>2009-03-27T12:56:27.993+07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">javascript</category><category domain="http://www.blogger.com/atom/ns#">google maps api</category><title>Geocoding on Google Maps</title><description>Geocoding is the process of converting from address into geographic coordinates which you then can position on the map. It can be accessed directly via an HTTP request or by using a GClientGeocoder object. It is worthwhile to mention two methods of GClientGeocoder object.&lt;br /&gt;&lt;br /&gt;1. &lt;code&gt;GClientGeocoder.getLatLng()&lt;/code&gt;: this method allows you to get location of a specific location by querying google geoserver. You need to pass two arguments, address and a callback function. That callback function is invoked with one parameter, a GLatLng object of that location, when there is a reply from this service. See example &lt;a href="http://code.google.com/apis/maps/documentation/examples/geocoding-simple.html"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;2. &lt;code&gt;GClientGeocoder.getLocations()&lt;/code&gt;: this method allows you more ability than the previous one by returning a JSON object consisting of the following information: Status (request, code), Placemark (address, AddressDetails, Accuracy, Point, coordinates,...). Moreover, it supports both standard and reverse geocoding. If you pass this method a GLatLng object instead of a String address, the geocoder will perform a reverse lookup and return a structured JSON object of the closest addressable location. See examples:&lt;br /&gt;&lt;a href="http://code.google.com/apis/maps/documentation/examples/geocoding-extraction.html"&gt;geocoding-extraction&lt;/a&gt;&lt;br /&gt;&lt;a href="http://code.google.com/apis/maps/documentation/examples/geocoding-reverse.html"&gt;geocoding-reverse&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Recently, I realized Google has added another information of data returned by this method, ExtendedData which consists of north, east, south, and west of that area. This is quite useful when positioning location on the map with appropriate zoom level. All you have to do, construct a GLatLngBounds object with these data, then call getBoundsZoomLevel() by passing this GLatLngBounds object to determine proper zoom level that fits map view port.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;var getLocation = function(address) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;var geoCoder = new GClientGeocoder();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;geoCoder.getLocations(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;address,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;function(location){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;document.getElementById('txtAddressId').value = address;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//if this address is found&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if(location.Status.code == 200) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var placeMark = location.Placemark[0];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var latLngBox = placeMark.ExtendedData.LatLonBox;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//default zoom level is 7&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var latlng, zoom = 7;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if(latLngBox) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//determine zoom level if possible&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;b&gt;var latLngBound = new GLatLngBounds(new GLatLng(latLngBox.south, latLngBox.west), new GLatLng(latLngBox.north, latLngBox.east));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;zoom = map.getBoundsZoomLevel(latLngBound);&lt;/b&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;latlng = new GLatLng(placeMark.Point.coordinates[1], placeMark.Point.coordinates[0]);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;map.setCenter(latlng, zoom);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} else {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;alert('Address is not found.');&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;);&lt;br /&gt;}&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6761142148052793737-9210570323714499421?l=chamnapchhorn.blogspot.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/chamnap/~4/c_fW1cKU3Y0" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/blogspot/chamnap/~3/c_fW1cKU3Y0/geocoding-on-google-maps.html</link><author>chamnapchhorn@gmail.com (chamnap)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://chamnapchhorn.blogspot.com/2009/03/geocoding-on-google-maps.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6761142148052793737.post-2382765381030186366</guid><pubDate>Thu, 26 Mar 2009 01:21:00 +0000</pubDate><atom:updated>2009-03-26T10:57:56.869+07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">javascript</category><category domain="http://www.blogger.com/atom/ns#">google maps api</category><title>Load Google Maps Dynamically</title><description>Previously, I posted how to load google maps script dynamically for performance reasons. However, when callback function is get called, we could not pass any parameters to this callback, because the callback we passed is the name specified in string. &lt;br /&gt;&lt;br /&gt;There is another way if you use multiple APIs from Google, Google AJAX APIs. This framework allows you to load one API key for all supported Google AJAX APIs (including Google Maps) and also provides a common namespace for each API, allowing different Google APIs to operate together. If you decide not to use the Google AJAX API framework, you can continue to use the existing namespace. There is a method from this framework called load() with 2 parameters: moduleName, and callback function. Hence, I could use the same way to load google map except the url to load and call load(). &lt;a href="http://code.google.com/apis/ajax/documentation/#Dynamic"&gt;Here&lt;/a&gt; is from google documentation.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;function mapsLoaded() {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;var map = new google.maps.Map2(document.getElementById("map"));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;map.setCenter(new google.maps.LatLng(37.4419, -122.1419), 13);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function loadMaps() {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;google.load("maps", "2", {"callback" : mapsLoaded});&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function initLoader() {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;var script = document.createElement("script");&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;script.src = "http://www.google.com/jsapi?key=ABCDEFG&amp;callback=loadMaps";&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;script.type = "text/javascript";&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;document.getElementsByTagName("head")[0].appendChild(script);&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;To solve the previous problem, you could actually add the script tag of Google AJAX APIs, which describes more precisely at &lt;a href="http://code.google.com/apis/ajax/documentation/"&gt;http://code.google.com/apis/ajax/documentation/&lt;/a&gt;. The Google AJAX APIs &amp;lt;script&amp;gt; tag loads a single method, while google.load() which loads individual AJAX APIs. With this method, you can load any specific Google API on demand.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;function mapsLoaded() {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;var map = new google.maps.Map2(document.getElementById("map"));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;map.setCenter(new google.maps.LatLng(37.4419, -122.1419), 13);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function loadMaps() {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;google.load("maps", "2", {"callback" : mapsLoaded});&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6761142148052793737-2382765381030186366?l=chamnapchhorn.blogspot.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/chamnap/~4/bKM4AqacWqo" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/blogspot/chamnap/~3/bKM4AqacWqo/load-google-maps-dynamically.html</link><author>chamnapchhorn@gmail.com (chamnap)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://chamnapchhorn.blogspot.com/2009/03/load-google-maps-dynamically.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6761142148052793737.post-893409686127858482</guid><pubDate>Sat, 14 Mar 2009 02:43:00 +0000</pubDate><atom:updated>2009-03-14T10:18:40.194+07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">mysql</category><title>MySQL Stored Function</title><description>I have not touched any database code for about 1 year, and I have tried to help my friend with CREATE FUNCTION syntax. I have spent a couple hours with it in phpMyAdmin; however, I reviewed it very well which makes me much more clearer. Have a look the following code:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;CREATE FUNCTION myFunction()&lt;br /&gt;RETURNS int(11)&lt;br /&gt;BEGIN&lt;br /&gt;RETURN 1;&lt;br /&gt;END;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;There is a problem with the above code because it doesn't use any DELIMITER statements at all. I found this solution on &lt;a href="http://forums.mysql.com/read.php?98,212863,212877#msg-212877"&gt;http://forums.mysql.com/read.php?98,212863,212877#msg-212877&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Well, I have tested that again on phpMyAdmin, but it still doesn't work. I found some people said don't use phpMyAdmin to run this type of statement. Hence, I tried MySQL Query Browser, it works well.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;DELIMITER $$&lt;br /&gt;&lt;br /&gt;CREATE FUNCTION myFunction() RETURNS int(11)&lt;br /&gt;BEGIN&lt;br /&gt;RETURN 1;&lt;br /&gt;END $$&lt;br /&gt;&lt;br /&gt;DELIMITER ;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Have a look on full syntax of &lt;a href="http://dev.mysql.com/doc/refman/5.0/en/create-procedure.html"&gt;create stored routine&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6761142148052793737-893409686127858482?l=chamnapchhorn.blogspot.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/chamnap/~4/pW6PIiT0u0g" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/blogspot/chamnap/~3/pW6PIiT0u0g/mysql-stored-function_14.html</link><author>chamnapchhorn@gmail.com (chamnap)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://chamnapchhorn.blogspot.com/2009/03/mysql-stored-function_14.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6761142148052793737.post-8309342522102796462</guid><pubDate>Tue, 27 Jan 2009 03:48:00 +0000</pubDate><atom:updated>2009-01-27T11:03:38.674+07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">javascript</category><category domain="http://www.blogger.com/atom/ns#">yui</category><title>SplitButton and MenuButton</title><description>Probably, somebody also experiences difficulties with dealing with SplitButton and MenuButton when you add new items, select an item, replace it with new items. To deal with those items, you need to call getMenu().&lt;br /&gt;&lt;br /&gt;1. To clear existing items, call clearContent() of getMenu()&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;split.getMenu().clearContent();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;split.set("label", "Choose One");&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;2. To add item(s), call addItem() or addItems(). Remember each item has three properties: "text", "value", and "onclick". After calling this method, you need to call render by passing the container of this button, otherwise it won't appear on the browser. &lt;br /&gt;&lt;code&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;split.getMenu().addItems(splitData);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;split.getMenu().render(split.get('container'));&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;3. To replace with new data, just combine two previous snippet codes&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;split.getMenu().clearContent();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;split.set("label", "Choose One");&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;split.getMenu().addItems(splitData);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;split.getMenu().render(split.get('container'));&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;4. To enable selection when clicking on each item, each item must have onclick property with an object literal as shown below:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;splitData = {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;fn: function(type, args, item) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;split_group.set("label", item.cfg.getProperty("text")); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6761142148052793737-8309342522102796462?l=chamnapchhorn.blogspot.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/chamnap/~4/KtuaMQ84NSo" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/blogspot/chamnap/~3/KtuaMQ84NSo/splitbutton-and-menubutton.html</link><author>chamnapchhorn@gmail.com (chamnap)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://chamnapchhorn.blogspot.com/2009/01/splitbutton-and-menubutton.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6761142148052793737.post-3142941732244556670</guid><pubDate>Tue, 27 Jan 2009 02:40:00 +0000</pubDate><atom:updated>2009-01-27T10:46:16.201+07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">javascript</category><category domain="http://www.blogger.com/atom/ns#">gears</category><title>Handle DateTime field in Gears</title><description>SQLite in Gears supports DATETIME data type, but it works differently from JavaScript context. SQLite only support the following formats as shown on &lt;a href="http://www.somacon.com/p370.php"&gt;SQLite Date and Time Functions&lt;/a&gt;. If you provide invalid format, SQLite will not give an error, but the function call (&lt;a href="http://www.somacon.com/p370.php"&gt;SQLite DateTime function&lt;/a&gt;) will return null, or record could not be inserted/updated. There are two ways to handle this situation.&lt;br /&gt;&lt;br /&gt;1. If you don't use ORM JavaScript library such JazzRecord or JStORM, you could make this field an Integer field and call getTime() of JavaScript Date object to store. For displaying data back, you can still sort by ascending/descending order. Pass value that get from getTime() to a constructor of Date object to convert a Date object.&lt;br /&gt;&lt;code&gt;&lt;br /&gt;var db = google.gears.factory.create('beta.database');&lt;br /&gt;db.open('database-test');&lt;br /&gt;db.execute('create table if not exists Test (Phrase text, Timestamp int)');&lt;br /&gt;//store in db&lt;br /&gt;db.execute('insert into Test values (?, ?)', ['Monkey!', new Date().getTime()]);&lt;br /&gt;var rs = db.execute('select * from Test order by Timestamp desc');&lt;br /&gt;&lt;br /&gt;while (rs.isValidRow()) {&lt;br /&gt;  //convert to date object&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;var date = new Date(rs.field(1));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;alert(rs.field(0) + '@' + date.getDate() + "/" + (date.getMonth()+1) + "/" + date.getFullYear());&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;rs.next();&lt;br /&gt;}&lt;br /&gt;rs.close();&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;One exception with this is that you can use SQLite DateTime functions when querying back because the format you store is not recognized by SQLite. You have to loop through in JavaScript and an if statement.&lt;br /&gt;&lt;br /&gt;2. This way is preferable because it supports full &lt;a href="http://www.somacon.com/p370.php"&gt;SQLite Date and Time Functions&lt;/a&gt;, but it needs some helper method to transform format between SQLite and JavaScript back and forth.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;var Util = {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;fromJSDateToSQLiteDate: function(date) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var toTwoCharacters = function(number) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return (number.toString().length == 2) ? number.toString() : '0' + number.toString();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;};&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var strYear = date.getFullYear();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var strMonth = toTwoCharacters(date.getMonth() + 1);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var strDate = toTwoCharacters(date.getDate());&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var strHour = toTwoCharacters(date.getHours());&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var strMinute = toTwoCharacters(date.getMinutes());&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var strSecond = toTwoCharacters(date.getSeconds());&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return strYear + '-' + strMonth + '-' + strDate + ' ' + strHour + ':' + strMinute + ':' + strSecond;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;},&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;fromSQLiteDateToJSDate: function(strDateTime) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var strDate = strDateTime.split(' ')[0];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var strTime = strDateTime.split(' ')[1];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var arrDate = strDate.split('-');&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var arrTime = strTime.split(':');&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return new Date(arrDate[0], arrDate[1]-1, arrDate[2], arrTime[0], arrTime[1], arrTime[2]);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;};&lt;br /&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6761142148052793737-3142941732244556670?l=chamnapchhorn.blogspot.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/chamnap/~4/Hf9gN2jMhGw" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/blogspot/chamnap/~3/Hf9gN2jMhGw/handle-datetime-field-in-gears.html</link><author>chamnapchhorn@gmail.com (chamnap)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://chamnapchhorn.blogspot.com/2009/01/handle-datetime-field-in-gears.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6761142148052793737.post-528205740551455819</guid><pubDate>Fri, 23 Jan 2009 09:33:00 +0000</pubDate><atom:updated>2009-01-23T16:53:48.771+07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">javascript</category><category domain="http://www.blogger.com/atom/ns#">yui</category><title>Refresh DataSource of DataTable</title><description>I have been using YUI as a UI framework for my projects recently. I found the documentation of YUI is very bad since it just tells that you do this, you will get this. It doesn't tell why I need to do this, and it still misses some common examples. Most often, I need to check what are methods and properties do this object have.&lt;br /&gt;&lt;br /&gt;In order to reset new data when your data have been updated by somewhere, you need to call reset() from getRecordSet() of datatable object. Then, call setRecords() by passing your new data. If you have paginator, you also have to update it by calling setPage() to its current page and reset the total number of record.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt; dataTable.getRecordSet().reset();&lt;br /&gt; dataTable.getRecordSet().setRecords(newData);&lt;br /&gt; dataTable.refreshView();&lt;br /&gt;  &lt;br /&gt; //refresh paginator&lt;br /&gt; dataTable.get("paginator").setPage(dataTable.get("paginator").getCurrentPage());&lt;br /&gt; dataTable.get("paginator").set("totalRecords", dataTable.getRecordSet().getLength());&lt;br /&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6761142148052793737-528205740551455819?l=chamnapchhorn.blogspot.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/chamnap/~4/SLGu3lkvQ_E" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/blogspot/chamnap/~3/SLGu3lkvQ_E/refresh-datasource-of-datatable.html</link><author>chamnapchhorn@gmail.com (chamnap)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://chamnapchhorn.blogspot.com/2009/01/refresh-datasource-of-datatable.html</feedburner:origLink></item><language>en-us</language></channel></rss>
