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
Related
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 %>
I have a form_for, and a nested fields_for within it.
now it looks like this
form_for blah
fields_for :badgetype do |b|
b.text_field :name
b.text_field :keyword
Params looks like badgetype: { :name => "foo", :keyword => "bar" }
What I want is to have 5 of these set up, and get something like this back:
badgetype: { 1 => { :name => "foo", :keyword => "bar" },
2 => { :name => "boof", :keyword => "baz" },
...
}
How would I accomplish this?
Thank you
<%= form_for blah do |a| %>
<% (1..5).each do |number| %>
<%= a.fields_for "badgetype[#{number}]" do |b| %>
<%= b.text_field :name %>
<%= b.text_field :keyword %>
<% end %>
<% end %>
<%= a.submit %>
<% end %>
This is my form partial:
<%= f.simple_fields_for :photo_attributes, :html => { :multipart => true } do |d| %>
<%= d.label :image, :label => 'Upload logo', :required => false %>
<%= d.file_field :image, :label => 'Image, :required => false', :style => 'margin-bottom:2px' %>
<%= d.input :image_url, :label => 'Billed URL', :required => false %>
<% end %>
If the action is edit I want to show this instead:
<%= f.simple_fields_for :photo, :html => { :multipart => true } do |d| %>
<%= d.label :image, :label => 'Upload logo', :required => false %>
<%= d.file_field :image, :label => 'Image, :required => false', :style => 'margin-bottom:2px' %>
<%= d.input :image_url, :label => 'Billed URL', :required => false %>
<% end %>
How can i achieve this?
current_page?(action: 'edit')
See ActionView::Helpers::UrlHelper#current_page?
Rails also makes the methods controller_path, controller_name, action_name available for use in the view.
Generally the form partial only contains the fields, not the form tag or the fields for, but if you have no other way, you can always see what params[:action] is currently set to and behave accordingly.
You could write something like
<%- form_url = #object.new_record? ? :photo_attributes : :photo %>
<% f.simple_fields_for form_url, :html => { :multipart => true } do |d| %>
That is, if you have an #object to check against. Otherwise you could use action_name (and even controller_name).
So something like:
<%- form_url = action_name == :edit ? :photo : :photo_attributes %>
<% f.simple_fields_for form_url, :html => { :multipart => true } do |d| %>
Hope this helps.
Rails 5: Display Action within the view
<%= action_name %>
If statement within the view
<% if action_name == "edit" %>
This is an edit action.
<% end %>
Just use #_controller.action_name in view
I have following controller:
def personalization
#title = t "generic.forms.personalization"
end
def update_personalization
begin
#user.user_data.birthdate = Date.civil(params[:user_data][:"birthdate(1i)"].to_i,params[:user_data][:"birthdate(2i)"].to_i,params[:user_data][:"birthdate(3i)"].to_i)
rescue
wrong_data = 1
end
if #user.user_data.update_attributes(params[:user_data])
if wrong_data
flash[:Error] = t "generic.messages.error.wrong_data"
redirect_to :back and return
end
flash[:Success] = t "generic.messages.success.account_updated"
redirect_to :back
else
flash[:Error] = #user.user_data.errors.full_messages.join(".<br>")
redirect_to :back
end
end
and following view:
<div id="ProfileEditForm" class="ContentBorders">
<h1 class="FormsHeading"><%= t #title %></h1>
<div class="FormsSpacing">
<%= form_for(#user.user_data, :html => { :id => "UpdateUserForm", :class => "EditForms"}, :url => {:action => 'update_personalization'}) do |f| %>
<% flash.each do |key, value| %>
<div class="FormsMargins <%= key %>"><%=raw value + "." %></div>
<% end %>
<div class="Field"><div class="LabelInline"><%= t "generic.site.first_name" %>:</div>
<%= f.text_field :first_name, :id => "EditFirstName", :class => "Rounded5", :maxlength => "30" %></div>
<div class="Field"><div class="LabelInline"><%= t "generic.site.last_name" %>:</div>
<%= f.text_field :last_name, :id => "EditLastName", :class => "Rounded5", :maxlength => "30" %></div>
<div class="Field DateSelection"><div class="LabelInline"><%= t "generic.site.birthdate" %>:</div>
<%= date_select("user_data", "birthdate", :start_year => 1901, :end_year => 2011, :include_blank => true) %>
</div>
<div class="Field GenderSelection"><div class="LabelInline"><%= t "generic.site.gender" %>:</div>
<%= f.radio_button :gender, "0", :id => "EditGenderMale" %> <span><%= t "generic.site.male" %></span>
<%= f.radio_button :gender, "1", :id => "EditGenderFemale" %> <span><%= t "generic.site.female" %></span>
</div>
<div class="Field EducationSelection"><div class="LabelInline"><%= t "generic.site.educational_level" %>:</div>
<%= f.select :education_level, options_for_select({
" " => 0, (t "generic.site.education_levels.first") => 1, (t "generic.site.education_levels.second") => 2,
(t "generic.site.education_levels.third") => 3, (t "generic.site.education_levels.fourth") => 4,
(t "generic.site.education_levels.fifth") => 5, (t "generic.site.education_levels.sixth") => 6,
(t "generic.site.education_levels.seventh") => 7 }, #user.user_data.education_level) %>
</div>
<div class="Action"><%= f.submit (t "generic.forms.update_data"), :id => "EditSubmit", :class => "ProfileEditAction Shadow1 Rounded5 AcceptButtonsBorder" %></div>
<% end %>
</div>
</div>
<%= render :partial => 'profile_panel' %>
Now. The problem is with date_select method. Each of form field works properly (data from database fills them up), except that which was generated from data_select.
If I select some proper data, and click update button, then it saves that proper data to the db. Problem comes with the moment, when it is generated, and it doesn't come with any values (it's always empty when loaded).
Any ideas, how can that be fixed?
maybe...
you have:
<%= date_select("user_data", "birthdate", :start_year => 1901, :end_year => 2011, :include_blank => true) %>
you need:
<%= f.date_select("user_data", "birthdate", :start_year => 1901, :end_year => 2011, :include_blank => true) %>
just put the "f"
<%= f.date_select ...
I'm trying to pass a string with a link_to_remote call as the :id, and the string should be collected from an input field with and id of "movie_title".
<div id="search_list">Nothing here yet</div>
<br />
<% semantic_form_for #movie do |f| %>
<% f.inputs do -%>
<%= f.input :title, :class => "movie_title" %> <%= link_to_remote( 'Search...', { :url => { :action => :imdb_search, :id => "'+$('\#movie_title').value+'" } }, { :title => "Search for this movie", :class => "imdb_search" } ) -%>
[...removed text that does not matter...]
<% end -%>
<%= f.buttons %>
<% end %>
I keep getting an javascript error, and if I remove the # from the jquery in the link, it returns "Undefined".
The link I get is:
<a class="imdb_search" href="#" onclick="jQuery.ajax({data:'authenticity_token=' + encodeURIComponent('yHPHYTZsPTQLi9JYSauUYcoie/pqPPk2uHBTN0PzNsQ='), dataType:'script', type:'post', url:'/movies/imdb_search/'+$('%23movie_title').value+''}); return false;" title="Search for this movie">Search...</a>
So I want the link updated with the contents of movie_title.
How do I do that?
I'd try something like
<%= link_to_remote( 'Search...', {
:url => { :action => :imdb_search},
:with => "'id=' + $('movie_title').value",
{:title => "Search for this movie", :class => "imdb_search"}
)
Fixed it
Used:
$('movie_title').val()
Insted of
$('movie_title').value