I have a Box which has many Items which belongs to a Category.
When the Box is created it has the user_id.
Items has a category_id.
I've seen that if you have a user_id in the table concerned it works okay:
<%= f.collection_select :category_id, Category.where(:user_id => current_user.id), :id , :name %>
But how can I get a Category collection_select from what the current_user has entered - do I have to add a user_id to Categories or can I join my tables somehow?
Maybe this way is easier:
<%= f.collection_select :category_id, current_user.categories, :id, :name %>
PS: Even better if you put this in your controller, so, in case you have to change the select and add some clauses, you will not need to change almost all your views, just the controller (MVC).
Related
I have a working search form built using Ransack with two separate search fields for two different Classes like so:
<%= search_form_for #q do |f| %>
<%= f.label :tags_id_in, 'Tags' %>
<%= f.select :tags_id_in, Tag.all.map{ |u| [u.name, u.id] }, { include_blank: "Tags" } %>
<%= f.label :sector_id_eq, 'Sector' %>
<%= f.select :sector_id_eq, Sector.all.map { |w| [w.name, w.id] }, {include_blank: 'Any'} %>
<%= f.submit "Search" %>
<% end %>
Each of these Classes are linked to a Company Class
class Company < ApplicationRecord
belongs_to :sector
has_many :company_tags
has_many :tags, through: :company_tags
accepts_nested_attributes_for :company_tags
end
I am trying to combine the two select fields into one. So far I can build the view for this like so:
<% combined = Sector.all + Tag.all %>
<%= f.select :combined, combined.map { |w| [w.name, w.id] }.sort, {include_blank: 'Any'} %>
Whilst the above works at displaying a single search form, there is no functionality to it. Can anyone help with this? Thanks in advance.
Hooray, Ransack. It seems like this answer from 2013 is still valid:
Search multiple models at once with Ransack
But if you're adventurous, maybe try this:
https://github.com/activerecord-hackery/ransack/issues/131
You can add associations' columns/ransackers to the list of attributes by passing their names to #attribute_select via the :associations option.
I'm not familiar with ransack, but maybe it's worth creating a new stand-in class? Just a PORO (plain ol' ruby object) go-between for the view and the model, using ransack for your queries rather than calling them directly from the form. You could build the tag list in that object as well.
You've got a lot of logic in your view, many frown on putting ActiveRecord queries there. A form object would fix that, and keep your controller simple as well.
I am building a Rails app that tracks musicians. I want each user to be able to to select multiple genres they like from a form when they create a profile. I want to store it within the "profile" table for the user in the "genre" column. Right now, I have this, but it only allows me to select ONE option. I want the dropdown to allow multiple options. Is that possible? I'm sure this is very simple.
<%= simple_form_for #profile do |f| %>
<%= f.input :genre, collection:['Rock','Blues','Jazz','Classical','Soul','R&B','Alternative', 'Other'], label: "Favorite Genres" %>
Right now, genre is a string. Do I need to pass an array? How would I do that?
There are 2 things you need to do to handle a multi-select with rails.
1) Allowing the user to select multiple options on the form with the {:multiple => true} option.
<%= simple_form_for #profile do |f| %>
<%= f.input :genre, collection:['Rock','Blues','Jazz','Classical','Soul','R&B','Alternative', 'Other'], label: "Favorite Genres", input_html: {:multiple => true} %>
2) Let your controller accept an array of params for the value.
def profile_params
params.require(:profile).permit( :years_spent_playing, :user_id, :name, :bio, :age, :city, :state, :primary_instrument, :second_instrument, :third_instrument, :status, :looking_for, :image, :genre => [])
end
Im not sure your setup but I get the feeling you may not have the proper models and associations setup to handle this in the ideal way. I would suggest looking at adding a has_many :through association and breaking your genres out into a separate model and table.
the relevant part of the new form looks like this:
<%= f.fields_for :event_artists do |fea| %>
<%= fea.collection_select :artist_id, Artist.all, "id", "name", {include_blank: true}, {multiple: true} %>
<% end %>
on the log, you can see that the first item of the array is always blank, even if I didn't select the blank field
"event_artists_attributes"=>{"0"=>{"artist_id"=>["", "2", "5"]}}}
is there a way to fix this? perhaps, make it so that if the blank field is selected, then no actual event_artists can be selected in that case, and vice versa?
The empty artist_id is important. On another form, you may have omitted the artist select altogether, in which case, the artists association should not be affected.
If the artist select is included, and you de-select all artists, the artists need to be removed from the artists association. Normal HTML behavior would not include the artist_id parameter in the PUT at all when nothing is selected. Your controller in that case would think that you do not want to modify the artists association at all.
To solve this, the collection_select includes a hidden field with a blank value to let the controller know that the form intends to alter the artists association. If no artists have been selected, that blank element in the array will ensure all artists are removed from the association.
I think the problem has to do with the order of arguments. I looked at collection_select and tried the following code in an app I'm working on.
<%= collection_select(:category, :category_id, Category.all, :id, :name, {}, {multiple: true}) %>
UPDATE:
<%= fea.collection_select :artist_id, Artist.all, "id", "name", {prompt: true}, {multiple: true} %>
I'm struggling to create a dynamic dropdown box arrangement. Thanks to StackExchange Ruby community, I was able to create the first dropdown box. What I'd like to do, is have the user select a group of banks in a particular state, but keep getting the following error message from my f.grouped_collection_select form: undefined method `map' for "MD":String. I looked at ActionView::Helpers::Forms and this video, but nothing seems to work. Any help you could provide would be greatly appreciated. I think I also have to add jquery code too? Here is my current view code:
<%= form_for #boli do |f| %>
<%= f.label :state %>
<%= f.collection_select :state, (Boli.order(:state).select("DISTINCT ON (state) id, state")), :id, :state, include_blank: true %>
<div>
<%= f.label :bank %>
<%= f.grouped_collection_select :bank, Boli.order(:bank), :state, :name, :id, :name, include_blank: true %>
</div>
<% end %>
You need to group banks by state. This implies that there is either a one-to-many (one state to many banks) or a many-to-many relationship between them.
The one-to-many relationship implies Bank is a model that either has state as an attribute or references another model State.
The many-to-many relationship implies that both Bank and State are models joined by another table.
With both bank and state as attributes of another model it's unfeasible to model the relationship between them.
In order to use grouped_collection_select you should have both as models.
In the Rails Tutorial there is a great chapter on creating a toy app with users and microposts. However, when editing the microposts, I can only edit user_id which is a numeric value, not user name. Is there a simple way to enforce displaying user's name instead of user's id in the app?
I've looked app/views/microposts/_form.html.erb and it says:
<div class="field">
<%= f.label :user_id %><br>
<%= f.number_field :user_id %>
</div>
What should I change to be able to select the users by name instead of the id?
Try using a select helper rather than a number_field.
<%= f.collection_select(:user_id, #users, :id, :first_name) %>
In your controller, you'd need the following line (or something similar):
#users = User.all
If you want to display each user's full name, you'd need to create a method in user.rb to concatenate first and last names, like so:
def fullname
fullname = "#{last_name}, #{first_name}"
end
Your select would then use the method name, like this:
<%= f.collection_select(:user_id, #users, :id, :fullname) %>
You should probably take some time to read up on all the different form helpers.
The feature you're looking for is called a collection_select. http://apidock.com/rails/ActionView/Helpers/FormOptionsHelper/collection_select
f.collection_select :user_id, User.all, :id, :username