Displaying and selecting from a HABTM - ruby-on-rails

Currently I have a Category and Post model, joined by a HABTM relationship.
Posts belong to multiple categories and have many attributes.
Categories just have a Name Property.
How do I create a multi-select form in my Posts _form.html.erb so I can select which categories I want the post to be assigned to?

<%= form_for #post do |f| %>
<div>
<%= f.label :category_ids, "Categories" %><br />
<%= f.collection_select :category_ids, Category.order(:name), :id, :name, {}, {multiple: true} %>
</div>
<div>
<%= f.submit 'Submit' %>
</div>
<% end %>

Try using select and collection. You may have to change the collection, not sure exactly what Category options you want to be able to choose from. Something like this:
<%= f.input :post, as: :select, collection: Category.posts, include_blank:false %>
Or checkout out the collection_select form helper method
http://api.rubyonrails.org/classes/ActionView/Helpers/FormOptionsHelper.html#method-i-collection_select

Related

Rails delete multiple objects checkboxes with fields_for

I have two models - Campaigns & Cities (belongs to Campaign). On the create and edit form for Campaign I'm using fields_for to allow users to edit cities directly on the campaign edit page. I want to add a checkbox for each city, so that their ids will be sent in an array (delete_cities) in the params.
My attempt at it:
<%= f.fields_for :cities do | city_form | %>
<%= city_form.label :name %>
<%= city_form.text_field :name%>
<%= city_form.label :phone_number %>
<%= city_form.text_field :phone_number %>
<%= city_form.label :zip_code %>
<%= city_form.text_field :zip_code %>
<%= city_form.check_box :delete_cities %>
</br>
<% end %>
I cant solve this any help is appeciated.
According to the docs:
:allow_destroy
If true, destroys any members from the attributes hash with a _destroy key and a value that evaluates to true (eg. 1, '1', true, or 'true'). This option is off by default.
In order to allow users to delete cities, you can do like this:
<%= city_form.check_box :_destroy %>
And don't forget to permit :_destroy in the controller:
params.require(:campaign).permit(cities_attributes: [:id, :_destroy])

create record based on collection_select dropdown

I am trying to create playlist records based on the dropdown selection. I'm going to put this in a bootstrap divided dropdown once functional. For now I have a dropdown and a link. The link does the thing, creates a new playlist obj with the values from the video it was clicked on, everything is a PORO until added as a playlist obj, where the video is persisted to the DB as a video obj. What I am wanting to do is, if you want to add a video to as a playlist obj, that you see a list of associated playlist names. When you click on the name, it does the same thing as the link_to but takes the name parameter along with it to create the new record. Thanks for any help.
PS. if you have tips on implementing the bootstrap that'd be wicked helpful too :D
<%= form_tag :playlists, {action: 'create'} do %>
<%= collection_select :playlist, :name, current_user.playlists, :id, :name, class: 'dropdown-item' %>
<%= link_to 'Create Playlist', new_playlist_path(etag: video.etag, video_id: video.video_id, user_id: current_user.id,
img_high: video.img_high, img_default: video.img_default,
title: video.title, description: video.description), class: 'dropdown-item' %>
<% end %>
Basically, what I'm trying to do is...be able to do what the link_to is doing but also take along the playlist name
Bind to the onchange event of the the select and trigger it's form to submit.
<%= collection_select :playlist, :name, current_user.playlists, :id, :name, class: 'dropdown-item', onchange: "this.form.submit()" %>
Here's an example:
<form action="https://google.com/">
<select name="q" onchange="this.form.submit()">
<option value="abc">Option 1</option>
<option value="123">Option 2</option>
</select>
</form>
Was finally able to get the passing the params, I still have to use a button as couldn't get the onchange: to work yet.
<%= form_tag :playlists, {action: 'create'} do %>
<%= hidden_field_tag :etag, video.etag %>
<%= hidden_field_tag :video_id, video.video_id %>
<%= hidden_field_tag :img_high, video.img_high%>
<%= hidden_field_tag :img_default, video.img_default %>
<%= hidden_field_tag :title, video.title %>
<%= hidden_field_tag :published_at, video.published_at %>
<%= hidden_field_tag :description, video.description %>
<%= hidden_field_tag :user_id, current_user.id %>
<%= collection_select :playlist, :name, current_user.playlists, :name, :name, {class: 'dropdown-item', onsubmit: 'this.form.submit()'} %>
<%= submit_tag 'Add', method: 'post' %>
Wasn't aware I could use the hidden_field_tag there like that :P

To store the value of the check box and radio button in the database ruby on rails

