Ruby on Rails Wednesday, April 3, 2013

I am unfamiliar with this concept of separating helper functions. In
the interest of DRY code, what you're doing makes complete sense to
me.

On Tue, Apr 2, 2013 at 4:54 PM, John Merlino <stoicism1@aol.com> wrote:
> I came across some posts which postulate that it's undesirable to
> share helper methods across controller and views because UI code
> (designed to render HTML) should be separate from controller code
> (designed for handling requests). That makes sense but there are
> times, a good example is filtering, when it only makes sense to create
> a reusable method to query against the params hash from both
> controller and view. For example, I created some custom filtering and
> sorting. When a http request is initially made, my controller must be
> able to query the database for results without user input.
>
>
> # controller layer (query a default without user input)
> helper_method :sort_column, :sort_direction, :for_selected_month, :for_selected_year
> def driver_reports_table
> @drivers = Driver.select("drivers.*,
> #{sort_column}").joins([:reports, :driving_habits]).by_month(for_selected_month.to_i,
> for_selected_year.to_i).order(sort_column + " " +
> sort_direction).page(params[:page]).per(10)
> @unit = current_unit
> respond_to do |format|
> format.html { render :partial => '/home/reports/
> driver_reports_table', :layout => false, :locals => { :drivers =>
> @drivers, :unit => @unit } }
> format.json { render :json => @drivers}
> end
> end
>
>
> private
>
> def sort_column
> if legal_attributes.include? params[:order]
> params[:order]
> else
> "drivers.id"
> end
> end
>
> def sort_direction
> %w[asc desc].include?(params[:direction]) ? params[:direction] :
> "asc"
> end
>
> def for_selected_month
> (params[:date] && params[:date][:month]) || Time.now.month
> end
>
> def for_selected_year
> (params[:date] && params[:date][:year]) || Time.now.year
> end
>
> def legal_attributes
> @columns ||= Driver.column_names + DrivingHabit.column_names
> end
>
> In my view layer, the user will interact with form elements and links
> to modify the values of the params hash
> In one situation, I have a form tag where the user will set the date
> and date and month/year attributes of the params hash:
> #view
> = form_tag driver_reports_path, :method => 'get', :id =>
> 'drivers_filter' do
> %fieldset.filter_tab
> = select_month(Date.today)
> = select_year(Date.today, :start_year => 2012, :end_year =>
> Time.now.year)
> = submit_tag "Filter Date"
> = render '/home/reports/driver_reports_table'
>
> In another situation, I have links where the user will set the sort
> and direction attributes of the params hash, depending on which link
> they click:
> #partial
> = hidden_field_tag :sort, params[:sort]
> = hidden_field_tag :direction, params[:direction]
> ...
> %table.sortable
> %tr
> = sortable "id", :order => "drivers.id"
>
> #helper
> def sortable(column, query_string={})
> title ||= column.titleize
> query_string[:order] = query_string[:order] || column
> css_class = 'driver_refresh'
> css_class << (column ==
> sort_column.gsub("driving_habits.","").gsub("drivers.","") ? " current
> #{sort_direction}" : "")
> query_string[:direction] = column ==
> sort_column.gsub("driving_habits.","").gsub("drivers.","") &&
> sort_direction == "asc" ? "desc" : "asc"
> query_string[:page] = nil
>
> content_tag :th, link_to(title,
> driver_reports_path(params.merge(query_string)), {:class =>
> css_class })
> end
>
> Each of the situations compensate for the other. If the user selects
> an option from the select tag and thus populates the date attributes,
> when they click a link, it will merge the date attributes from the
> form with the link attributes that were selected and thus send them
> together to the server. Conversely, when the form is submitted,
> because of the hidden field tags with the current value of the sort
> and direction attributes stored in them, those attributes will be send
> with the form attributes.
>
> As you can see, my view helper makes use of the sort_column and
> sort_direction methods to check the current values in the params hash
> to determine how to render the links. So those methods have importance
> both in the controller and view layer. So it would make sense to
> define the methods once and reuse them in both layers. So what is
> wrong with this technique and how else could it be done so as not to
> violate the MVC structure and separation of concerns?
>
> --
> You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to rubyonrails-talk+unsubscribe@googlegroups.com.
> To post to this group, send email to rubyonrails-talk@googlegroups.com.
> For more options, visit https://groups.google.com/groups/opt_out.
>
>

--
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rubyonrails-talk+unsubscribe@googlegroups.com.
To post to this group, send email to rubyonrails-talk@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

No comments:

Post a Comment