select values in a form not getting submitted - ruby-on-rails

I'm not exactly sure what I'm missing, when I use the dev tools the form shows up properly in the html but the only value that is not being submitted it the one in the drop down.
I looked at my database and it's not submitting any value at all what am I doing wrong, I posted my code below.
******************the form********************
= form_for #menu_price do |f|
- if #menu_price.errors.any?
#error_explanation
h2 = "#{pluralize(#menu_price.errors.count, "error")} prohibited this menu_price from being saved:"
ul
- #menu_price.errors.full_messages.each do |message|
li = message
.form-group
= f.label Category
= f.select :category_id, options_for_select( #categories_options),{prompt: "Select a category"}
.form-group
= f.label :price
= f.number_field :price
.form-group
= f.label :description
= f.text_field :description
.form-group
= f.label :serves
= f.text_field :serves
= f.submit
= link_to 'Back', menu_prices_path, class:'button'
******************Controller******************
class MenuPricesController < ApplicationController
before_action :set_menu_price, only: [:show, :edit, :update, :destroy]
def index
#menu_prices = MenuPrice.all
end
def show
#categories = Category.all
end
def new
#menu_price = MenuPrice.new
#categories_options = Category.all.map{|u| [ u.name, u.id ] }
end
def edit
#categories_options = Category.all.map{|u| [ u.name, u.id ] }
end
def create
#menu_price = MenuPrice.new(menu_price_params)
respond_to do |format|
if #menu_price.save
format.html { redirect_to #menu_price, notice: 'Menu price was successfully created.' }
format.json { render :show, status: :created, location: #menu_price }
else
format.html { render :new }
format.json { render json: #menu_price.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #menu_price.update(menu_price_params)
format.html { redirect_to #menu_price, notice: 'Menu price was successfully updated.' }
format.json { render :show, status: :ok, location: #menu_price }
else
format.html { render :edit }
format.json { render json: #menu_price.errors, status: :unprocessable_entity }
end
end
end
def destroy
#menu_price.destroy
respond_to do |format|
format.html { redirect_to menu_prices_url, notice: 'Menu price was successfully destroyed.' }
format.json { head :no_content }
end
end
private
def set_menu_price
#menu_price = MenuPrice.find(params[:id])
end
def menu_price_params
params.require(:menu_price).permit(:category, :price, :description, :serves)
end
end

You need to whitelist category_id not category.Change your menu_price_params to
def menu_price_params
params.require(:menu_price).permit(:category_id, :price, :description, :serves)
end

In your view you have
= f.select :category_id
while in your MenuPricesController you have
params.require(:menu_price).permit(:category, ..)
Just change the :category to :category_id

Related

I have the same form in two pages and i need to redirect to the same page of the form

My problem
I have two forms for one model on two different pages (opinions and user) when I click submit the form on the user page it redirects me to the opinions page, I know that I can redirect to the same page that I redirect in the action create but is there a way to redirect user form to the user page
User controller
class UsersController < ApplicationController
include TheUser
before_action :set_user
before_action :authenticate_user!
before_action :user_signed_in?
def index
#users = User.all
#mutual_friends = User.where(id: show_two_friends)
end
def show
#user = User.find(params[:id])
#new_opinion = Opinion.new
respond_to do |format|
if #user
format.html
format.js
format.json { render :show, status: :created, location: #user }
else
format.html { render :new }
format.json { render json: #user.errors, status: :unprocessable_entity }
format.js
end
end
end
private
def show_mutual_friends
#ids = []
current_user.friends.each do |person|
person.friends.each do |m|
#ids << m.id
end
end
#ids.reject { |x| x == current_user.id }
end
def show_two_friends
show_mutual_friends.sample(2)
end
end
Opinions controller
class OpinionsController < ApplicationController
include TheUser
before_action :set_user
before_action :set_opinion, only: [:show, :edit, :update, :destroy]
# GET /opinions
# GET /opinions.json
def index
#opinions = Opinion.all.order("created_at DESC")
#opinion = Opinion.new
end
# POST /opinions
# POST /opinions.json
def create
#opinion = #user.opinions.build(opinion_params)
respond_to do |format|
if #opinion.save
format.html { redirect_to opinions_url, notice: 'Post was successfully created.' }
format.json { render :show, status: :created, location: #opinion }
else
format.html { render :new }
format.json { render json: #opinion.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /opinions/1
# PATCH/PUT /opinions/1.json
def update
respond_to do |format|
if #opinion.update(opinion_params)
format.html { redirect_to #opinion, notice: 'Opinion was successfully updated.' }
format.json { render :show, status: :ok, location: #opinion }
else
format.html { render :edit }
format.json { render json: #opinion.errors, status: :unprocessable_entity }
end
end
end
# DELETE /opinions/1
# DELETE /opinions/1.json
def destroy
#opinion.destroy
respond_to do |format|
format.html { redirect_to opinions_url, notice: 'Opinion was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_opinion
#opinion = Opinion.find(params[:id])
end
# Only allow a list of trusted parameters through.
def opinion_params
params.require(:opinion).permit(:user, :body, :user_id)
end
end
User form
<%= form_with(model: #new_opinion, local: false) do |form| %>
<div class="field rich p-3">
<div class="control">
<%= form.rich_text_area :body, label: "What's Your Opinion", input_html: {class: "textarea"}, wrapper: false, label_html: {class: "label"}, placeholders: "Your opinion...", autofocus: true %>
</div>
</div>
<%= form.button :submit %>
<% end %>
Opinions form
<%= form_with(model: #opinion, local: true) do |form| %>
<div class="field rich p-3">
<div class="control">
<%= form.rich_text_area :body, label: "What's Your Opinion", input_html: {class: "textarea"}, wrapper: false, label_html: {class: "label"}, placeholders: "Your opinion...", autofocus: true %>
</div>
</div>
<%= form.button :submit, class: "button is-info" %>
<% end %>
I will really appreciate it if you guys help me with this it's my final project
The solution is by adding a hiddin_field_tag and redirect each form to the desired path like this:
<%= form_with(model: #new_opinion, local: true) do |form| %>
<div class="field rich p-3">
<div class="control">
<%= form.rich_text_area :body, label: "What's Your Opinion", input_html: {class: "textarea"}, wrapper: false, label_html: {class: "label"}, placeholders: "Your opinion...", autofocus: true %>
</div>
</div>
<%= hidden_field_tag(:redirect_url, user_path(#user.id)) %>
<%= form.button :submit %>
<% end %>
And redirect the create action in the controller to the params
def create
#opinion = #user.opinions.build(opinion_params)
respond_to do |format|
if #opinion.save
format.html { redirect_to(params[:redirect_url]) }
format.json { render :show, status: :created, location: #opinion }
else
format.html { render :new }
format.json { render json: #opinion.errors, status: :unprocessable_entity }
end
end
end
Rails 5 has redirect_back
& Then change
redirect_to opinions_url
to
redirect_back(fallback_location: root_path)

rails: nested resources saving empty records

I have created a simple form of nested resources. I can't get the child form todo_item to save correctly. When I click the "create todo item" button, an empty record will be created and saved no matter what I put in the title field.
The code is really simple and the parent record is saving fine. the child records are displaying so I can't figure out what could be wrong. Please help.
My models:
class TodoItem < ActiveRecord::Base
belongs_to :todo_list
end
class TodoList < ActiveRecord::Base
has_many :todo_items, dependent: :destroy
end
My controllers:
class TodoItemsController < ApplicationController
before_action :set_todo_list
before_action :set_todo_item, only: [:show, :edit, :update, :destroy]
def new
#todo_item = #todo_list.todo_items.new
end
def create
#todo_item = #todo_list.todo_items.new
respond_to do |format|
if #todo_list.save
format.html { redirect_to #todo_list, notice: 'Todo item was successfully created.' }
format.json { render :show, status: :created, location: #todo_list }
else
format.html { render :new }
format.json { render json: #todo_list.errors, status: :unprocessable_entity }
end
end
end
private
def set_todo_item
#todo_item = #todo_list.todo_items.find(params[:id])
end
def set_todo_list
#todo_list = TodoList.find(params[:todo_list_id])
end
def todo_item_params
params.require(:todo_item).permit(:title, :due_date, :description, :text, :completed)
end
end
View.html.erb:
<h1>New Todo Item</h1>
<%= render 'form' %>
<%= link_to 'Back', #todo_list %>
_form.html.erb:
<%= form_for([#todo_list, #todo_item]) do |f| %>
...
<div class="field">
<%= f.label :title %><br>
<%= f.text_field :title %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
You initialize the #todo_item here:
def create
#todo_item = #todo_list.todo_items.new # <===== INITIALIZED HERE
respond_to do |format|
if #todo_list.save # <===== SAVED HERE WITHOUT EVER ASSIGNING VALUES.
format.html { redirect_to #todo_list, notice: 'Todo item was successfully created.' }
format.json { render :show, status: :created, location: #todo_list }
else
format.html { render :new }
format.json { render json: #todo_list.errors, status: :unprocessable_entity }
end
end
end
But, don't provide any arguments to new. So, the new record has no values.
Instead, do something more like:
#todo_item = #todo_list.todo_items.new(todo_item_params)
Perhaps you should also add some validations so you could avoid this situation.
You need to modify the create method:
def create
#todo_item = #todo_list.todo_items.create(todo_item_params)
respond_to do |format|
if #todo_list.save
format.html { redirect_to #todo_list, notice: 'Todo item was successfully created.' }
format.json { render :show, status: :created, location: #todo_list }
else
format.html { render :new }
format.json { render json: #todo_list.errors, status: :unprocessable_entity }
end
end
end

Couldn't find Tray with 'id'=

Im creating a garden app that has trays and plants.
tray has_many plants, plant belongs_to tray etc.
Im getting the above error and Im not sure how to assign the tray_id to the new plant being created.
Here is the add plant button in my tray's show view
<%= link_to 'ADD PLANT', new_plant_path(#tray.id), class: "btn btn-raised btn-success hoverable" %>
Here is my plants_controller:
class PlantsController < ApplicationController
before_action :set_plant, only: [:show, :edit, :update, :destroy]
# GET /plants
# GET /plants.json
def index
#plants = Plant.all
end
def show
end
def new
#plant = Plant.new
end
def edit
end
def create
tray = Tray.find(params[:tray_id])
#plant = tray.plants.create(plant_params)
respond_to do |format|
if #plant.save
format.html { redirect_to #plant, notice: 'Plant was successfully created.' }
format.json { render :show, status: :created, location: #plant }
else
format.html { render :new }
format.json { render json: #plant.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #plant.update(plant_params)
format.html { redirect_to #plant, notice: 'Plant was successfully updated.' }
format.json { render :show, status: :ok, location: #plant }
else
format.html { render :edit }
format.json { render json: #plant.errors, status: :unprocessable_entity }
end
end
end
def destroy
#plant.destroy
respond_to do |format|
format.html { redirect_to plants_url, notice: 'Plant was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_plant
#plant = Plant.find(params[:id])
end
def plant_params
params.require(:plant).permit(:title, :notes, :category_id, :tray_id, images_files: [])
end
end
Here is my trays controller
class PlantsController < ApplicationController
before_action :set_plant, only: [:show, :edit, :update, :destroy]
def index
#plants = Plant.all
end
def show
end
def new
#plant = Plant.new
end
def edit
end
def create
tray = Tray.find(params[:tray_id])
#plant = tray.plants.create(plant_params)
respond_to do |format|
if #plant.save
format.html { redirect_to #plant, notice: 'Plant was successfully created.' }
format.json { render :show, status: :created, location: #plant }
else
format.html { render :new }
format.json { render json: #plant.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #plant.update(plant_params)
format.html { redirect_to #plant, notice: 'Plant was successfully updated.' }
format.json { render :show, status: :ok, location: #plant }
else
format.html { render :edit }
format.json { render json: #plant.errors, status: :unprocessable_entity }
end
end
end
def destroy
#plant.destroy
respond_to do |format|
format.html { redirect_to plants_url, notice: 'Plant was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_plant
#plant = Plant.find(params[:id])
end
def plant_params
params.require(:plant).permit(:title, :notes, :category_id, :tray_id, images_files: [])
end
end
Here is my form for creating new plants
<%= form_for(#plant) do |f| %>
<%= f.label 'NAME' %>
<%= f.text_field :title, class: 'form-control', id: 'focusedInput1', placeholder: 'ENTER NAME' %>
etc, etc
<% end %>
What am I doing wrong? Thanks for the help :)
The params[:tray_id] is nil on this line tray = Tray.find(params[:tray_id]) in your Posts controller.
You're also not passing tray_id anywhere in your params. You'll need to properly pass it as a param to your new action:
<%= link_to 'ADD PLANT', new_plant_path(tray_id: #tray.id), class: "btn btn-raised btn-success hoverable" %>
Then add a hidden field to pass :tray_id in your form:
<%= f.hidden_field :tray_id, value: params[:tray_id] %>
Now, you can find tray in your create action using tray = Tray.find(params[:plant][:tray_id]).

Simple-Form input :collection does not highlight field when error is raised

I have a problem with simple form it doesn’t highlight field where error is raised.
search_controller.rb
class SearchesController < ApplicationController
before_action :set_search, only: [:show, :edit, :update, :destroy]
layout 'admin'
def index
#searches = Search.includes(:brand, :search_index, :price_ranges)
end
def show
end
def new
#search = Search.new
end
def edit
end
def create
#search = Search.new(search_params)
respond_to do |format|
if #search.save
format.html { redirect_to #search, notice: 'Search was successfully created.' }
format.json { render :show, status: :created, location: #search }
else
format.html { render :new }
format.json { render json: #search.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #search.update(search_params)
format.html { redirect_to searches_url, notice: 'Search was successfully updated.' }
format.json { render :show, status: :ok, location: #search }
else
format.html { render :edit }
format.json { render json: #search.errors, status: :unprocessable_entity }
end
end
end
def destroy
#search.destroy
respond_to do |format|
format.html { redirect_to searches_url, notice: 'Search was successfully destroyed.' }
format.json { head :no_content }
end
end
private
def set_search
#search = Search.find(params[:id])
end
def search_params
params.require(:search).permit(:brand_id)
end
end
search.rb
class Search < ActiveRecord::Base
validates_presence_of :brand
_form.html.erb
<%= simple_form_for(#search) do |f| %>
<%= f.error_notification %>
<%= f.input :brand_id, collection: Brand.all.order(:name), prompt: 'Select brand' %>
<% end %>
I want brand field be hihlighted the same way keywords field is.
I've checked if validates_presence_of brand raise the error and it dose, but doesn’t highlight the field.

Why no error with unassigned variable?

I have a pupils model and a groups model. When adding a new pupil I have a collection_select box with :multiple=> true so that the pupil can be put into several groups.
<div class="field">
<%= f.label "All Groups" %><br />
<%= collection_select(:groups, :id, #all_groups,
:id, :name, {},
{:multiple => true}) %>
</div>
I have an edit pupil form that when loaded selects the groups the pupil was previously assigned so that they can be changed if needs be so has the extra bit in {} in the collection select options;
<div class="field">
<%= f.label "All Groups" %><br />
<%= collection_select(:groups, :id, #all_groups,
:id, :name, {selected: #previous_selection},
{:multiple => true}) %>
</div>
the #previous_selection is set in the pupils_controller;
#previous_selection = Array.new
#pupil.groups.each do |pg|
#previous_selection.push(pg.id)
end
This is in the def edit block so only setup for the edit page.
Here is the PupilsController;
class PupilsController < ApplicationController
before_action :set_pupil, only: [:show, :edit, :update, :destroy]
def index
#pupils = Pupil.all
end
def show
#pupil_groups = #pupil.groups
end
def new
#pupil = Pupil.new
#all_groups = set_pupil_list
end
def edit
#all_groups = set_pupil_list
#previous_selection = Array.new
#pupil.groups.each do |pg|
#previous_selection.push(pg.id)
end
end
def create
#pupil = Pupil.new(pupil_params)
clean_select_multiple_params
logger.debug "The groups parameter contains: #{params[:groups][:id]}"
selected_groups = Group.find(params[:groups][:id])
#pupil.groups = selected_groups
respond_to do |format|
if #pupil.save
format.html { redirect_to #pupil, notice: 'Pupil was successfully created.' }
format.json { render action: 'show', status: :created, location: #pupil }
else
format.html { render action: 'new' }
format.json { render json: #pupil.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #pupil.update(pupil_params)
clean_select_multiple_params
selected_groups = Group.find(params[:groups][:id])
#pupil.groups = selected_groups
format.html { redirect_to #pupil, notice: 'Pupil was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #pupil.errors, status: :unprocessable_entity }
end
end
end
def destroy
#pupil.destroy
respond_to do |format|
format.html { redirect_to pupils_url }
format.json { head :no_content }
end
end
def full_name
#fn = #pupil.given_name
#sn = #pupil.surname
#full_name = #fn + #sn
end
private
def set_pupil
#pupil = Pupil.find(params[:id])
end
def set_pupil_list
Group.all
end
def clean_select_multiple_params hash = params
hash.each do |k, v|
case v
when Array then v.reject!(&:blank?)
when Hash then clean_select_multiple_params(v)
end
end
end
def pupil_params
params.require(:pupil).permit(:given_name, :surname, :date_of_birth, :gender, :ethnicity)
end
end
When the new pupil page is requested the _form.html.erb file is used that has the {selected: #previous_selection} argument in it that has not been set up by def new in the pupils_controller but there is not a error message about #previous_selection not being initialized.
I would expect an error but am not getting one but do not understand why. Could someone please explain? I am new to programming in general so sorry if I am using the wrong terminolog.
Thank you
Leon
#previous_selection variable is nil, and hence in the view none of collection items will be selected. It is not necessary to initialize a variable to nil, rails does that.

Resources