Hi I am playing around in rails and have built a little listing application.
My application has a listing model that has many tags through a has and belongs to many join table.
the join table is called listings_tags
The problem I have is that I cannot save the listing_tag association during create or update.
I can see in console
Started PATCH "/listings/92" for 127.0.0.1 at 2018-08-15 12:45:58 +1000
Processing by ListingsController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"5isdLs2FiToZxtm1ZVPP0y0lKtnfyoLA8Njv4GBwWVH1M3TIm2IUW9ts5RR06OpQz8tgSBitZ7Rm69uVIifevQ==", "listing"=>{"name"=>"Canteen Coffee", "streetAddres"=>"19 Park Avenue", "suburb_id"=>"31", "post_code_id"=>"2", "region_id"=>"1", "country_id"=>"2", "telephone"=>"+61416650204", "url"=>"http://canteencoffee.com.au/canteen-kitchen/", "tag_ids"=>["", "1"]}, "commit"=>"Update Listing", "id"=>"92"}
Listing Load (0.2ms) SELECT "listings".* FROM "listings" WHERE "listings"."id" = $1 LIMIT $2 [["id", 92], ["LIMIT", 1]]
Unpermitted parameter: :tag_ids
(1.8ms) BEGIN
Suburb Load (5.4ms) SELECT "suburbs".* FROM "suburbs" WHERE "suburbs"."id" = $1 LIMIT $2 [["id", 31], ["LIMIT", 1]]
(1.7ms) COMMIT
Redirected to http://localhost:3000/listings/92
Completed 302 Found in 21ms (ActiveRecord: 9.0ms)
Obviously my issue is the :tag_ids
so I tried changing my listing params.require(:listing).permit() to include listing_attributes: [:id], tags: [:id] and :tag_ids
its killing me :) please help
Listing Model
class Listing < ApplicationRecord
has_and_belongs_to_many :tags
belongs_to :suburb
has_one :post_code, through: :suburb
accepts_nested_attributes_for :tags
def self.search(term)
if term
where('name LIKE ?', "%#{term}%")
else
order('id DESC')
end
end
end
Tag Model
class Tag < ApplicationRecord
has_and_belongs_to_many :listings
end
Listings Tags Schema
create_table "listings_tags", id: false, force: :cascade do |t|
t.bigint "listing_id", null: false
t.bigint "tag_id", null: false
t.index ["listing_id", "tag_id"], name: "index_listings_tags_on_listing_id_and_tag_id"
end
Listings Controller
class ListingsController < ApplicationController
before_action :set_listing, only: [:show, :edit, :update, :destroy]
# GET /listings
# GET /listings.json
def index
#listings = Listing.search(params[:term])
end
# GET /listings/1
# GET /listings/1.json
def show
#listing = Listing.find(params[:id])
#tags = #listing.tags
#suburb = #listing.suburb
#postcode = #suburb.post_code
end
# GET /listings/new
def new
#listing = Listing.new
end
# GET /listings/1/edit
def edit
end
# POST /listings
# POST /listings.json
def create
#listing = Listing.new(listing_params)
respond_to do |format|
if #listing.save
format.html { redirect_to #listing, notice: 'Listing was successfully created.' }
format.json { render :show, status: :created, location: #listing }
else
format.html { render :new }
format.json { render json: #listing.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /listings/1
# PATCH/PUT /listings/1.json
def update
respond_to do |format|
if #listing.update(listing_params)
format.html { redirect_to #listing, notice: 'Listing was successfully updated.' }
format.json { render :show, status: :ok, location: #listing }
else
format.html { render :edit }
format.json { render json: #listing.errors, status: :unprocessable_entity }
end
end
end
# DELETE /listings/1
# DELETE /listings/1.json
def destroy
#listing.destroy
respond_to do |format|
format.html { redirect_to listings_url, notice: 'Listing was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_listing
#listing = Listing.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def listing_params
params.require(:listing).permit(:name, :streetAddress, :telephone, :url, :term, :suburb_id, :post_code_id, :region_id, :country_id, :tag_ids)
end
end
Tags Controller
class TagsController < ApplicationController
before_action :set_tag, only: [:show, :edit, :update, :destroy]
# GET /tags
# GET /tags.json
def index
#tags = Tag.all
end
# GET /tags/1
# GET /tags/1.json
def show
#tag = Tag.find(params[:id])
#listings = #tag.listings
end
# GET /tags/new
def new
#tag = Tag.new
end
# GET /tags/1/edit
def edit
end
# POST /tags
# POST /tags.json
def create
#tag = Tag.new(tag_params)
respond_to do |format|
if #tag.save
format.html { redirect_to #tag, notice: 'Tag was successfully created.' }
format.json { render :show, status: :created, location: #tag }
else
format.html { render :new }
format.json { render json: #tag.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /tags/1
# PATCH/PUT /tags/1.json
def update
respond_to do |format|
if #tag.update(tag_params)
format.html { redirect_to #tag, notice: 'Tag was successfully updated.' }
format.json { render :show, status: :ok, location: #tag }
else
format.html { render :edit }
format.json { render json: #tag.errors, status: :unprocessable_entity }
end
end
end
# DELETE /tags/1
# DELETE /tags/1.json
def destroy
#tag.destroy
respond_to do |format|
format.html { redirect_to tags_url, notice: 'Tag was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_tag
#tag = Tag.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def tag_params
params.require(:tag).permit(:name)
end
end
Form
<%= bootstrap_form_for(#listing, local: true) do |form| %>
<%= form.text_field :name, id: :listing_name %>
<%= form.text_field :streetAddress, id: :listing_streetAddress %>
<%= form.collection_select(:suburb_id, Suburb.all, :id, :name) %>
<%= form.collection_select(:post_code_id, PostCode.all, :id, :number) %>
<%= form.collection_select(:region_id, Region.all, :id, :name) %>
<%= form.collection_select(:country_id, Country.all, :id, :name) %>
<%= form.text_field :telephone, id: :listing_telephone %>
<%= form.text_field :url, id: :listing_url %>
<%= form.select :tag_ids, Tag.all.pluck(:name, :id), {}, { multiple: true, class: "selectize" } %>
<%= form.submit %>
<% end %>
I really appreciate your help. I am sure it is probably something simple that I am doing wrong.
try this
params.require(:listing).permit(:name, :streetAddress, :telephone, :url, :term, :suburb_id, :post_code_id, :region_id, :country_id, :tag_ids => [])
source : https://github.com/rails/strong_parameters
Related
so, I used CarrierWave gem and followed a railscast demo to get it working, but the image doesn't show on my listing show page.
here's the code on the show page:
<p id="notice"><%= notice %></p>
<p>
<strong>Description:</strong>
<%= #listing.description %>
</p>
<p>
<strong>Price $:</strong>
<%= #listing.price %>
</p>
<p>
<strong>Subcategory:</strong>
<%= Subcategory.find(#listing.subcategory_id).subcategory_name %>
</p>
<p>
<strong>Choose an image to upload:</strong>
<%= image_tag #listing.image_url(:half).to_s %>
</p>
<%= link_to 'Edit', edit_listing_path(#listing) %> |
<%= link_to 'Back', listings_path %> |
<%= link_to 'Home', root_path %>
and here's the controller:
class ListingsController < ApplicationController
before_action :set_listing, only: [:show, :edit, :update, :destroy]
before_action :set_options, only: [:new, :edit, :update, :create]
# GET /listings
# GET /listings.json
def search
if params[:category_id].present?
#category = Category.find(params[:category_id])
#subcategory = nil
elsif params[:subcategory_id].present?
#subcategory = Subcategory.find(params[:subcategory_id])
#category = Category.find(#subcategory.category_id)
end
end
def index
#listings = Listing.all
end
# GET /listings/1
# GET /listings/1.json
def show
end
# GET /listings/new
def new
#listing = Listing.new
end
# GET /listings/1/edit
def edit
end
# POST /listings
# POST /listings.json
def create
#listing = Listing.new(listing_params)
respond_to do |format|
if #listing.save
format.html { redirect_to #listing, notice: 'Listing was successfully created.' }
format.json { render :show, status: :created, location: #listing }
else
format.html { render :new }
format.json { render json: #listing.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /listings/1
# PATCH/PUT /listings/1.json
def update
respond_to do |format|
if #listing.update(listing_params)
format.html { redirect_to #listing, notice: 'Listing was successfully updated.' }
format.json { render :show, status: :ok, location: #listing }
else
format.html { render :edit }
format.json { render json: #listing.errors, status: :unprocessable_entity }
end
end
end
# DELETE /listings/1
# DELETE /listings/1.json
def destroy
#listing.destroy
respond_to do |format|
format.html { redirect_to listings_url, notice: 'Listing was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_listing
#listing = Listing.find(params[:id])
end
def set_options
#options_for_select_ary = Subcategory.all.collect {|subcategory| [ subcategory.subcategory_name, subcategory.id ] }
end
# Never trust parameters from the scary internet, only allow the white list through.
def listing_params
params.require(:listing).permit(:id, :description, :price, :subcategory_id)
end
end
and finally the model:
class Listing < ApplicationRecord
attr_accessor :image, :remote_image_url
belongs_to :category, optional: true
belongs_to :subcategory, optional: true
belongs_to :delivery, optional: true
belongs_to :user, optional: true
mount_uploader :image, AvatarUploader
end
so, my question is, how do I get the image to show up in the listing once it's been created?
I can add in my AvatarUploader class in an edit if you need to see the carrierwave code....
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|
I'm building a program to keep a client database for my first Rails app. I've followed through several different tutorials and successfully built out the demo apps, but now I am trying to create my own. In an effort to keep the database organized and efficient at scale, I setup a relational database with foreign keys.
My new client form should be displaying three fields - First Name, Address ID and Street, but it is only showing the first two. I've run across a couple things suggesting using .build to initialize my street field, but adding #client.address.build to def new in my clients_controller.rb didn't help. Any suggestions as to what I'm doing wrong?
Schema:
ActiveRecord::Schema.define(version: 20141120045947) do
create_table "addresses", force: true do |t|
t.string "number"
t.datetime "created_at"
t.datetime "updated_at"
t.string "street"
end
create_table "clients", force: true do |t|
t.string "first_name"
t.integer "address_id"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "street_id"
end
add_index "clients", ["address_id"], name: "index_clients_on_address_id", using: :btree
end
Form partial:
<%= form_for(#client) do |f| %>
<% if #client.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#client.errors.count, "error") %> prohibited this client from being saved:</h2>
<ul>
<% #client.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :first_name %><br>
<%= f.text_field :first_name %>
</div>
<div class="field">
<%= f.label :address_id, "Address ID"%><br>
<%= f.text_field :address_id %>
</div>
<%= f.fields_for :address do |address| %>
<div class="field">
<%= address.label :street %><br>
<%= address.text_field :street %>
</div>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Clients controller:
class ClientsController < ApplicationController
before_action :set_client, only: [:show, :edit, :update, :destroy]
# GET /clients
# GET /clients.json
def index
#clients = Client.all
end
# GET /clients/1
# GET /clients/1.json
def show
#address = Address.find(params[:id])
end
# GET /clients/new
def new
#client = Client.new
end
# GET /clients/1/edit
def edit
end
# POST /clients
# POST /clients.json
def create
#client = Client.new(client_params)
respond_to do |format|
if #client.save
format.html { redirect_to #client, notice: 'Client was successfully created.' }
format.json { render :show, status: :created, location: #client }
else
format.html { render :new }
format.json { render json: #client.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /clients/1
# PATCH/PUT /clients/1.json
def update
respond_to do |format|
if #client.update(client_params)
format.html { redirect_to #client, notice: 'Client was successfully updated.' }
format.json { render :show, status: :ok, location: #client }
else
format.html { render :edit }
format.json { render json: #client.errors, status: :unprocessable_entity }
end
end
end
# DELETE /clients/1
# DELETE /clients/1.json
def destroy
#client.destroy
respond_to do |format|
format.html { redirect_to clients_url, notice: 'Client was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_client
#client = Client.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def client_params
params.require(:client).permit(:first_name, :address_id, address_attributes: [:number,:street])
end
end
Addresses controller:
class AddressesController < ApplicationController
before_action :set_address, only: [:show, :edit, :update, :destroy]
# GET /addresses
# GET /addresses.json
def index
#addresses = Address.all
end
# GET /addresses/1
# GET /addresses/1.json
def show
end
# GET /addresses/new
def new
#address = Address.new
end
# GET /addresses/1/edit
def edit
end
# POST /addresses
# POST /addresses.json
def create
#address = Address.new(address_params)
respond_to do |format|
if #address.save
format.html { redirect_to #address, notice: 'Address was successfully created.' }
format.json { render :show, status: :created, location: #address }
else
format.html { render :new }
format.json { render json: #address.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /addresses/1
# PATCH/PUT /addresses/1.json
def update
respond_to do |format|
if #address.update(address_params)
format.html { redirect_to #address, notice: 'Address was successfully updated.' }
format.json { render :show, status: :ok, location: #address }
else
format.html { render :edit }
format.json { render json: #address.errors, status: :unprocessable_entity }
end
end
end
# DELETE /addresses/1
# DELETE /addresses/1.json
def destroy
#address.destroy
respond_to do |format|
format.html { redirect_to addresses_url, notice: 'Address was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_address
#address = Address.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def address_params
params.require(:address).permit(:number, :street)
end
end
Client model:
class Client < ActiveRecord::Base
belongs_to :address
accepts_nested_attributes_for :address
end
Address model:
class Address < ActiveRecord::Base
has_many :clients
end
Good day, community.
First of all, I'm a newbie in Rails. I did some thing with it in College 4 years ago, and now I decided to get back on it. Lots of things changed in version 4.
Anyway, I am experiencing issues with strong parameters. Here's what I have:
I'm using Ruby 2.1, Rails 4.1.
I am trying to create a form for a hockey match with parameters (id, team_a, team_b, arena, date, score_a, score_b). team is a table (id, name) and arena is a table (id, name).
When I pass the parameters from form to the controller, the json parameters seem to be okay. But, when it is converted into match_params it is missing some values from parameters from other table. For example, I am passing arena_id: 12, but it shows arena_id: as blank.
I've spent over 5 days on this thing. Any help appreciated.
Some of the code is bellow. Let me know if you need me to provide more information...
migration data
class CreateMatches < ActiveRecord::Migration
def change
create_table :matches do |t|
t.references :team_a, default: 1 # unknown
t.references :team_b, default: 1 # unknown
t.references :arena, default: 1 # unknown
t.datetime :date
t.integer :score_a
t.integer :score_b
t.timestamps
end
add_index :matches, :team_a_id
add_index :matches, :team_b_id
add_index :matches, :arena_id
end
end
class CreateTeams < ActiveRecord::Migration
def change
create_table :teams do |t|
t.string :name, null: false
t.timestamps
end
end
end
class CreateArena < ActiveRecord::Migration
def change
create_table :arena do |t|
t.string :name, null: false
t.timestamps
end
end
end
match.rb (model)
class Match < ActiveRecord::Base
belongs_to :team_a, :class_name => 'Team'
belongs_to :team_b, :class_name => 'Team'
belongs_to :arena
end
team.rb (model)
class Team < ActiveRecord::Base
has_many :matches
accepts_nested_attributes_for :matches
end
arena.rb (model)
class Arena < ActiveRecord::Base
has_many :matches
accepts_nested_attributes_for :matches
end
matches_controller.rb
class MatchesController < ApplicationController
before_action :set_match, only: [:show, :edit, :score, :update, :destroy]
include ActionView::Helpers::DateHelper
def index
# some code
end
def show
# some code
end
def new
#match = Match.new
#teams = Team.all.order("name ASC")
#arenas = Arena.all.order("name ASC")
end
# GET /matches/1/edit
def edit
# some code
end
def create
puts YAML::dump(match_params) # Checking passed params. Output is bellow
#match = Match.new(match_params)
respond_to do |format|
if #match.save
format.html { redirect_to #match, notice: 'Match was successfully created.' }
format.json { render action: 'show', status: :created, location: #match }
else
format.html { render action: 'new' }
format.json { render json: #match.errors, status: :unprocessable_entity }
end
end
end
def update
end
def destroy
end
private
# Use callbacks to share common setup or constraints between actions.
def set_match
#match = Match.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def match_params
params.require(:match).permit(:date, :score_a, :score_b, team_a_id: [:id, :name], team_b_id: [:id, :name], arena_id: [:id, :name])
end
public
end
teams_controller.rb
class TeamsController < ApplicationController
before_action :set_team, only: [:show, :edit, :update, :destroy]
layout :false
def index
#teams = Team.all
end
def show
end
def new
#team = Team.new
end
def edit
end
def create
#team = Team.new(team_params)
respond_to do |format|
if #team.save
format.json { render action: 'show', status: :created, location: #team }
format.html { redirect_to #team, notice: 'Team was successfully created.' }
else
format.html { render action: 'new' }
format.json { render json: #team.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #team.update(team_params)
format.json { head :no_content }
format.html { redirect_to #team, notice: 'Team was successfully updated.' }
else
format.html { render action: 'edit' }
format.json { render json: #team.errors, status: :unprocessable_entity }
end
end
end
def destroy
#team.destroy
respond_to do |format|
format.html { redirect_to teams_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_team
#team = Team.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def team_params
params.require(:team).permit(:name)
end
end
arenas_controller.rb
class ArenasController < ApplicationController
before_action :set_arena, only: [:show, :edit, :update, :destroy]
layout false
def index
#arena = Arena.all
end
def show
end
def new
#arena = Arena.new
end
def edit
end
def create
#arena = Arena.new(arena_params)
respond_to do |format|
if #arena.save
format.json { render action: 'show', status: :created, location: #arena }
format.html { redirect_to #arena, notice: 'Arena was successfully created.' }
else
format.html { render action: 'new' }
format.json { render json: #arena.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #arena.update(arena_params)
format.json { head :no_content }
format.html { redirect_to #arena, notice: 'Arena was successfully updated.' }
else
format.html { render action: 'edit' }
format.json { render json: #arena.errors, status: :unprocessable_entity }
end
end
end
def destroy
#arena.destroy
respond_to do |format|
format.html { redirect_to arenas_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_arena
#arena = Arena.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def arena_params
params.require(:arena).permit(:name)
end
end
matches/_match.html.erb
<%= form_for(#match, html: {role: 'form', class: 'form-horizontal'}) do |f| %>
<% if #match.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#match.errors.count, "error") %> prohibited this match from being saved:</h2>
<ul>
<% #match.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<%= f.label 'Home Team' %>
<%= f.collection_select :team_a_id, #teams, :id, :name, {prompt: true}, {class: ''} %>
<%= f.label 'Visitor Team' %>
<%= f.collection_select :team_b_id, #teams, :id, :name, {prompt: true}, {class: ''} %>
<%= f.label 'Arena' %>
<%= f.collection_select :arena_id, #arenas, :id, :name, {prompt: true}, {class: ''} %>
<%= f.label 'Date' %>
<%= f.datetime_select :date, class: 'form-control' %>
<%= f.submit value: 'Submit' %>
<% end %>
And here's what I am getting in console after dumping data:
Started POST "/matches" for 127.0.0.1 at 2014-05-06 18:24:20 -0700
Processing by MatchesController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"0RJjnpczVkp2unG9VITyHYC89ThgELn5kVE2wYRymBU=", "match"=>{"team_a_id"=>"24", "team_b_id"=>"27", "arena_id"=>"21", "date(1i)"=>"2014", "date(2i)"=>"5", "date(3i)"=>"6", "date(4i)"=>"18", "date(5i)"=>"24"}, "commit"=>"Update"}
User Load (0.5ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 ORDER BY `users`.`id` ASC LIMIT 1
--- !ruby/hash:ActionController::Parameters
date(1i): '2014'
date(2i): '5'
date(3i): '6'
date(4i): '18'
date(5i): '24'
team_a_id:
team_b_id:
arena_id:
(0.2ms) BEGIN
SQL (1.5ms) INSERT INTO `matches` (`created_at`, `date`, `arena_id`, `team_a_id`, `team_b_id`, `updated_at`) VALUES ('2014-05-07 01:24:20', '2014-05-07 01:24:00', NULL, NULL, NULL, '2014-05-07 01:24:20')
(0.2ms) COMMIT
Redirected to http://localhost:3000/matches/90
Completed 302 Found in 13ms (ActiveRecord: 2.4ms)
Take a look at your match_params, and compare it to what parameters are being passed to your controller from your form.
def match_params
params.require(:match).permit(:date, :score_a, :score_b, team_a_id: [:id, :name], team_b_id: [:id, :name], area_id: [:id, :name])
end
Parameters: {"utf8"=>"✓", "authenticity_token"=>"0RJjnpczVkp2unG9VITyHYC89ThgELn5kVE2wYRymBU=", "match"=>{"team_a_id"=>"24", "team_b_id"=>"27", "arena_id"=>"21", "date(1i)"=>"2014", "date(2i)"=>"5", "date(3i)"=>"6", "date(4i)"=>"18", "date(5i)"=>"24"}, "commit"=>"Update"}
You're permitting your arena_id in match_params as an array called area_id, with elements :id and :name. However, it's being passed from your form as just arena_id. You should change your match_params function to:
def match_params
params.require(:match).permit(:date, :score_a, :score_b, :team_a_id, :team_b_id, :arena_id)
end
Note that I've also changed :team_a_id and :team_b_id to be consistent with what's being passed in your parameters too, although it doesn't look like you're passing :score_a or :score_b. You should check out strong parameters in the rails guides for more information.
Okay, I found my mistake. (Thanks to JKen13579)
I have put params in the wrong place.
It should be something like that:
def match_params
params.require(:match).permit(:date, :score_a, :score_b, :team_a_id, :team_b_id , :arena_id)
end
def team_params
params.require(:team).permit(:name, matches_params:[:id, :match_id, :name])
end
def arena_params
params.require(:arena).permit(:name, matches_params:[:id, :match_id, :name])
end
It fixed the issue.
everyting but name will be removed when you call this:
params.require(:arena).permit(:name)
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