Wednesday, June 22, 2011

Rails: Calling Controller Action using onclick and Ajax (remote_function)

Say you want to call the update_reasons action in the reports controller in response to an onclick on a checkbox.

First, of course, you need the route in config/routes.rb



match "/reports/update_reasons" => "reports#update_reasons"



And, of course, the action...I just echo relevant arguments in this version.

Note, I render "nothing" because operation does not result in any view change beyond status change of checkbox which is managed by browser.


def update_reasons
  checked = params[:checked]
  params.each do |key, value|
    if /reasons_(\d+)/.match(value) != nil
      logger.debug("update reason #{$1} to #{checked}")
    end
  end
  respond_to do |format|
    format.js { render  :nothing => true }
  end
end


Using the check_box_tag, you will include on :onclick parameter. The value of :onclick is javascript. The "best" way to generate that javascript is using remote_function helper. I use the :with parameter to send request parameters

with the Ajax call. Notice in ruby code above reference to parameter names appearing in value of :with string in view code.



Here is my view code:



<% reasons.each do |infraction| %>
    <% rf =  remote_function(
       :url => { :controller => 'reports', 
               :action => :update_reasons },
       :with => '\'reason=\'+ this.id + \'&checked=\' + this.checked')  %>
    <%= check_box_tag "reasons[#{infraction.id}]", 
      infraction.description,
      false ,
      :onclick => "#{rf}",
      :class=>:"iToggle", :title=>"YES|NO" %>
    <%= infraction.description %>  
  <% end %>



If I expect some server-side generated change to view, I could include an :update argument to remote_function. This parameter names a div into rendered output is placed.

I admit I took a lazy approach by placing value of remote_function to a local variable. After much hair-pulling,I gave on trying to get quotes right with remote_function as direct value of :onclick parameter.

Monday, June 20, 2011

Contact Reasons Associated with a Report

I have added a method to RelationshipToReport model that returns a list of only those 'relationships' that apply to a given report type. The method name is for.

Here is an example usage:

infractions = RelationshipToReport.for(report)
infractions.each do |infraction|
...
end

Wednesday, April 13, 2011

Javascript and Rails

I have learned two things in the last 24 hours:

Javascript in partials

You can't place <% javascript_tag do %> in partials if you expect your javascript to be seen.

Multiple Requests as a Result of Form Submit

Multiple inclusions of js files, e.g. rails.js can cause multiple events/requests to be posted as a result of form submit. This is very hard to debug, but rails server shows, e.g. multiple GET requests being performed.

Monday, April 4, 2011

Cucumber on Windows

You must augment instructions from RSpec book for installing Cucumber on Windows. Specifically, you need to download MinGW for gcc (c compiler) and make. MinGW is
available from http://www.mingw.org/

When installing MinGW, make sure you select MSYS Developer Kit when stepping through installer.

To access gcc, you need to augment PATH environment variable to include C:\MinGW\bin.
To access make, you need to include C:\MinGW\msys\1.0\bin on your PATH environment variable. See Control Panel->System->Advanced->Environment Variables to edit PATH environment variable.

Wednesday, March 2, 2011

Default Values in ActiveRecord Fields

Looking at some of the incident report controller code, I noticed a few rogue constants floating around. They appeared to be primary key values of default values for, e.g. infractions.

Let me propose an alternative: set the default in the ActiveRecord code. There are a variety of approaches discussed here.

Check it out.

So, we should consider something like:
class RecordedInfraction < ActiveRecord::Base
  after_initialize :default_values

  private
    def default_values
      self.infraction_id ||= Infraction.find_by_name("FYI").id
    end
end

That way we can reduce the WTFs when reading our code.