i have a rails app. i have strange problem in saving form
this is my ticket model .
class Ticket < ApplicationRecord
belongs_to :user
has_many :ticketissues , inverse_of: :ticket
accepts_nested_attributes_for :ticketissues, :reject_if => lambda { |a| a[:body].blank? }
end
this is ticketisue model
class Ticketissue < ApplicationRecord
belongs_to :user
belongs_to :ticket
validates :body, presence: true
end
this is ticket controller
class TicketsController < ApplicationController
before_action :set_ticket, only: [:show, :edit, :update, :destroy]
# GET /tickets
# GET /tickets.json
def index
#tickets = Ticket.all
end
# GET /tickets/1
# GET /tickets/1.json
def show
end
# GET /tickets/new
def new
#ticket = Ticket.new
end
# GET /tickets/1/edit
def edit
end
# POST /tickets
# POST /tickets.json
def create
#ticket = Ticket.new(ticket_params)
#ticket.user_id = current_user.id
#ticket.ticketissues.build
respond_to do |format|
if #ticket.save
format.html { redirect_to #ticket, notice: 'Ticket was successfully created.' }
format.json { render :show, status: :created, location: #ticket }
else
format.html { render :new }
format.json { render json: #ticket.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /tickets/1
# PATCH/PUT /tickets/1.json
def update
respond_to do |format|
if #ticket.update(ticket_params)
format.html { redirect_to #ticket, notice: 'Ticket was successfully updated.' }
format.json { render :show, status: :ok, location: #ticket }
else
format.html { render :edit }
format.json { render json: #ticket.errors, status: :unprocessable_entity }
end
end
end
# DELETE /tickets/1
# DELETE /tickets/1.json
def destroy
#ticket.destroy
respond_to do |format|
format.html { redirect_to tickets_url, notice: 'Ticket was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_ticket
#ticket = Ticket.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def ticket_params
params.require(:ticket).permit(:subject, :subsubject, :user_id, ticketissues_attributes: [
:body, :id, :_destroy] )
#params.require(:ticket).permit!
end
end
and my view is like this
<%= f.input :subject , collection: [ "تغییر اطلاعات کسب و کار",
"تغییر اطلاعات یک کوپن",
"سایر موارد"] %>
<%= f.input :subsubject %>
<!-- <%= f.association :user %> -->
</div>
<%= f.simple_fields_for :ticketissue do |p| %>
<%= p.input :body %>
<% end %>
<div class="form-actions">
<%= f.button :submit %>
</div>
<% end %>
but when i want to create a ticket , form will not save to database
and i get this error:
Started POST "/tickets" for 127.0.0.1 at 2017-04-11 23:52:33 +0430
Processing by TicketsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"fsl6nTe0PjmBKpeuh16BRFlYOw0MB93LEYDVEAl6TtT/uu/LwGTA0P2q0bRxIxBUqHqZINXHntrZLt7MuCG84Q==", "ticket"=>{"subject"=>"تغییر اطلاعات کسب و کار", "subsubject"=>"lk", "ticketissue"=>{"body"=>"lkjkjkjkjkkjkj"}}, "commit"=>"Create Ticket"}
Unpermitted parameter: ticketissue
but when i use console and this command:
Ticket.create(subject: 'test' , subsubject: 'ticket test' , ticketissues_attributes: [{body: "[some thing" }] )
every things work fines and all data save.
tanks for read and help.
You must use the plural here
= f.simple_fields_for :ticketissues do |p|
Related
I am having trouble structuring my nested attributes for my model Request.
The data is being passed in the correct way from my POST action.
What am I missing to whitelist these parameters?
Appreciate any help.
Console Output
Started POST "/requests" for 127.0.0.1 at 2017-06-08 10:57:15 -0400
Processing by RequestsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"fmvhoPxVpcHoqOd32mO/HJMrfaPUd+KbNqDJiSRs78U44Y0uL3prpTfU6wmw7PAwv0b+mRHXOGMLvD9bsZpxnw==", "request"=>{"concierge_name"=>"Alex", "concierge_number"=>"954-123-4567", "concierge_email"=>"alex#email.com", "client_name"=>"Adam", "client_number"=>"954-765-4321", "client_email"=>"adam#email.com", "hotel_employee"=>"0", "concierge_service"=>"0", "vip_promoter"=>"0", "arriving_with_client"=>"1", "client_alone"=>"0", "males"=>"", "females"=>"1", "table_minimum"=>"1000", "arrival_time(1i)"=>"2017", "arrival_time(2i)"=>"6", "arrival_time(3i)"=>"8", "arrival_time(4i)"=>"14", "arrival_time(5i)"=>"56", "table_location_ids"=>["1"], "drink_attributes"=>[{"id"=>"1", "quantity"=>"1"}, {"id"=>"2", "quantity"=>""}, {"id"=>"3", "quantity"=>""}, {"id"=>"4", "quantity"=>""}], "chaser_ids"=>["1"], "comments"=>""}, "commit"=>"Submit"}
Completed 500 Internal Server Error in 8ms (ActiveRecord: 0.0ms)
ActiveModel::UnknownAttributeError (unknown attribute 'drink_attributes' for Request.):
app/models/request.rb
class Request < ApplicationRecord
has_many :request_drinks
has_many :drinks, through: :request_drinks
accepts_nested_attributes_for :drinks
end
app/model/drink.rb
class Drink < ApplicationRecord
has_many :request_drinks
has_many :requests, through: :request_drinks
end
app/model/request_drink.rb
class RequestDrink < ApplicationRecord
belongs_to :request
belongs_to :drink
end
app/controllers/request_controller.rb
class RequestsController < ApplicationController
before_action :set_request, only: [:show,
:edit,
:update,
:destroy]
def index
#requests = Request.search(params[:term], params[:filter], params[:page])
end
def show
end
def new
#request = Request.new
#drinks = Drink.active
end
def edit
end
def create
#request = Request.new(request_params)
respond_to do |format|
if #request.save
format.html { redirect_to thanks_path, notice: 'Request was successfully created.' }
format.json { render :show, status: :created, location: #request }
else
format.html { render :new }
format.json { render json: #request.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #request.update(request_params)
format.html { redirect_to #request, notice: 'Request was successfully updated.' }
format.json { render :show, status: :ok, location: #request }
else
format.html { render :edit }
format.json { render json: #request.errors, status: :unprocessable_entity }
end
end
end
def destroy
#request.destroy
respond_to do |format|
format.html { redirect_to requests_url, notice: 'Request was successfully destroyed.' }
format.json { head :no_content }
end
end
private
def set_request
#request = Request.find(params[:id])
end
def request_params
params.require(:request).permit(:concierge_name,
:concierge_number,
:concierge_email,
:client_name,
:client_number,
:client_email,
:hotel_employee,
:concierge_service,
:vip_promoter,
:arriving_with_client,
:client_alone,
:people,
:males,
:females,
:table_minimum,
:arrival_time,
:comments,
:drink_attributes => [:id, :quantity]
)
end
end
app/views/requests/_form.html.erb
...
<div class="field-3">
<h4>Drinks</h4>
<% #drinks.all.each do |d| %>
<%= hidden_field_tag "request[drink_attributes][][id]", d.id %>
<%= number_field_tag "request[drink_attributes][][quantity]" %>
<%= d.name %>
<br />
<% end %>
</div>
...
You need to use the plural form of the object (i.e. drinks) when using nested attributes.
So, in your request_params change:
:drink_attributes => [:id, :quantity]
to:
:drinks_attributes => [:id, :quantity]
An you need to update your form too:
...
<%= hidden_field_tag "request[drinks_attributes][][id]", d.id %>
<%= number_field_tag "request[drinks_attributes][][quantity]" %>
...
I'm currently trying to add a collection_select of ranches to my staff
And I saw that it's better to create an extra table to make this association.
And I follow some tutorial, but is not working on my side
This is my code :
Staffs/_form :
<%= form_for(#staff) do |f| %>
<div class="field">
<%= f.label :name %><br>
<%= f.text_field :name %>
</div>
<%= fields_for(#staff_ranch) do |x| %>
<div class="field">
<%= x.collection_select(:ranch_id, #all_ranch, :id, :name, { }, {:multiple => true}) %>
</div>
<%end%>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
My models :
- Ranch :
has_many :ranchstaffs
has_many :staffs, :through => :ranchstaffs
- Staff :
has_many :ranchstaffs
has_many :ranches, :through => :ranchstaffs
-Ranchstaff :
belongs_to :ranch
belongs_to :staff
Staff controller :
class StaffsController < ApplicationController
before_action :set_staff, only: [:show, :edit, :update, :destroy]
# GET /ranches
# GET /ranches.json
def index
#staffs = current_user.staffs
end
# GET /ranches/1
# GET /ranches/1.json
def show
end
# GET /ranches/new
def new
#staff = Staff.new
#all_ranch = current_user.ranches
#staff_ranch = #staff.ranchstaffs.build
end
# GET /ranches/1/edit
def edit
end
# POST /ranches
# POST /ranches.json
def create
#staff = Staff.new(staff_params)
#staff.update(user_id: current_user.id)
respond_to do |format|
if #staff.save
format.html { redirect_to #staff, notice: 'Staff was successfully created.' }
format.json { render :show, status: :created, location: #staff }
else
format.html { render :new }
format.json { render json: #staff.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /ranches/1
# PATCH/PUT /ranches/1.json
def update
respond_to do |format|
if #staff.update(staff_params)
format.html { redirect_to #staff, notice: 'Staff was successfully updated.' }
format.json { render :show, status: :ok, location: #staff }
else
format.html { render :edit }
format.json { render json: #staff.errors, status: :unprocessable_entity }
end
end
end
# DELETE /ranches/1
# DELETE /ranches/1.json
def destroy
#staff.destroy
respond_to do |format|
format.html { redirect_to staffs_url, notice: 'Ranch was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_staff
#staff = Staff.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def staff_params
params.require(:staff).permit(:name, :user_id, :cat, :ranch_id)
end
end
Can you explain me why the model ranchstaff was not created after a creation of a new staff ?
As you are using fields_for you are using nested form but you are not permitting the parameters properly. First make change in your form:
<%= f.fields_for(#staff_ranch) do |x| %>
<div class="field">
<%= x.collection_select(:ranch_id, #all_ranch, :id, :name, { }, {:multiple => true}) %>
</div>
<% end %>
And then in your controller:
def staff_params
params.require(:staff).permit(:name, :user_id, :cat, ranchstaff_attributes: [ranch_id: []])
end
And in your Staff model write:
accepts_nested_attributes_for :ranchstaffs
Then your ranchstaff should be created when the User is being created.
Your ranch_id is coming in an array. So u have to specify that ranch_id would be array in strong parameters.
so your staff_params method would look like this
def staff_params
params.require(:staff).permit(:name, :user_id, :cat, :staff_ranch_attributes =>[:ranch_id => []])
end
sorry for this question but I'm struggling with this issue for hours now and can't find the answer anywhere.
Here is the thing, I have a rails app with "Reservation" and "Space" models with the following relations:
class Reservation < ActiveRecord::Base
belongs_to :space
belongs_to :user
end
class Space < ActiveRecord::Base
belongs_to :condo
has_many :reservations
end
When the user creates a new Reservation, in the form he gets to choose from a dropdown (f.select) the spaces available for him. The f.select in the form look like this:
<div class="field">
<%= #user_spaces = current_user.condo.spaces
f.select :space_id,
options_from_collection_for_select(#user_spaces, :id, :name), :prompt => "Select space"
%>
</div>
That select it supose to assign a value to the key "space_id" in the Reservation that is being created (column's table is created). But when I check the last reservation in Rails console, space_id value is "nil". What am I doing wrong?
Thank you very much for your help
Reservation controller file:
class ReservationsController < ApplicationController
before_action :set_reservation, only: [:show, :edit, :update, :destroy]
# GET /reservations
# GET /reservations.json
def index
#reservations = Reservation.all
end
# GET /reservations/1
# GET /reservations/1.json
def show
end
# GET /reservations/new
def new
#reservation = Reservation.new
end
# GET /reservations/1/edit
def edit
end
# POST /reservations
# POST /reservations.json
def create
#reservation = Reservation.new(reservation_params)
#user = current_user.id
#reservation.user_id = #user
respond_to do |format|
if #reservation.save
format.html { redirect_to #reservation, notice: 'Reservation was successfully created.' }
format.json { render :show, status: :created, location: #reservation }
else
format.html { render :new }
format.json { render json: #reservation.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /reservations/1
# PATCH/PUT /reservations/1.json
def update
respond_to do |format|
if #reservation.update(reservation_params)
format.html { redirect_to #reservation, notice: 'Reservation was successfully updated.' }
format.json { render :show, status: :ok, location: #reservation }
else
format.html { render :edit }
format.json { render json: #reservation.errors, status: :unprocessable_entity }
end
end
end
# DELETE /reservations/1
# DELETE /reservations/1.json
def destroy
#reservation.destroy
respond_to do |format|
format.html { redirect_to reservations_url, notice: 'Reservation was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_reservation
#reservation = Reservation.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def reservation_params
params.require(:reservation).permit(:eventdate)
end
end
Space controller file:
class SpacesController < ApplicationController
before_action :set_space, only: [:show, :edit, :update, :destroy]
# GET /spaces
# GET /spaces.json
def index
#spaces = Space.all
end
# GET /spaces/1
# GET /spaces/1.json
def show
end
# GET /spaces/new
def new
#space = Space.new
end
# GET /spaces/1/edit
def edit
end
# POST /spaces
# POST /spaces.json
def create
#space = Space.new(space_params)
respond_to do |format|
if #space.save
format.html { redirect_to #space, notice: 'Space was successfully created.' }
format.json { render :show, status: :created, location: #space }
else
format.html { render :new }
format.json { render json: #space.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /spaces/1
# PATCH/PUT /spaces/1.json
def update
respond_to do |format|
if #space.update(space_params)
format.html { redirect_to #space, notice: 'Space was successfully updated.' }
format.json { render :show, status: :ok, location: #space }
else
format.html { render :edit }
format.json { render json: #space.errors, status: :unprocessable_entity }
end
end
end
# DELETE /spaces/1
# DELETE /spaces/1.json
def destroy
#space.destroy
respond_to do |format|
format.html { redirect_to spaces_url, notice: 'Space was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_space
#space = Space.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def space_params
params.require(:space).permit(:name)
end
end
And full Reservation Form:
<%= form_for(#reservation) do |f| %>
<% if #reservation.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#reservation.errors.count, "error") %> prohibited this reservation from being saved:</h2>
<ul>
<% #reservation.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :eventdate %><br>
<%= f.date_select :eventdate %>
</div>
<div class="field">
<%= #user = current_user.condo.spaces
f.select :space_id,
options_from_collection_for_select(#user, :id, :name), :prompt => "Select space"
%>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
pretty sure you need to permit the space_id attribute in your strong params.
def reservation_params
params.require(:reservation).permit(:eventdate, :space_id)
end
whats happening is that when you go to create a reservation, youre passing in set of params, that is the output of reservation_params
#reservation = Reservation.new(reservation_params)
if space_id is not being permitted in your strong params, then it will be nil when created.
if this is not the issue, can you post what params are getting to the server, and what the output of reservation_params are.
I have a model "post" and a model "photo". The model post have a nested form from photo to upload images with association. The upload works fine, but everytime I go to edit the post, I have a new input to each image uploaded and one more input to upload a new image. I want to have just the input to upload a new file and hide or not load the others.
Here is my code:
<%= f.fields_for :photos do |photo| %>
<%= photo.file_field :image, class: "form-control" %>
<% end %>
Controller:
module Admin
class SeminovosController < SuperAdminController
before_action :set_seminovo, only: [:show, :edit, :update, :destroy]
# GET /seminovos
# GET /seminovos.json
def index
#seminovos = Seminovo.all
#seminovo = Seminovo.new
#seminovo.photos.build
#expires_in 3.hours, :public => true, 'max-stale' => 0
end
# GET /seminovos/1
# GET /seminovos/1.json
def show
end
# GET /seminovos/new
def new
#seminovo = Seminovo.new
#seminovo.photos.build
#seminovo.photos
end
# GET /seminovos/1/edit
def edit
#seminovo.photos.build
#seminovo.photos
end
# POST /seminovos
# POST /seminovos.json
def create
##seminovo = Seminovo.new(seminovo_params)
respond_to do |format|
#seminovo = Seminovo.new(seminovo_params)
#seminovo.save
format.html { redirect_to #seminovo }
format.js
# if #seminovo.save
# format.html { redirect_to #seminovo, notice: 'Seminovo was successfully created.' }
# format.json { render :show, status: :created, location: #seminovo }
# else
# format.html { render :new }
# format.json { render json: #seminovo.errors, status: :unprocessable_entity }
# end
end
end
# PATCH/PUT /seminovos/1
# PATCH/PUT /seminovos/1.json
def update
respond_to do |format|
if #seminovo.update(seminovo_params)
format.html { redirect_to #seminovo, notice: 'Seminovo was successfully updated.' }
format.json { render :show, status: :ok, location: #seminovo }
else
format.html { render :edit }
format.json { render json: #seminovo.errors, status: :unprocessable_entity }
end
end
end
# DELETE /seminovos/1
# DELETE /seminovos/1.json
def destroy
#seminovo.destroy
respond_to do |format|
format.html { redirect_to seminovos_url, notice: 'Seminovo was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_seminovo
#seminovo = Seminovo.friendly.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def seminovo_params
params.require(:seminovo).permit(:name, :price, :marca_id, :tipo_id, :ano_modelo,
:portas, :km_rodados, :combustivel, :placa, :cor, :desc,
:video, :destaque, :photo_id, :slug,
photos_attributes: [ :id, :image, :image_uid, :image_name, :desc,
:seminovos_id, :_destroy ])
end
end
end
Remove
#seminovo.photos.build
#seminovo.photos
from new and edit action.
Then replace
<%= f.fields_for :photos do |photo| %>
<%= photo.file_field :image, class: "form-control" %>
<% end %>
With
<%= f.fields_for :photos, #seminovo.photos.new do |photo| %>
<%= photo.file_field :image, class: "form-control" %>
<% end %>
I'm fairly new to rails, building my first app. I'm running rails 4 w/ bootstrap 3. I'm trying to get a complex form to work. I have two models:
class Employee < ActiveRecord::Base
belongs_to :company
belongs_to :user, :through => :company
has_one :position
accepts_nested_attributes_for :position
end
class Position < ActiveRecord::Base
belongs_to :employees
accepts_nested_attributes_for :employees
end
I have a form where the User can create a new job title (Position Model) and select the employees (Employees Model) that position will be applied to. Basically it's a single form that will add fields to 2 different database tables (Position and Employee).
This is my view:
<%= simple_form_for(#position) do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<%= f.input :job_title %>
<%= f.input :job_description %>
</div>
<%= f.fields_for :Employee do |f| %>
<%= f.input :employee_title, label: "Apply to:", collection: Employee.all, label_method: :first_name, as: :check_boxes %>
<% end %>
<div class="form-actions">
<%= f.button :submit %>
</div>
<% end %>
Below are the controllers:
class PositionsController < ApplicationController
before_action :set_position, only: [:show, :edit, :update, :destroy]
# GET /positions
# GET /positions.json
def index
#positions = Position.all
end
# GET /positions/1
# GET /positions/1.json
def show
end
# GET /positions/new
def new
#position = Position.new
end
# GET /positions/1/edit
def edit
end
# POST /positions
# POST /positions.json
def create
#position = Position.new(position_params)
respond_to do |format|
if #position.save
format.html { redirect_to #position, notice: 'position was successfully created.' }
format.json { render action: 'show', status: :created, location: #position }
else
format.html { render action: 'new' }
format.json { render json: #position.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /positions/1
# PATCH/PUT /positions/1.json
def update
respond_to do |format|
if #position.update(position_params)
format.html { redirect_to #position, notice: 'position was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #position.errors, status: :unprocessable_entity }
end
end
end
# DELETE /positions/1
# DELETE /positions/1.json
def destroy
#position.destroy
respond_to do |format|
format.html { redirect_to positions_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_position
#position = Position.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def position_params
params.require(:position).permit(:position_title, :position_description, :position_create_date)
end
end
class EmployeesController < ApplicationController
# encoding: UTF-8
before_action :set_employee, only: [:show, :edit, :update, :destroy]
# GET /employees
# GET /employees.json
def index
#employees = Employee.all
end
# GET /employees/1
# GET /employees/1.json
def show
end
# GET /employees/new
def new
#employee = Employee.new
end
# GET /employees/1/edit
def edit
end
# POST /employees
# POST /employees.json
def create
#employee = Employee.new(employee_params)
respond_to do |format|
if #employee.save
format.html { redirect_to #employee, notice: 'Employee was successfully created.' }
format.json { render action: 'show', status: :created, location: #employee }
else
format.html { render action: 'new' }
format.json { render json: #employee.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /employees/1
# PATCH/PUT /employees/1.json
def update
respond_to do |format|
if #employee.update(employee_params)
format.html { redirect_to #employee, notice: 'Employee was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #employee.errors, status: :unprocessable_entity }
end
end
end
# DELETE /employees/1
# DELETE /employees/1.json
def destroy
#employee.destroy
respond_to do |format|
format.html { redirect_to employees_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_employee
#employee = Employee.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def employee_params
params.require(:employee).permit(:first_name, :last_name, :employee_title)
end
end
The problem I'm facing is I get the form to render perfectly, but when I submit it, only fields that belong to the Position model get recorded. The :employee_title stays blank. Any suggestions what the problem is?
Thank you!!
Too many points to fit in a comment:
belongs_to :employees should be singular: belongs_to :employee
Your fields_for should be like (differentiate the ff from parent form):
<%= f.fields_for :Employee do |ff| %>
<%= ff.input :employee_title, label: "Apply to:", collection: Employee.all,
label_method: :first_name, as: :check_boxes %>
<% end %>
If it doesn't work, supply your controller also and I'll update my answer.
Edit:
After seeing your controllers, it seems most likely to be case of unpermitted params.
In position_controller.rb add employee params to position params
def position_params
params.require(:position).permit(:position_title, :position_description, :position_create_date, employees_attributes: [:first_name, :last_name, :employee_title])
end