Blog
A practice that I've started doing more of in my Rails application has been using a helper to generate javascript to remove duplication and magic numbers or strings. Primarily the only time I've generated javascript is when I needed to generate the url for an Ajax request or something similar using the url_for{:controller=>'foo', :action=>'bar'}. In the past, most of my javascript was placed in a static javascript file in the javascript library. One of the justifications for this of course is to allow the browser to cache the javascript file. In our example, perhaps we want to use javascript to disable or maybe display completely different form or other html elements based on a users selection from a drop down. In our controller, we may have different logic also based on the selected value from the drop down. For example, maybe we want to disable validation if the user selected a draft or some pre-approval option, or do additional business logic on others. You could write the javascript function using the selected index or value in application.js or other javascript file.
controller:def edit @options = [['Draft', 1],['Pre-Approve',2],['Final Submission',3]] end def handle_status if params[:status] == 1 # ignore validation, etc. elsif params[:status] == 2 # some other business logic elsif params[:status] == 3 # other business logic, validate and save end end------------------------ edit.rhtml:<% form_tag :action=>'handle_status' do%> <%= select_tag 'status', options_for_select(@options), {:onchange=>'handleOption'}-%> <% end %>------------------------ application.js:function handleOption() { var selected = $('status').id; switch (selected) { case 1: Element.show('stuff_for_draft'); Element.hide('stuff_for_pre_approve_only'); Element.hide('stuff_for_final'); break; case 2: Element.hide('stuff_for_draft'); Element.show('stuff_for_pre_approve_only'); Element.hide('stuff_for_final'); break: case 3: Element.hide('stuff_for_draft'); Element.hide('stuff_for_pre_approve_only'); Element. show('stuff_for_final'); } }
------------------------ The problem here is that we are using 'magic number or strings' in our controller and javascript files. If requirements change, and often they do, or one of the values needs to be renamed, or removed, etc, we have to remember to make the changes in three different places. Our '@options' could have also come from an enumerated type or an ActiveRecord object using the id and some other field for the value. One way to handle this duplication is to create a constant, normally in a model or the controller, and use it in the helper to generate the javascript.
controller:DRAFT = 1 PRE_SUBMIT = 2 FINAL_SUBMIT = 3 def edit @options = [['Draft', DRAFT],['Pre-Approve', PRE_SUBMIT],['Final Submission', FINAL_SUBMIT]] end def handle_status if params[:status] == DRAFT # ignore validation, etc. elsif params[:status] == PRE_SUBMIT # some other business logic elsif params[:status] == FINAL_SUBMIT # other business logic, validate and save end end------------------------ helper file:def handle_option_js js =<<-EOF function handleOption() { var selected = $('status').id; switch (selected) { case '#{ItemController::DRAFT}': Element.show('stuff_for_draft'); Element.hide('stuff_for_pre_approve_only'); Element.hide('stuff_for_final'); break; case '#{ItemController::PRE_SUMMIT}': Element.hide('stuff_for_draft'); Element.show('stuff_for_pre_approve_only'); Element.hide('stuff_for_final'); break: case '#{ItemController::FINAL_SUBMIT}': Element.hide('stuff_for_draft'); Element.hide('stuff_for_pre_approve_only'); Element. show('stuff_for_final'); } } EOF end------------------------ edit.rhtml:<%= javascript_tag handle_option_js %> <% form_tag :action=>'handle_status' do%> <%= select_tag 'status', options_for_select(@options), {:onchange=>'handleOption'}-%> <% end %>------------------------
You could of course replace the constants with perhaps methods that pulled the value or id from some active record. This is a simplistic example, but demonstrates when it maybe beneficial to have the javascript generated rather than having it in a static file. You lose the browser caching, but you gain maintainability.
Categories
News
Careers
Passionate, talented, ambitious, creative … sound familiar?
Three Pillar Global is hiring the best and brightest, and we might just be looking for you.
Check out our open positions.


Leave a comment