Rails/Ruby delete_if - ruby-on-rails

I have a select tag nested in my form and I am needing to delete an item from my options_for_select array if it equals the word English
code:
<%= fields_for :users_languages do |u| %>
<div class="field">
<%= u.label :Assign_Languages %><br />
<%= select_tag :language_id,
options_for_select(Language.all.collect {|lang|
[lang.english, lang.id].delete_if {lang.english == "English"}
}, #lang_list),
:multiple => true,
:prompt => 'Select Language' %>
</div>
<% end %>
Problem:
The above code works fine, but for some reason the first option is still shown in the mutli-select producing a blank select option. Is there anyway to get rid of the select option and its value? Am I even doing this correctly?
Thanks for all the help in advance!

You can do it using a collect and a reject.
Language.all.collect { |lang| [lang.english, lang.id] }.reject { |(lang, id)| lang == 'English' }
Not sure how to do it using just collect.

I realize this is a year old, but for the sake of future googlers...
Rather than inlining SQL, you might be better off with a named scope:
scope :not_english, where("english != 'English'") # Rails 3
or
named_scope :not_english, :conditions => "english != 'English'" # Rails 2
which will let you do:
options_for_select(Language.not_english.collect {|lang| [lang.english, lang.id]})
That is easier to read, more expressive, and not depending on some magic database id.
Cheers!
(PS: Also, you may want to consider updating your schema so the name of the db column isn't confused with it's value. May I suggest language.name, rather than language.english?)

It looks like your selection is actually returning an empty array as the first element. Try pulling out the unwanted option first:
Language.all.reject {|lang| lang.english == "English}.collect {|lang| [lang.english, lang.id]}

Thanks for the reply guys! What I ended up doing was handle it in my query
code:
<%= fields_for :users_languages do |u| %>
<div class="field">
<%= u.label :Assign_Languages %><br />
<%= select_tag :language_id, options_for_select(Language.find(:all, :conditions => "id != 1").collect {|lang| [lang.english, lang.id]}, #lang_list),:multiple => true, :prompt => 'Select Language' %>
</div>
<% end %>
the first row in the database will always be the same so this was easy to do in the query... although the suggestions above will come in handy in the future! Thanks again!

Related

Changing ruby generated select to checkboxes

Im very much new to ruby, but working on a new clients project and im wanting to change the current dropdown they have into multiple checkboxes but not sure how or if possible.
Current code is:
<%= f.label :section,t(:pick_admin_options)%><br/>
<% options = (#admin_permission.action == :edit) ? section_options('edit') : section_options %>
<%= f.select :section, options_for_select(options,:selected => #admin_permission.section) %>
Anyone have any ideas? much appreciated in advance!
Thanks
I think, This should do the trick:
<%= f.input :sections, :as => :check_boxes, :collection =>
((#admin_permission.action == :edit) ? section_options('edit') : section_options) %>
Thanks

Display a checkbox list instead of multiple select

I have a model MyModel with a serialized attribute a, describing an array of symbols.
This code works :
<% form_for #my_model do |f| %>
<%= f.select :a, MyModel::AS, :multiple => true) %>
<% end %>
The parameters are correct :
{ :my_model => { :a => [:a_value1, :a_value2] } }
I want to transform this multiple select into a set of checkboxes, like this :
<% form_for #my_model do |f| %>
<% MyModel::AS.each do |a_value|
<%= f.check_box(:a_value) %>
<% end %>
<% end %>
It works too, but the parameters are not the same at all :
{ :my_model => { :a_value1 => 1, :a_value2 => 1 } }
I think of 2 solutions to return to the first solution...
Transform my check_box into check_box_tag, replace multiple select, and add some javascript to 'check' select values when user clic on check_box_tags. Then, the parameter will be the same directly in the controller.
Add a litte code into the controller for 'adapting' my params.
What solution is the less ugly ? Or is there any other one ?
I found a solution, using 'multiple' option that I didn't know.
<% MyModel::AS.each do |a_value| %>
<%= f.check_box(:a, { :multiple => true }, a_value) %>
<% end %>
Result parameters are a little weird, but it should work.
{"my_model" => { "a" => ["0", "a_value1", "0", "a_value2", "0"] }
Edit from #Viren : passing nil at the end of the function like
<%= f.check_box(:a, { :multiple => true }, a_value, nil) %>
works perfectly.
There is another solution worth mentioning that makes it very easy to insert records into the database if you have a has_and_belongs_to_many or has_many through relationship by using the collection_check_boxes form helper. See documentation here.
<%= f.collection_check_boxes :mymodel_ids, MyModel::AS, :id, :name do |m| %>
<%= m.check_box %> <%= m.label %>
<% end %>
Then, in the controller we would allow the mymodel_ids attribute:
params.require(:mymodel).permit(:name, mymodel_ids:[])
We can also set up a model validation to require that at least one of the checkboxes be checked:
validates :mymodel_ids, presence: true
An added benefit of this method is that if you later edit the mymodel record and uncheck one of the checkboxes, its record will be deleted from the many_to_many association table on save.
You can do it like this:
<% MyModel::AS.each do |a_value| %>
<%= f.check_box("a[]", a_value) %>
<% end %>
This will make params come to server as follows
{ :my_model => { :a => [:a_value1, :a_value2] } }
if you already have a select_tag
<%= select_tag "filters", options_from_collection_for_select(filter_values, "id", "name", selected_ids), multiple:true, class:"form-control" %>
and wants to replace it with check_box_tag, you will need to implement something like this:
<div class="checkbox-inline">
<%= check_box_tag "filters[]", value.id, selected_ids.include?(value.id), { :multiple => true} %>
<%= value.name %>
</div>
notice the ending brackets on the name which is needed to catch check box results in the same parameter.
When I implemented this, the parameters were of the same format between the select_tag and the check_box_tag

Rails + Ransack - Drop Down List Collection?

I am loving the ransack gem for its flexibility, however I am unable to get the standard collection_select to function properly. Perhaps someone can assist.
Example:
<%= collection_select(:expense, :project_id, Project.all,
:id, :name, { prompt: 'Select Project'}, { class: 'span4' }) %>
in this case, this code is from an expense entry screen, so the first parameter is the expense object. What should it be in the ransack form? Also, I know I need to get the suffix in there. In this example, I would like project_id_eq to be the search pattern.
Also, my form is on a controller and view called "reports", I am not putting this search in the default controllers.
Thanks!
Seems that this will work.
<%= f.select :project_id_eq, options_from_collection_for_select(Project.all, "id", "name", #search.project_id_eq) %>
If anyone has another suggestion, would love to know it too.
To do this with an include_blank, put it outside of the parentheses:
ex:
<%= f.select :languages_id_eq, options_from_collection_for_select(Language.all, "id", "name"), include_blank: true %>
== UPDATE ==
better yet, use f.collection_select. This way after the user searches for something using the drop down, that option is preselected on the following page:
<%= form.collection_select :vendor_id_eq, Vendor.all, :id, :name, include_blank: true %>

f.collection_select not displaying the selected value

There are so many results for this search on google, and it's even asked at SO - but the solutions discussed so far are not helping me. Here's the issue: I have a form_for #company |f| and I am using f.collection_select for company_status_id - but when the form loads, I want the actual company status selected if it is set. Through the debugger I know, that it's been set, yet I am getting a default value displayed there. Here's the code:
= puts #company.company_status_id
= f.collection_select :company_status_id, ListCache.company_statuses, :id, :name, {:prompt => #select_value}
Here's the generated htmnl
<select id="company_company_status_id" prompt="-Select-" name="company[company_status_id]">
<option value="1">-Not Available-</option>
<option value="2">Active</option>
<option value="3">Bankrupt</option>
<option value="4">Acquired</option>
</select>
And the conditions remain the same even if I do:
f.collection_select :company_status_id, ListCache.company_statuses, :id, :name, {:prompt => #select_value, :selected => :selected => #company.company_status}
Or
f.collection_select :company_status_id, ListCache.company_statuses, :id, :name, {:prompt => #select_value, :selected => #company.company_status}
This is what I finally did:
f.collection_select :company_status_id, ListCache.company_statuses, :id, :name, {:prompt => #select_value, :selected => #company.company_status_id.to_i}
I read on of the answers on a similar question that collection_select automatically selects the selected value by making comparisons of what is passed with the attributes of collection. apparently there was a difference of their types, and comparing the int from CompanyStatus to the int of #company.company_status_id.to_i worked out. Though #company.company_status_id is supposed to be int as well. I can see that in the db. Anyway, it this line of code worked.
If anyone can exaplain, I will be much thankful!
If you use collection_select helper, syntax is very simple:
<%= f.collection_select :category_id, Category.all, :id, :name,
prompt: true, selected: #product.category_id %>
I hope this help
<% form_for(#company) do |f| %>
<%= f.select(:company_status_id, ListCache.all.map {|lc| [lc.name, lc.id]} ) %>
<% end %>
Sometimes you just need to go to the browser address bar and press enter. Normal reloading the page clicking the refresh button doesn't help. My problem was solved that way.
Use select_tag instead
<%= form_for(#product, :html => {:multipart => true}) do |f| %>
<%= select_tag("product[category_id]", options_for_select(#categories.map { |cat| [cat.name, cat.id] })) %>
<%end%>
Hope this help you.....

Rails select list reverts to top?

I have number of select lists in my rails application like this:
<li>Company<span><%= f.select :company_id, Company.all.collect {|m| [m.companyname, m.id]} %></span></li>
They all work well, except - sometimes if you go to the edit view, the select list reverts to the top item, not the item that was chosen when creating. So if you go to an edit view and then click update without actually making any changes, the lists default to the top item - even though you didn't touch them.
Is there a way around this?
Thanks,
Danny
EDIT:
<% form_for (#kase), :html => { :multipart => true } do |f| %>
<li>Appointed Surveyor<span><%= f.select :appointedsurveyor_id, Company.all.collect {|m| [m.companyname, m.id]}, {:selected => #kase.appointedsurveyor_id} %></span></li>
<li>Surveyor Name<span><%= f.select :surveyorperson_id, Person.all.collect { |x| [x.personname, x.id]}, {:selected => #kase.surveyorperson_id} %></span></li>
I have tried the above, but sadly it still seems to revert to the default value.
I'm stuck on this, I can't find any tutorials etc on this at all.
EDIT 2:
<li>Appointed Surveyor<span><%= f.select :appointedsurveyor_id, Company.all.collect {|m| [m.companyname, m.id]}, {:selected => (#kase.appointedsurveyor_id rescue "")} %></span></li>
<li>Surveyor Name<span><%= f.select :surveyorperson_id, Person.all.collect { |x| [x.personname, x.id]}, {:selected => (#kase.surveyorperson_id rescue "")} %></span></li>
You might be able to make sure of it with the third parameter, try the following code:
<li>Company<span><%= f.select :company_id, Company.all.collect {|m| [m.companyname, m.id]}, {:selected => #your_instance_name.company_id} %></span></li>
Make sure that you replace #your_instance_name with the instance variable you use at the form_for tag.
Hopefully that helps.
It turns out I had the fields in the database as strings not integers.

Resources