Rails - Dynamic Select - Collection Select - ruby-on-rails

I've been trying to get some dynamic select functionality working, but despite many different tutorial i've yet to get it to work. For ease of reading, i've brought the code examples down to basics. Any advise would be greatly appreciated.
On the faults page, i need to assign a company and contact to the fault, but I only want to be able to see the contacts associated with the selected company
Fault - belongs_to :company, :user, :contact
User - has_many :faults
Contacts - has_and_belongs_to_many :companies
Company - has_and_belongs_to_many :contacts, has_many :faults
/faults/_form.html.erb
<%= f.label :company, "Company:" %>
<%= collection_select(:fault,:company_id,#companies,:id,:full_name, :prompt => "Please select a company") %></br>
<%= f.label :contact, "Contact:" %>
<%= f.collection_select :contact_id, #contacts, :id, :name, :prompt => "Select a Contact" %>
<%= link_to "Add New Contact", {:controller => "companies", :action => "index"}, :confirm => "To add a contact for a company you need to do this from the companies page." %></br>

Gotcha. Using UJS you can dynamically populate your select in 5 steps.
Add class names to your selects in the view
Add JavaScript (or CoffeeScript) to watch the changes on the select element
Create a controller method to fetch the info you need based on your selection
Add a route to match your new controller method
Create a UJS view to update your contacts select
So,
Add class names:
<%= f.label :company, "Company:" %>
<%= collection_select(:fault,:company_id,#companies,:id,:name, {:prompt => "Please select a company"}, {:class => "company_selection"}) %>
<%= f.label :contact, "Contact:" %>
<%= f.collection_select :contact_id, #contacts, :id, :name, {:prompt => "Select a Contact"}, {:class=>"contact_selection"} %>
Throw in some CoffeeScript (app/assets/javascripts/faults.js.coffee)
$(document).ready ->
$(".company_selection").on "change", ->
$.ajax
url: "/faults/get_contacts"
type: "GET"
dataType: "script"
data:
company_id: $('.company_selection option:selected').val()
Update your faults controller
def get_contacts
#company = Company.find params[:company_id]
#contacts = #company.contacts
end
Add a route to your new method
resources :faults do
collection do
get 'get_contacts', to: "faults#get_contacts"
end
end
Add the UJS file (app/views/faults/get_contacts.js.erb)
$('.contact_selection').empty();
$('.contact_selection').append( $('<option>Select the Contact</option>'));
<% #contacts.each do |contact| %>
$('.contact_selection').append($('<option value="<%= contact.id %>"><%= contact.name %></option>'));
<% end %>

Vanilla JS Option
This can be achieved with vanilla javascript only. Make sure that there is a route at companies/[id]/contacts.json which returns correct data.
const select = document.querySelector('#company_id');
select.addEventListener('change',function(e) {
axios.get(`/companies/${e.target.value}/contacts.json`)
.then((res) => {
let contactSelect = document.querySelector('#contact_id')
contactSelect.innerHTML = ''
res.data.map((model, i) => {
contactSelect.options[i] = new Option(model.name, model.id);
})
})
});

Related

Rails - Multiple Select Update all objects of model

I have a 'country' model in my app with attributes name and status. If a country is activated, its status will be 1. Admin type of user can toggle this so I have given a multiple select dropdown for the same. My problem, how to update all the selected/unselected countries at one hit of submit button ?
My form on settings page for Admin user -
<%= simple_form_for #country do |form| %>
<%= form.collection_select :name, Country.order(:name), :id, :name, {:selected => #selected}, {:multiple => true, :class =>"ui fluid selection dropdown"} %>
<%= form.submit 'Submit' %>
<% end %>
Controller -
def settings
#country = Country.new
#selected = Country.where(status: '1').pluck(:id)
end
And the script -
<script>
$(document).on('turbolinks:load', function() {
$('.ui.dropdown').dropdown();
});

Rails - Show objects related to user in form dropdown

In my rails application the following relationships exist:
user belongs_to :team ,
element belongs_to :team ,
task belongs_to :element
A user can then create a task which belongs to an element.
When a user is creating a task, they can select the element they would like the task to belong to. How do I show only the elements that belong to the current_user's team? I am using Devise to get the current_user.
The samples below do not work.
<div class="field">
<%= form.label :element_id %>
<%= form.select :element_id, options_for_select(Element.current_user.team_id.map{|s|[s.title, s.id]}),{ :multiple => true} %>
</div>
I also tried to call the method below from the tasks_controller.rb file but it didnt work either
def new
#task = Task.new
#tasks_element_dropdown = Element.current_user.team_id.map{|s|[s.title, s.id]}
end
In the tasks/_form.html.erb file, I called the method with the code below
<%= form.select :element_id, options_for_select(#tasks_element_dropdown),{ :multiple => true} %>
When I tried the example below it does work but it displays all elements, and I only want the elements that belong to the user's team to display
<div class="field">
<%= form.label :element_id %>
<%= form.select :element_id, options_for_select(Element.all.map{|s|[s.title, s.id]}),{ :multiple => true} %>
</div>
The problem is in the following code, which should return the elements:
Element.current_user.team_id.map{|s|[s.title, s.id]}
Since you have a user, you can get the team: current_user.team
And then get the elements of the team (as long as has_many :elements is defined in the Team class): current_user.team.elements
Thus, the final code should be something like:
<div class="field">
<%= form.label :element_id %>
<%= form.select :element_id, options_for_select(current_user.team.elements.map{ |s| [s.title, s.id] }),{ :multiple => true} %>
</div>

Rails Search and add filters to the search - geocoder

I would like some advices on the way to add a filter , on my search form with geocoder.
I got a User model and Animal model (animals got a Type argument)
And a join table : Animal_User with Animal_ID / User_ID)
Right now, I can locate Users around a city with the choice of Kilometers around that city.That's working fine.
I would like to add the filter on the type of animal, that would be great :)
Search would look like this : London > 10KM > Filter on Type : dogs
Many thanks in advance if you have a glimpse of an idea on how to do that. You will find the search html and the controller. If you need User Model or Animal model i can post it too ( it's really standard Has_many / has_many though association)
search.html.erb
<div class="search-bar">
<%= form_tag search_path, :class => "webdesigntuts-workshop", method: :get do %>
<%= label :user, "" %>
<%= text_field_tag :city, params[:city], placeholder: 'City', :input_html => { :value => 'Paris' } %>
<%= label :distance, "" %>
<%= text_field_tag :distance, params[:distance], placeholder: 'km', :input_html => { :value => '10' } %>
<%= submit_tag "Search" %>
<% end %>
</div>
search controller
class SearchsController < ApplicationController
def search
if params[:city].present?
#searchs = User.near(params[:city], params[:distance] || 10).where("id != ?", current_user.id)
else
#searchs = User.all.where("id != ?", current_user.id)
end
end
end
Try this, I'm basing it on Active Record Querying:
User.joins(:animals).where(id: current_user.id, animals: {type: params[:animal_type]}).near(params[:city], params[:distance] || 10)
This assumes that your User model has_many :animals (being able to write Rails models DSL like this is awesome)

How do I select a car make and then select model according to make?

In my rails project I have two models, Car Make & Car Model, with a 1:M relationship (i.e. one Audi has many Audi models).
In my Views page, I want a form with two input fields for car make & car model. Ideally, I will be able to input a car make (i.e. Audi) and the second input field will have a drop down menu with all the models available for the make (2016 Audi A6, 2017 Audi A7).
I've set up all the relations and in the models I have saved a foreign key of the make.
currently in _form.html.erb I have
<div class="field">
<%= f.label :make_id, "Make:"%><br>
<%#= f.number_field :make_id %>
<%= f.collection_select :make_id, Make.all,
:id,:makes_info, {:include_blank => 'Please Select'} %>
</div>
<div class="field">
<%= f.label :model_id, "Model:" %><br>
<%= f.collection_select :model_id, Model.all,
:id,:model_info, {:include_blank => 'Please Select'} %>
</div>
If you want it to truly be dynamic, you would need to use an AJAX request to update the second select after the first is picked. You'd also need to use the options_for_select method inside of the select tag
Some more info to accompany what was already provided.
It's known as dynamic select boxes:
#config/routes.rb
resources :makes do
get :models, on: :collection #-> url.com/makes/models
end
#app/controllers/makes_controller.rb
class MakesController < ApplicationController
def models
#make = Make.find(params[:make][:make_id])
respond_to do |format|
format.js
end
end
end
#app/views/makes/models.js.erb
$select = $("select#models");
$select.empty();
<% #make.models.each do |model| %>
$select.append($('<option>').text(<%=j model.name %>).attr('value', <%= model.id %>));
<% end %>
#views
<%= f.collection_select :make_id, Make.all, :id, :makes_info, {include_blank: 'Please Select'}, { data: { remote: true, url: make_models_path }} %>
<%= f.collection_select :model_id, Model.all, :id,:model_info, {include_blank: 'Please Select'}, { id: "models" } %>

Drop down list form validation alert in ruby on rails

I have drop down list and two radio button in a form.here is the code.i dont know how to set validations in controller.when not selecting value from drop down and one of the radio button,i have to show the warning messages 'please select value from dropdown' and check one radio button filed.how it is possible in ruby on rails while submitting a form.
<%= form_tag :action => 'show' do %>
<strong>Select device: </strong> <%= collection_select(:device, :id, #devices, :id, :name, options ={:prompt => "-Select a device"}) %>
<br></br>
<strong>Chose: </strong><%= radio_button_tag :name,:time, false, :onclick => "this.parentNode.submit();"%>Time
<%= radio_button_tag :name,:graph%>Graph
<% end %>
In device.rb i set the following but not showing any messages.
class Device < ActiveRecord::Base
attr_accessible :name
validates_presence_of :name
has_many :properties
def validate
if name == 'None'
errors.add_to_base("You must select a device name")
end
end
end
Why not use a validates_exclusion_of ? (or its equivalent in Rails 3)
http://apidock.com/rails/v2.3.8/ActiveModel/Validations/ClassMethods/validates_exclusion_of

Resources