What's wrong with this Dynamic select by JQuery? - ruby-on-rails

I'm trying to make the dynamic select just like this http://railscasts.com/episodes/88-dynamic-select-menus-revised?view=asciicast
In my case, it won't work somehow.
What's wrong with my code?
views/registrations/edit.html.erb
<h2>Edit <%= resource_name.to_s.humanize %></h2>
<% resource.build_user_profile if resource.user_profile.nil? %>
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => { :method => :put, :class => 'form-horizontal' }) do |f| %>
<%= devise_error_messages! %>
<%= f.fields_for :user_profile do |profile_form| %>
<%= profile_form.label :country_id %><br />
<%= profile_form.collection_select :country_id, Country.all, :id, :name, include_blank: true %>
<%= profile_form.label :prefecture_id, "State or Prefecture" %><br />
<%= profile_form.grouped_collection_select :prefecture_id, Country.all, :prefectures, :name, :id, :name, include_blank: true %>
<% end %>
<br />
<div class="control-group">
<div class="controls">
<%= f.submit 'Update', :class => 'btn btn-primary' %>
</div>
</div>
<% end %>
user_profiles.js.coffee
jQuery ->
$('#user_profile_prefecture_id').parent().hide()
states = $('#user_profile_prefecture_id').html()
console.log(prefectures)
$('#user_profile_country_id').change ->
country = $('#user_profile_country_id :selected').text()
escaped_country = country.replace(/([ #;&,.+*~\':"!^$[\]()=>|\/#])/g, '\\$1')
options = $(prefectures).filter("optgroup[label=#{escaped_country}]").html()
console.log(options)
if options
$('#user_profile_prefecture_id').html(options)
$('#user_profile_prefecture_id').parent().show()
else
$('#user_profile_prefecture_id').empty()
$('#user_profile_prefecture_id').parent().hide()

In any case when you pass:
<%= f.fields_for :user_profile ... %>
field's attributes name= and id= can not be just "#user_profile...", when parent form builder has an object. To determine exactly ID look at the source code (HTML response).

Related

Ruby on Rails - Nested Attributes Creating Duplicate Records

Please don't flag this as duplicate. I've already reviewed the other similar questions and mine is different.
I have an issue where some of the users that input their addresses manage to create duplicate CartAddress records.
My database structure includes a Cart model and CartAddress model.
The Cart model looks something like this:
class Cart < ApplicationRecord
has_many :cart_addresses, -> { order(address_type: :asc) }, inverse_of: :cart, dependent: :destroy
accepts_nested_attributes_for :cart_addresses, allow_destroy: true
end
My CartAddress model looks like this:
class CartAddress < ApplicationRecord
belongs_to :cart
validates :first_name, presence: true
validates :last_name, presence: true
validates :email, presence: true
validates :telephone, presence: true
validates :address_line_one, presence: true
validates :city, presence: true
validates :country, presence: true
validates :state, presence: true
validates :zip_code, presence: true
validates_format_of :email, :with => /\A([^#\s]+)#((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i
end
When the user loads the cart page:
def index
#bunch of init code here
#more here
#exists = true
if #cart.cart_addresses.count == 0
#exists = false
2.times { #cart.cart_addresses.build(country: "United States", state: "Alabama")}
end
end
Then when I create/update:
def update_addresses
#countries = Country.all
#states = State.all
#cart = Cart.find(params[:cart][:id])
if params[:cart][:cart_addresses_attributes]["0"][:address_type] == "Billing" and params[:cart][:cart_addresses_attributes]["1"][:address_type] == "Shipping"
#cart.update(params.require(:cart).permit(cart_addresses_attributes: [:id, :address_type, :first_name, :last_name, :email, :telephone, :address_line_one, :address_line_two, :city, :zip_code, :country, :state]))
#bunch of other code
end
Here is my partial that renders the form
<%= form_for(cart, :remote => true, :url => update_cart_addresses_path, :html => {:class => 'addresses-class', :id => 'cart-addresses', :autocomplete => :off}) do |u| %>
<% billing = true %>
<% state = 0 %>
<%= u.hidden_field :id %>
<% offset_two = true %>
<% if #exists == true %>
<%= u.fields_for :cart_addresses do |b| %>
<%= b.hidden_field :address_type %>
<% if billing == true %>
<div class="col-xs-12">
<h4>Billing Address</h4>
<% billing = false %>
</div>
<% else %>
<div class="col-xs-12 pad-top-15 checkout-section-padding">
<h4>Shipping Address</h4>
<input type="checkbox" id="same-as-billing" name="same_as_billing" value="1" onclick="toggleShippingAddress(this);">Same as Billing?
</div>
<% end %>
<div class="address">
<div class="col-xs-6">
<%= b.label :first_name %><span class="required-field">*</span>
<%= b.text_field :first_name, class: 'checkout-addr-text-field required', :data => {:hj_whitelist => ''}%>
</div>
<div class="col-xs-6">
<%= b.label :last_name %><span class="required-field">*</span>
<%= b.text_field :last_name, class: 'checkout-addr-text-field required', :data => {:hj_whitelist => ''} %>
</div>
<div class="col-xs-6 pad-top-15">
<%= b.label :email %><span class="required-field">*</span>
<%= b.email_field :email, class: 'checkout-addr-text-field required', :data => {:hj_whitelist => ''} %>
</div>
<div class="col-xs-6 pad-top-15">
<%= b.label :telephone %><span class="required-field">*</span>
<%= b.text_field :telephone, class: 'checkout-addr-text-field required', :data => {:hj_whitelist => ''} %>
</div>
<div class="col-xs-12 pad-top-15">
<%= b.label :address_line_one %><span class="required-field">*</span>
<%= b.text_field :address_line_one, class: 'checkout-addr-text-field required', :data => {:hj_whitelist => ''} %>
</div>
<div class="col-xs-12 pad-top-15">
<%= b.text_field :address_line_two, class: 'checkout-addr-text-field', :data => {:hj_whitelist => ''} %>
</div>
<div class="col-xs-12 pad-top-15">
<%= b.label :city %><span class="required-field">*</span>
<%= b.text_field :city, class: 'checkout-addr-text-field required', :data => {:hj_whitelist => ''} %>
</div>
<div class="col-xs-12 pad-top-15">
<%= b.label :country %><span class="required-field">*</span>
<%= b.select(:country, countries.all.collect {|a| [a.name]}, {:prompt => "Select A Country"}, :onchange => "setStates(#{state});", class: 'checkout-country') %>
</div>
<div class="col-xs-6 pad-top-15">
<div id="<%= "state_" + state.to_s %>">
<%= b.label :state %><span class="required-field">*</span>
<%= b.text_field :state, class: 'checkout-addr-text-field' %>
</div>
</div>
<div class="col-xs-6 pad-top-15">
<%= b.label :zip_code%><span class="required-field">*</span>
<%= b.text_field :zip_code, class: 'checkout-addr-text-field required', :data => {:hj_whitelist => ''} %>
</div>
<% state = state + 1 %>
</div>
<% end %>
<% else %>
<%= u.fields_for :cart_addresses do |b| %>
<% if billing == true %>
<div class="col-xs-12">
<h4>Billing Address</h4>
<% billing = false %>
<%= b.hidden_field :address_type, value: "Billing" %>
</div>
<% else %>
<div class="col-xs-12 pad-top-15 checkout-section-padding">
<h4>Shipping Address</h4>
<input type="checkbox" id="same-as-billing" name="same_as_billing" value="1" onclick="toggleShippingAddress(this);">Same as Billing?
<%= b.hidden_field :address_type, value: "Shipping" %>
</div>
<% end %>
<div class="address">
<div class="col-xs-6">
<%= b.label :first_name %><span class="required-field">*</span>
<%= b.text_field :first_name, class: 'checkout-addr-text-field required', :data => {:hj_whitelist => ''} %>
</div>
<div class="col-xs-6">
<%= b.label :last_name %><span class="required-field">*</span>
<%= b.text_field :last_name, class: 'checkout-addr-text-field required', :data => {:hj_whitelist => ''} %>
</div>
<div class="col-xs-6 pad-top-15">
<%= b.label :email %><span class="required-field">*</span>
<%= b.email_field :email, class: 'checkout-addr-text-field required', :data => {:hj_whitelist => ''} %>
</div>
<div class="col-xs-6 pad-top-15">
<%= b.label :telephone %><span class="required-field">*</span>
<%= b.text_field :telephone, class: 'checkout-addr-text-field required', :data => {:hj_whitelist => ''} %>
</div>
<div class="col-xs-12 pad-top-15">
<%= b.label :address_line_one %><span class="required-field">*</span>
<%= b.text_field :address_line_one, class: 'checkout-addr-text-field required', :data => {:hj_whitelist => ''} %>
</div>
<div class="col-xs-12 pad-top-15">
<%= b.text_field :address_line_two, class: 'checkout-addr-text-field', :data => {:hj_whitelist => ''} %>
</div>
<div class="col-xs-12 pad-top-15">
<%= b.label :city %><span class="required-field">*</span>
<%= b.text_field :city, class: 'checkout-addr-text-field required', :data => {:hj_whitelist => ''} %>
</div>
<div class="col-xs-12 pad-top-15">
<%= b.label :country %><span class="required-field">*</span>
<%= b.select(:country, countries.all.collect {|a| [a.name]}, {:prompt => "Select A Country"}, :onchange => "setStates(#{state});", class: 'checkout-country') %>
</div>
<div class="col-xs-6 pad-top-15">
<div id="<%= "state_" + state.to_s %>">
<%= b.label :state %><span class="required-field">*</span>
<%= b.text_field :state, class: 'checkout-addr-text-field' %>
</div>
</div>
<div class="col-xs-6 pad-top-15">
<%= b.label :zip_code %><span class="required-field">*</span>
<%= b.text_field :zip_code, class: 'checkout-addr-text-field required', :data => {:hj_whitelist => ''} %>
</div>
<% state = state + 1 %>
</div>
<% end %>
<% end %>
<% end %>
<div class="col-xs-12 pad-top-15">
<button id="update-checkout-addresses-btn" class="checkout-addresses-submit-btn btn btn-primary btn-sm" onclick="submitCheckoutAddressesForm(this);" type="button">Update Addresses</button>
</div>
When creating new address records the form is submitted without an id. When editing the records a id is submitted. Somehow it appears that the form is being submitted more than once although I do have javascript disabling the form upon submission. How should I handle this in the controller to prevent this error from happening? Or fix my view partial?
UPDATE
Here is my JS
function submitCheckoutAddressesForm(element){
element.disabled = true;
var e = document.getElementById("same-as-billing")
sameAsBillingCheckout(e);
$(e).closest("form").submit();
}
The below function makes sure that all the elements are the same in the form if a checkbox "Shipping Address Same As Billing" is selected. The reason I am having to clone the element and copy it into the shipping addresses is because the element type has the ability to change due to other javascript. I figured this would be the safest way of handling this event just to ensure that the proper elements were submitted in the form. I don't see that this should effect the duplicate records being created.
function sameAsBillingCheckout(element){
if(element.checked == true){
var billing = ["#cart_cart_addresses_attributes_0_first_name", "#cart_cart_addresses_attributes_0_last_name", "#cart_cart_addresses_attributes_0_email", "#cart_cart_addresses_attributes_0_telephone",
"#cart_cart_addresses_attributes_0_address_line_one", "#cart_cart_addresses_attributes_0_address_line_two", "#cart_cart_addresses_attributes_0_country", "#cart_cart_addresses_attributes_0_state", "#cart_cart_addresses_attributes_0_city", "#cart_cart_addresses_attributes_0_zip_code"]
var shipping = ["#cart_cart_addresses_attributes_1_first_name", "#cart_cart_addresses_attributes_1_last_name", "#cart_cart_addresses_attributes_1_email", "#cart_cart_addresses_attributes_1_telephone",
"#cart_cart_addresses_attributes_1_address_line_one", "#cart_cart_addresses_attributes_1_address_line_two", "#cart_cart_addresses_attributes_1_country", "#cart_cart_addresses_attributes_1_state", "#cart_cart_addresses_attributes_1_city", "#cart_cart_addresses_attributes_1_zip_code"]
for(i = 0; i < billing.length; i++){
$(shipping[i]).val($(billing[i]).val());
if(billing[i] == "#cart_cart_addresses_attributes_0_country"){
$("#cart_cart_addresses_attributes_1_state").remove();
var e = document.getElementById("cart_cart_addresses_attributes_0_state");
var cln = e.cloneNode(true);
cln.name = "cart[cart_addresses_attributes][1][state]";
cln.id = "cart_cart_addresses_attributes_1_state";
var stateDiv = document.getElementById("state_1");
stateDiv.appendChild(cln);
}
}
}
}
This code below does the same as the javascript above. It's just submitting the form after the user finishes typing if the form isn't disabled.
$(function(){
//create one instance for handler:
var myHandler = function(e){
var sAB = document.getElementById("same-as-billing").checked;
var ready = true;
//LOOPS THROUGH ALL THE TEXT FIELDS
$('.checkout-addr-text-field').each(function (){
//IF SAME AS BILLING CHECKBOX SELECTED
if(sAB == true){
//if the field is disabled or the field includes _0_ (means its a billing address field) and the id is not the optional field and the value isn't blank then dont submit the form.
if(this.disabled || this.id.indexOf("_0_") !== -1 && this.id !=
"cart_cart_addresses_attributes_0_address_line_two" && this.value == ""){
ready = false;
}
}else{ // IF SAME AS BILLING CHECKBOX NOT SELECTED
if(this.disabled || this.id !=
"cart_cart_addresses_attributes_0_address_line_two" && this.id !=
"cart_cart_addresses_attributes_1_address_line_two" && this.value == ""){
ready = false;
}
}
});
if(ready == true){
var e = document.getElementById("same-as-billing")
sameAsBillingCheckout(e);
$(e).closest("form").submit();
$("#cart-addresses :input").attr("disabled", true);
}
};
$(document).on('keyup', '.checkout-addr-text-field', debounce(function(e){
myHandler(e);
}, 1700));
$(document).on('change', '#cart_cart_addresses_attributes_0_state', function(e){
myHandler(e);
});
$(document).on('change', '#cart_cart_addresses_attributes_1_state', function(e){
myHandler(e);
});
$(document).on('change', '#cart_cart_addresses_attributes_0_state', function(e){
myHandler(e);
});
$(document).on('click', '#same-as-billing', function(e){
if(this.checked){
myHandler(e);
}
});
});

Rails f.select not passing values

Here is code sample:
<%= form_for #article, html: { class: "form-horizontal" } do |f| %>
<div class="form-group">
<%= f.label :keywords, class: 'col-md-1 control-label' %>
<div class="col-md-3">
<%= f.select :keywords, ['test_1', 'test_2', 'test_3', 'test_4', 'test_5'], {}, { :multiple => true, :size => 10, :class => 'form-control' } %>
</div>
</div>
<% end %>
When I set multiple to 'false' it works just fine, but if I set it to true (for multiple select), it just doesn't pass any data. If I have verification it gives me an "keyword is empty" error and if I remove validation - it is just empty. Any ideas?
<%= f.select :keywords, options_for_select([['test_1','test_1'], ['test_2','test_2'], ['test_3','test_3'], ['test_4','test_4'], ['test_5','test_5']]), {}, { :multiple => true, :size => 10, :class => 'form-control' } %>

Getting an "undefined method `permit' for "create"" error when submitting form

When I try to create an "Action" I get this error.
My Actions controller:
class ActionsController < ApplicationController
def new
#match_set = MatchSet.find(params[:match_set_id])
#fixture = #match_set.fixture
#teams = Team.where("id = " + #fixture.home_team_id.to_s + " OR id = " + #fixture.away_team_id.to_s)
#players = Player.where("team_id = " + #teams.ids.first.to_s + " OR id = " + #teams.ids.last.to_s)
#action = #match_set.actions.new
end
def create
#match_set = MatchSet.find(params[:match_set_id])
#action = #match_set.actions.new(action_params)
if #action.save
redirect_to match_set(#match_set)
else
render "actions/new"
end
end
private
def action_params
params.require(:action).permit(:team_id, :player_id, :position, :action_type, :action_result)
end
end
It is submitted from this form in views/actions/new.html.erb:
<%= form_for [#match_set, #action] do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<!-- Team -->
<%= f.label :team_id %>
<%= f.collection_select :team_id, #teams,:id, :name, {include_blank: "Select team..."}, {class: "form-control"} %>
<!-- Player -->
<%= f.label :player_id %>
<%= f.collection_select :player_id, #players,:id, :last_name, {include_blank: "Select player..."}, {class: "form-control"} %>
<!-- Position -->
<%= f.label :position %>
<%= f.select :position, options_for_select(['1', '2', '3', '4', '5', '6']), {include_blank: "Select position on court..."}, class: "form-control" %>
<!-- Action Type -->
<%= f.label :action_type %>
<%= f.select :action_type, options_for_select(['Attack', 'Block', 'Pass', 'Set']), {include_blank: "Select action_type..."}, class: "form-control" %>
<!-- Action Result -->
<%= f.label :action_result %>
<%= f.select :action_result, options_for_select(['Score', 'Block', 'Pass', 'Set']), {include_blank: "Select action_type..."}, class: "form-control" %>
<!-- Submit Button -->
<%= f.submit "Add Action", class: "btn btn-primary" %>
<% end %>
Also the relevant routes:
resources :fixtures, shallow: true do
resources :match_sets, shallow: true do
resources :actions
end
end
I'm getting an error on this line in the controller:
params.require(:action).permit(:team_id,:player_id,
:position,:action_type,:action_result)
I have also noticed that my parameters seem to be disappearing but again have no clue as to the cause.
Parameters:
{"utf8"=>"✓", "authenticity_token"=>"BqbEOfL7hEA8XSMXDvMW2qQ2uR74Egp5
jJvtQlsuyV2TikZJ+6hTIEMH05gy8TM6r3ZglFDRUFBl7ScZD1czCQ==",
"commit"=>"Add Action", "match_set_id"=>"15"}
Any help is appreciated.
action is a reserved word in rails. You will need to change your model name.
Rails provides a few params on each request such as:
params[:controller] # maps to your controller name
params[:action] # maps to an action with your controllers
http://api.rubyonrails.org/classes/ActionDispatch/Routing.html

Search filter applied through "link_to"

So i have a search filter working perfectly in my index view. The code in the controller is as follows
def index
#tutor = Tutor.where(:admin => false)
#tutor_array = []
#tutor_array << #tutor.fees_search(params[:fees_search]) if params[:fees_search].present?
#tutor_array << #tutor.subject_search(params[:subject_search]) if params[:subject_search].present?
#tutor_array << #tutor.lssubject_search(params[:lssubject_search]) if params[:lssubject_search].present?
#tutor_array << #tutor.ussubject_search(params[:ussubject_search]) if params[:ussubject_search].present?
#tutor_array << #tutor.jcsubject_search(params[:jcsubject_search]) if params[:jcsubject_search].present?
#tutor_array.each do |tutor|
ids = #tutor.merge(tutor).map(&:id)
#tutor = Tutor.where(id: ids)
end
#tutor = #tutor.sort_by { |tutor| tutor.rating.rating }.reverse
#tutor = #tutor.paginate(:page => params[:page], :per_page => 2)
end
And in my view the form that passes in the search filters for me is
<form class='form-inline'>
<%= form_tag(tutors_path, method: :get) do %>
<div class='row', id='filter-form'>
<div class='form-group'>
<%= label_tag 'subject_search', 'Primary Subject' %>
<% subject_array = Subject.all.map { |subject| [subject.name] } %>
<%= select_tag 'subject_search', options_for_select(subject_array, :selected => params[:subject_search]), :include_blank => true, class:'form-control' %>
<%= label_tag 'lssubject_search', 'Lower Sec Subject' %>
<% lssubject_array = Lssubject.all.map { |lssubject| [lssubject.name] } %>
<%= select_tag 'lssubject_search', options_for_select(lssubject_array, :selected => params[:lssubject_search]), :include_blank => true, class:'form-control' %>
<%= label_tag 'ussubject_search', 'Upper Sec Subject' %>
<% ussubject_array = Ussubject.all.map { |ussubject| [ussubject.name] } %>
<%= select_tag 'ussubject_search', options_for_select(ussubject_array, :selected => params[:ussubject_search]), :include_blank => true, class:'form-control' %>
</div>
</div>
<div class='row', id='filter-form2'>
<div class='form-group'>
<%= label_tag 'jcsubject_search', 'JC Subject' %>
<% jcsubject_array = Jcsubject.all.map { |jcsubject| [jcsubject.name] } %>
<%= select_tag 'jcsubject_search', options_for_select(jcsubject_array, :selected => params[:jcsubject_search]), :include_blank => true, class:'form-control' %>
<%= label_tag 'fees_search', 'Max Fees' %>
<%= select_tag 'fees_search', options_for_select((10..150).step(10), :selected => params[:fees_search]), :include_blank => true, class:'form-control' %>
<%= submit_tag 'Filter', class: 'btn btn-primary btn-xs' %>
</div>
</div>
<% end %>
<div id='filter-reset'>
<%= link_to 'Reset Filters', tutors_path, class: 'btn btn-primary btn-xs' %>
</div>
</form>
And when a filter is passed in an example or the URL attained is as follows
/tutors?utf8=✓&subject_search=Science&lssubject_search=&ussubject_search=&jcsubject_search=&fees_search=&commit=Filter
What i would like to ask is, how do i pass in the filters through a button?
So if i were to click on "Math" or "English" its equivalent to passing in the filter through the form? I understand that it'll most likely be link_to tutors_path(???) but what should go into the parenthesis to pass the correct filters in?
I tried <%= link_to subs.name, tutors_path(:subject_search => subs.name %> and it seems like it works. To provide some context here's the view and how subs.name comes about.
<% tutor.subjects.each do |subs| %>
<span class='badge'id='tutor-listing-badge'>
<%= link_to subs.name, tutors_path(:subject_search => subs.name) %>
</span>
<% end %>

Refactor ugly if/else statement in Rails View

I have this nasty if/else statement in a rails view:
<% if question.field_type == "text_area" %>
<%= f.text_area :content, :class=>"form-control question-field", :data => {:question => question.id, :filter=> #filter}, :value=> question.answer(#assessment).try(:content) %>
<% elsif question.field_type == "date" %>
<%= f.date_select :content, { :order => [:year, :month, :day], :prompt => { :day => 'day', :month => 'month', :year=> "year" }, :end_year=> Date.today.year, :start_year => Date.today.year - 2 }, {:class => "question-field", :data => {:question => question.id, :filter=> #filter}, :value=> question.answer(#assessment).try(:content)} %>
<% elsif question.field_type == "text_field" %>
<%= f.text_field :content, :class=>"form-control question-field", :value=> question.answer(#assessment).try(:content), :data => {:question => question.id, :filter=> #filter} %>
<% elsif question.field_type == "dropdown" %>
<%= f.select :content, options_for_select(question.options), { :prompt => "Choose One..." }, :class=>"form-control question-field", :value=> question.answer(#assessment).try(:content), :data => {:question => question.id, :filter=> #filter} %>
<% elsif question.field_type == "number" %>
<%= f.select :content, options_for_select(1..10), {:include_blank=> true}, :class=>"form-control question-field", :value=> question.answer(#assessment).try(:content), :data => {:question => question.id, :filter=> #filter} %>
<% elsif question.field_type == "percentage" %>
<h2>100%</h2>
<%= f.range_field :content, :value=> get_percentage(question), :class=> "question-field percentage", :data => {:question => question.id, :filter=> #filter}, :step => 25, :in => 0..100 %>
<% end %>
Is there a good way to refactor this to make it nicer? This piece of code is in every field:
:class=>"form-control question-field", :value=> question.answer(#assessment).try(:content), :data => {:question => question.id, :filter=> #filter}
Do I refactor into a helper method or a partial?
Sometimes templates are just messy and you can only clean up detail. Refactoring into a parameterized partial will help. For goodness sake, use a case. And consider switching to HAML. It eliminates a lot of the visual clutter.
<%= render 'question_field', f: f, type: question.field_type %>
Then in _question_field.erb,
<%= case type %>
<% when 'text_area' %>
<% f.text_area :content, class: 'form-control question-field', %>
<% data: { question: question.id, filter: #filter }, %>
<% value: question.answer(#assessment).try(:content) %>
<% when ... %>
<% end %>
Note common industrial practice is to pick a max line length and stick to it: 100 and 120 are pretty common. Also, use the new symbol key notation for hashes. The old hook-and-arrow is too noisy.
In HAML:
= case type
- when 'text_area'
- f.text_area :content, class: 'form-control question-field',
data: { question: question.id, filter: #filter },
value: question.answer(#assessment).try(:content)
- when ...
I would get rid of if's and when's altogether by creating seperate partial for every possibility, then you just end up with:
<%= render question.field_type, locals: {question: question} %>
Or to make it even cleaner for view make helper method and call only
<%= question_field(question) %>
and this method would look little bit like
def question_field(question)
return render question.field_type, locals: {question: question}
# raise when no partial found, or do something elese
end

Resources