rails generate scaffold Post title:string body:text category_id:integer status_id:integer
generated the scaffold like this. category_id and status_id is used for check-box and radio button
Here the value are stored as a integer values like category 1 or 2 but i need to store the value of the category like tv or mobile in the database because we can not understand what product is required .
thank you in advance
<%= f.label :title %>
<%= f.text_field :title %>
<%= f.label :body %>
<%= f.text_area :body %>
<%= f.label :category_id %>
<%= f.select :category_id, options_from_collection_for_select(Category.all, :id, :name, #post.category_id) %>
<%= f.label :status_id %>
<%= collection_radio_buttons(:post, :status_id, Status.all, :id, :name) %>
<%= f.submit %>
link is here i followed those steps
You shouldn't store the text value because it already in the Category table.
if you want to know what product is, you can use #product.category.try(:name) if associations setup correctly

How to organize form_for helper to show data from different models?

I have three models PriceGroup, PriceGroupLine and Item.
PriceGroup has fields - :id and :name.
Item has fields - :id and :name.
PriceGroupLine has fields - :id, :price_group_id, :item_id, :price
Associations:
PriceGroup has_many PriceGroupLines
Item has_one PriceGroupLine
PriceGroupLine belongs_to Item
PriceGroupLine belongs_to PriceGroup
I need to insert in PriceGroupLine model lines from PriceGroup show view. How I should organize form_for helper if I need to insert in PriceGroupLine:
item_id - items list organized with collection_select helper
price_group_id
price of item
I am using this code on view but I am not able to insert it:
<%= form_for #price_group, html: {class: "form-inline"} do |f| %>
<div class="form-group">
<label>Товар</label>
<%= f.collection_select(:id, Item.all, :id, :name, {}, {class: "form-control"}) %>
</div>
<div class="form-group">
<label>Цена</label>
<%= f.text_field :price, class: "form-control" %>
</div>
<%= f.submit "Добавить", class: "btn btn-default" %>
<% end %>
And one more question about the associations. At the beginning i had associations like:
PriceGroup has_many PriceGroupLines
PriceGroupLine has_many Items
Item belongs_to PriceGroupLine
PriceGroupLine belongs_to PriceGroup
But this associations didn't work correctly when i tried to get :name field from Item model like this:
<% #price_group.price_group_lines.each do |price_group_line| %>
<%= price_group_line.item.try(:name) %>>
<%= price_group_line.price %>
<% end %>
I changed associations and all worked. Now PriceGroupLine belongs_to :item and Item has_one :price_group_line. But it is logical to assume that ITEM is belongs to PriceGroupLine (PRICEGROUPLINE contains ITEM). Am I wrong?
UPDATE
Almost there :)) Here is a screenshot of my form.
Code of show view PriceGroup:
<%= form_for #price_group, html: {class: "form-inline"} do |f| %>
<%= f.fields_for :price_group_lines do |price_group_line| %>
<%= render partial: "price_group_line_fields", locals: { f: price_group_line } %>
<% end %>
.links
<%= link_to_add_association "Добавить", f, :price_group_lines %>
<% end %>
Code of partial:
<div class="form-group">
<label>Товар</label>
<%= f.collection_select(:item_id, Item.all, :id, :name, {}, {class: "form-control"}) %>
</div>
<div class="form-group">
<label>Цена</label>
<%= f.text_field :price, class: "form-control" %>
</div>
In footer Helper makes fields for each record in database. I need only items list to select a proper item and blank field PRICE to enter the price. And some word .link appears.
First of all you will be needing nested form for this. Using the nested form you will be able to insert multiple price_group_lines from price_group form. I would suggest you to use gem like Cocoon for this. What you need to do is:
In form:
<%= form_for #price_group, html: {class: "form-inline"} do |f| %>
<%= f.fields_for :price_group_lines do |price_group_line| %>
<%= render 'price_group_line_fields', f: price_group_line %>
<% end %>
<div class='links'>
<%= link_to_add_association 'add price group line', f, :price_group_lines %>
</div>
<% end %>
In price_group_line_fields:
<div class="form-group">
<label>Товар</label>
<%= f.collection_select(:item_id, Item.all, :id, :name, {}, {class: "form-control"}) %>
</div>
<div class="form-group">
<label>Цена</label>
<%= f.text_field :price, class: "form-control" %>
</div>
And in your controller you will need to allow this in strong parameters:
params.require(:price_group).permit(:name, :price_group_lines_attributes => [:item_id, :price])
And in you PriceGroup model you need to write:
accepts_nested_attributes_for :price_group_lines
This is just a example and rough code using cocoon gem, you can find more options by searching rails nested form. The code may throw error which you can easily fix.
Hope this helps.

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)).

Resources