Normally, we build a restful rails application when a ordering transaction system is needed. However, imaging a scenario such as a bicycle with three attributes:
- model
- size
- color
The size and color options vary by model and they are not always the same combination across all models. For example, model A has size options of 700c X 48cm, 700c X 50cm and 700c X 52cm and color options of red, blue and black. Model B may have 700c X 48cm and 700c X 50cm and color options of green and orange. Therefore, when model changes during user operation, the size and color options must be changed accordingly.
That is a big design problem for a Rails application. Unless there is a a button for user to press and refresh the page while a model has been chosen, the Rails app has no idea when to refresh the page.
I use jQuery to solve this problem.
jQuery ajax can be used to listen the change of the model selection. When the model change happens, ajax calls the get_info function in orderdetails controller.
/view/orderdetails/new.html.erb
<script type="text/javascript">
$('#orderdetail_model_id').on('change', function() {
$.ajax({
url: '/get_info',
type: 'GET',
data: { model_id: this.value }
})
});
</script>
The path is set in the routes.rb first.
get '/get_info', to: 'orderdetails#get_info', as: :get_info
Then ‘get_info’ function returns the instance variables needed for the page refresh.
controller orderdetails#get_info
def get_info
@model = Model.find(params[:model_id])
@sizes = @model.sizes
@colors = @model.colors
respond_to do |format|
format.js
end
end
Here is the magic: ‘get_info.js.erb’ replace the size and color select in their divs . The size and color options changes while model changes.
get_info.js.erb
$("#orderdetail_select_size_id").html("<%= escape_javascript(select("orderdetail", "size_id", @sizes.collect {|s| [s.name, s.id ] }, { include_blank: false })) %>");
$("#orderdetail_select_color_id").html("<%= escape_javascript(select("orderdetail", "color_id", @colors.collect {|c| [c.name, c.id ] }, { include_blank: false })) %>");
$("#orderdetail_text_field_price").html("<%= escape_javascript(text_field_tag("orderdetail", @model.price, style: "text-align: right", disabled: true )) %>");
TIP:
The code to be replaced need to be modified in the ‘get_info.js.erb’.
The ‘f.select’ causes error because ‘f’ is not defined in the replaced code portion.
The ‘f.select’ causes error because ‘f’ is not defined in the replaced code portion.
f.select("size_id", Model.find_by_id(orderdetail.model_id).sizes.collect {|s| [ s.name, s.id ] }, { include_blank: false })
We have to replace it to the name of the select. By inspecting the generated html file, the name of the select is “orderdetail_select_size_id”. Using select_tag and name the variable as “orderdetail”, the problem solved and it works.
select("orderdetail", "size_id", @sizes.collect {|s| [s.name, s.id ] }, { include_blank: false }))"
No comments:
Post a Comment