loop on a select input ruby on rails - ruby-on-rails

I'm trying to make a select input on all my users in ruby on rails, that almost works but the thing is that the don't get the username of my user but i render somethings like this : #<User:0x007f8cc1024d60>
I created 3 users in my console, I can see them while i'm on rails console
I got this in my controller :
def new
#bug = Bug.new
#users = User.all
end
Also my params
def bug_params
params.require(:bug).permit(:owner, :title, :description)
end
And in my html :
<%= form_with model: #bug do |form| %>
<%= form.select :owner, #users %>
<%= form.text_field :title, placeholder: "title" %>
<%= form.text_area :description, placeholder: "description" %>
<%= form.submit %>
<% end %>
Could someone explain me what's wrong ?

With your select form helper, you return only a collection of User instances.
As specified in the documentation, you need to collect what attribute of User you want to pass as option value and option display.
For example:
<%= form.select :owner, #users.collect {|u| [ u.name, u.id ] } %>
#=> output
# <select name="bug[owner]">
# <option value="1">John</option>
# <option value="2">Joe</option>
# </select>

Use collection_select to create a select from a collection of records.
<%= form_with model: #bug do |form| %>
<%= form.collection_select(:owner, #users, :id, :name) %>
<%= form.text_field :title, placeholder: "title" %>
<%= form.text_area :description, placeholder: "description" %>
<%= form.submit %>
<% end %>

Related

Rails Submitting Multiple Has_Many Attributes via Form

I am running a Rails 5.1 app with the following information:
Models
class Company < ApplicationRecord
has_many :complaints
accepts_nested_attributes_for :complaints
validates :name, presence: true
end
class Complaint < ApplicationRecord
belongs_to :company
validates :username, :priority, presence: true
end
Controller
class ComplaintController < ApplicationController
def new
#company = Company.new
#company.complaints.build
end
def create
#company = Company.new(company_params)
respond_to do |format|
if #company.save
format.html { redirect_to complaint_url }
else
format.html { render :new }
end
end
end
private
def company_params
params.require(:company).permit(:name, complaints_attributes: [:username, :priority])
end
Form in view
<%= form_for #company do |f| %>
<%= f.label :name, "Company" %>
<%= f.text_field :name, type: "text" %>
<%= f.fields_for :complaints do |complaint| %>
<%= complaint.label :username, "Username" %>
<%= complaint.text_field :username %>
<%= complaint.label :priority, "Priority" %>
<%= complaint.text_field :priority %>
<% end %>
<%= f.submit 'Submit' %>
<% end %>
If I have just one input field for the complaint_attributes part of the form (in other words just one field for username and one field for priority as shown above), this works just fine.
However, if I want to have multiple fields for username/priority in the form, so that I can submit multiple username/priority combinations in a single submission, I find that submitting the form will only save the last username/priority values from the form. Example of this view would be:
<%= form_for #company do |f| %>
<%= f.label :name, "Company" %>
<%= f.text_field :name, type: "text" %>
<%= f.fields_for :complaints do |complaint| %>
<div>
<%= complaint.label :username, "Username" %>
<%= complaint.text_field :username %>
<%= complaint.label :priority, "Priority" %>
<%= complaint.text_field :priority %>
</div>
<div>
<%= complaint.label :username, "Username" %>
<%= complaint.text_field :username %>
<%= complaint.label :priority, "Priority" %>
<%= complaint.text_field :priority %>
</div>
<% end %>
<%= f.submit 'Submit' %>
<% end %>
I noticed that when submitting the form, I get a hash like this (for submitting single complaint):
{"utf8"=>"✓", "authenticity_token"=>"...", "company"=>{"name"=>"Test", "complaints_attributes"=>{"0"=>{"username"=>"test_person", "priority"=>"1"}}}, "commit"=>"Submit"}
Is there any way to modify the params to make it similar to this and have it saved to the DB?:
{"utf8"=>"✓", "authenticity_token"=>"...", "company"=>{"name"=>"Test", "complaints_attributes"=>{"0"=>{"username"=>"test_person", "priority"=>"1"}"1"=>{"username"=>"test_person", "priority"=>"2"}}}, "commit"=>"Submit"}
Or if not the above, what would be the best way to have the username/priority values saved if using multiple fields for them in a single form?
EDIT: I should point out that I can dynamically add the username/priority field groups as needed, so I don't want to be restricted to a set number.
the second block will override the first fields... you should instead build many complaints in the controller:
def new
#company = Company.new
3.times { #company.complaints.build }
end
and then with the following form it should generate to inputs according to the number of complaints you have built:
<%= form_for #company do |f| %>
<%= f.label :name, "Company" %>
<%= f.text_field :name, type: "text" %>
<%= f.fields_for :complaints do |complaint| %>
<%= complaint.label :username, "Username" %>
<%= complaint.text_field :username %>
<%= complaint.label :priority, "Priority" %>
<%= complaint.text_field :priority %>
<% end %>
<%= f.submit 'Submit' %>
<% end %>

HABTM association dropdown select

I am trying to create a dropdown select on a form. I have a HABTM association between professors and classrooms:
Classroom Model:
class Classroom < ApplicationRecord
has_and_belongs_to_many :professors
end
Professor Model:
class Professor < ApplicationRecord
has_and_belongs_to_many :classrooms
end
Strong Params:
def classroom_params
params.require(:classroom).permit(:name, :professor_ids => [])
end
I am trying to find a way to use f.select instead of select_tag inside the form. But when I do it, the database does not save the values. This way works:
<%= form_for #classroom do |f| %>
<%= f.label :name %><br>
<%= f.text_field :name %><br>
<% array = Professor.all.map { |professor| [professor.user.name, professor.id] } %>
<%= select_tag "classroom[professor_ids][]", options_for_select(array) %>
<% end %>
But I am trying like that and it is not working:
<%= form_for #classroom do |f| %>
<%= f.label :name %><br>
<%= f.text_field :name %><br>
<% array = Professor.all.map { |professor| [professor.user.name, professor.id] } %>
<%= f.select :professor_ids, options_for_select(array) %>
<% end %>
The view works correctly but when I submit the form, the value doesn't go to to the classroom_params. I tried to debug it stopping the controller after the submit and I got this:
The params came correctly with all the information submitted, but the classroom_params came missing the professor_ids.
Is there a way to do this dropdown using f.select?
You whitelisted the array of 'professor_ids', but your 'select' input returns 1 string ("prefessor_ids" => "2" from you screenshot). Maybe you want to set the select as 'multiple'? (I have not tested it, but i think params will be whitelisted correctly after that)
<%= form_for #classroom do |f| %>
<%= f.label :name %><br>
<%= f.text_field :name %><br>
<%= s.collection_select :professor_ids, Professor.all, :id, :name, multiple: true %>
<% end %>
where
class Professor
...
delegate :name, to: :user
end
Update
You probably don't have 'cfg' variable in your controller action.

Rails controller saving from different table

I'm new to rails to bear with me.
This concerns two of my models: Product and Manufacturer.
When creating a new product the user can select which manufacturer the product belongs to from a drop down list. The problem is that I can't get this manufacturer to save.
I know I have to add some code to the controller and I've tried various things but to no avail.
Here's the view:
<h1>New Product</h1>
<%= form_for(#product) do |f| %>
<div>
<%= f.label :name, 'Name' %>
<%= f.text_field :name %>
</div>
<div>
<%= f.label :market_price, 'Market Price' %>
<%= f.text_field :market_price %>
</div>
<div>
<%= f.label :sell_price, 'Sell Price' %>
<%= f.text_field :market_price %>
</div>
<div>
<%= f.label :stock_level, 'Stock Level' %>
<%= f.text_field :stock_level %>
</div>
<div>
<%= f.label :manufacturer, 'Manufacturer' %>
<%= f.collection_select(:manufacturer, Manufacturer.all, :id, :name, prompt: true) %>
</div>
<div>
<%= f.label :location, 'Location' %>
<%= f.collection_select(:location, Product.all, :id, :location, prompt: true) %>
</div>
<br> </br>
<div>
<%= f.submit "Create Product" %>
</div>
And here's part of the controller:
def create
#product = Product.new(params[:product].permit(:name, :market_price, :sell_price, :stock_level, :location))
#product.save
flash[:notice] = 'Product Created'
redirect_to #product
end
end
After hours of trying several nesting methods, I still can't get this to work.
Surely it's very common to save fields from various models on one page???
You would usually nest your routes, so that products were within manufacturer:
resources :manufacturer do
resources :products
end
Then your form would be a form for an array:
form_for([#manufacturer, #product]) do |f|
f.hidden_field :manufacturer_id, value: #manufacturer.id
This allows you to pass in the ID of both the manufacturer and the product.
Now in your controller you can use something like the following, provided the associations are set up, such as product belongs_to :manufacturer and manufacturer has_many :products
#manufacturer = find(params[:manufacturer_id])
#product = #manufacturer.products.create()
In your form, you need to have a field for manufacturer_id, not manufacturer. You would change f.collection_select(:manufacturer to be f.collection_select(:manufacturer_id.
Then, in your controller, you need to add manufacturer_id to the list of parameters you are permitting in your permit method call. So it would be Product.new(params[:product].permit(:name, :market_price, :sell_price, :stock_level, :location, :manufacturer_id)).

Sunspot/Solr : Searching with multiple fields

What is the way to use Sunspot/Solr with mutiple fields ?
It works fine with a simple form, as explained in this screencast : http://railscasts.com/episodes/278-search-with-sunspot
You can see my draft which doesn't work :
product.rb
searchable do
text :address
text :model
text :category
end
*products_controller.rb*
def search
#search = Sunspot.search(Product) do
fulltext params[:address]
with(:model, params[:model]) if params[:model].present?
with(:category, params[:category]) if params[:category].present?
end
#products = #search.results
end
products/search.html.erb
<%= form_tag products_search_path, :method => :get do %>
<div class="field">
<%= label_tag "Address ?" %>
<%= select_tag :address, "<option>he</option><option>ho</option>".html_safe %>
</div>
<div class="field">
<%= label_tag "Model ?" %>
<%= text_field_tag :model, params[:model] %>
<%#= select_tag :model, "<option>hi</option><option>ha</option>".html_safe %>
</div>
<div class="field">
<%= label_tag "Category ?" %>
<%= text_field_tag :category, params[:category] %>
</div>
<div id="buttonSearch"><%= submit_tag "Search" %></div>
<% end %>
The error :
Sunspot::UnrecognizedFieldError (No field configured for Product with name 'model'):
app/controllers/products_controller.rb:99:in `block in search'
app/controllers/products_controller.rb:97:in `search'
Thanks guys for your helping!
You only want this (below)... You only want full text, which will search across all fields you define in searchable... I used "s" as the param name
#search = Sunspot.search(Product) do
fulltext(params[:s])
end
If you setup product.rb like so (specifying :model and :category as non-fulltext string fields that can be used for scoping), then your search code should work verbatim.
# product.rb
searchable do
text :address
string :model
string :category
end

Rails checkboxes

I have a string column in my database which is either "artist" or "listener", and I want the user to be able to choose which string the column is populated with by clicking the appropriate checkbox. How would I do this?
You should use radio button here:
# Imagine it is User model and user_type field
<%= form_for User.new do |f| %>
<%= f.radio_button :user_type, "artist" %>
<%= f.radio_button :user_type, "listener" %>
<% end %>
f.check_box :my_field, {}, "artist", "listener"
This would make my_field be "artist" when it's checked, and "listener" when unchecked.
You should use radio-buttons for that matter. Also make sure to put that logic into the model (validations).
# model
class User
TYPES = %w(artist listener)
validates_inclusion_of :user_type, :in => TYPES
end
# view
<%= form_for :user do |f| %>
<% User::TYPES.each do |type| %>
<%= f.radio_button :user_type, type %>
<% end %>
<% end %>

Resources