I ran into a very strange bug in my Rails app: Whenever I try to submit a form I get the error No route matches [PATCH] "/business_cases" (in this case). But after clicking the "Back"-Button in my Browser and filling out + submitting again, it works fine. As this error appears not only in this specific model but almost every other I'm quite lost.. Here is the example.
routes:
business_cases GET /business_cases(.:format) business_cases#index
POST /business_cases(.:format) business_cases#create
new_business_case GET /business_cases/new(.:format) business_cases#new
edit_business_case GET /business_cases/:id/edit(.:format) business_cases#edit
business_case GET /business_cases/:id(.:format) business_cases#show
PATCH /business_cases/:id(.:format) business_cases#update
PUT /business_cases/:id(.:format) business_cases#update
DELETE /business_cases/:id(.:format) business_cases#destroy
routes.rb:
root 'dashboards#index'
get "index" => "pages#index"
resources :users, :orders, :sales, :business_cases
controller (FYI: I use cancancan):
class BusinessCasesController < ApplicationController
load_and_authorize_resource
before_action :authenticate_user!
def index
end
def show
end
def new
end
def edit
end
def create
respond_to do |format|
if #business_case.save
format.html { redirect_to business_cases_url, notice: 'Business case was successfully created.' }
format.json { render :show, status: :created, location: #business_case }
else
format.html { render :new }
format.json { render json: #business_case.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #business_case.update(business_case_params)
format.html { redirect_to business_cases_url, notice: 'Business case was successfully updated.' }
format.json { render :show, status: :ok, location: #business_case }
else
format.html { render :edit }
format.json { render json: #business_case.errors, status: :unprocessable_entity }
end
end
end
def destroy
#business_case.destroy
respond_to do |format|
format.html { redirect_to business_cases_url, notice: 'Business case was successfully destroyed.' }
format.json { head :no_content }
end
end
model:
class BusinessCase < ActiveRecord::Base
validates :name, :description, :presence => true
end
form (shorten):
<%= form_for #business_case, html: { multipart: true } do |f| %>
<div class="form-group">
<%= f.label :name %>
<%= f.text_field :name, class: "form-control", placeholder: "X-Sell" %>
</div>
<% end %>
Related
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
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]).
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.
Routes File:
resources :tournaments do
resources :game, :only => [:new, :index, :create, :update, :destroy]
end
Rake Routes shows:
new_tournament_game GET /tournaments/:tournament_id/game/new(.:format) game#new
I call:
<td><%= link_to 'Add Game', new_tournament_game_path(tournament) %></td>
Game Model:
Takes me to the view game view with the URL:
http:// local host:3000/tournaments/2/game/new
And view:
<h1>New Game in <%= #tournament.name %> Tournament</h1>
<fieldset>
<%= form_for [:tournament, #game], :url => tournament_game_index_path do |f| %>
<table>
<td>
.... More fields .....
</td>
<div class="form-actions">
<%= f.submit "Create %>
</div>
<% end %>
When create is clicked it yields the error:
undefined method `game_url' for #<GamesController:0xb6131e40>
Questions:
Should I be using nested routes or hidden fields?
Do I need a separate tournament_game controller / view to handle the tournament game calls?
How do I get it to look for the correct create route when clicking the Create button?
When I want to have a relationship between two tables, do I only need the nested resource and the has_many / belongs_to calls or do I still need a foreign key column such as Tournament?
Sorry for all of the questions in one thread. Any help you can offer would be greatly appreciated!
Thank you.
Edit:
The error references line 39 which would be the line for the create controller.
class GamesController < ApplicationController
# GET /game
# GET /game.json
def index
#game = Game.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #game }
end
end
# GET /game/1
# GET /game/1.json
def show
#game = Game.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #game }
end
end
# GET /game/new
# GET /game/new.json
def new
#game = Game.new
#tournament = Tournament.find(params[:tournament_id])
end
# GET /game/1/edit
def edit
#game = Game.find(params[:id])
end
# POST /game
# POST /game.json
def create
#tournament = Tournament.find(params[:tournament_id])
#game = #tournament.game.build(params[:game])
respond_to do |format|
if params[:commit] != 'Cancel'
if #game.save
format.html { redirect_to #game, notice: 'Game was successfully created.' }
format.json { render json: #game, status: :created, location: #game }
format.json { render json: #game }
else
format.html { render action: "new" }
format.json { render json: #game.errors, status: :unprocessable_entity }
end
else
format.html { redirect_to #game, alert: 'Game was not updated.' }
end
end
end
# PUT /game/1
# PUT /game/1.json
def update
#game = Game.find(params[:id])
respond_to do |format|
if params[:commit] != 'Cancel'
if #game.update_attributes(params[:game])
format.html { redirect_to #game, notice: 'Game was successfully updated.' }
format.json { render json: #game }
else
format.html { render action: "edit" }
format.json { render json: #game.errors, status: :unprocessable_entity }
end
else
format.html { redirect_to #game, alert: 'Game was not updated.' }
end
end
end
# DELETE /game/1
# DELETE /game/1.json
def destroy
#game = Game.find(params[:id])
#game.destroy
respond_to do |format|
format.html { redirect_to game_url }
format.json { head :no_content }
end
end
end
Try this:
<%= form_for #game, :url => tournament_games_path(#tournament) do |f| %>
This will call the create method of games controller
Game Controller:
def create
#tournament = Tournament.find(params[:tournament_id])
#game = #tournament.games.build(params[:game])
if #game.save
flash[:success] = "Game created successfully"
redirect_to tournaments_path
else
render new_tournament_game_path
end
end
Routes:
resources :tournaments do
resources :games, :only => [:new, :index, :create, :update, :destroy]
end
I have a users table (Devise) , with a column "admin" (boolean) to qualify my users.
I also have a namespace "Backend".
I would like that my admins users can create new users from the backend namespace.
So I created a Backend::UsersController :
class Backend::UsersController < ApplicationController
layout 'admin'
before_filter :authenticate_user!
def index
#auteurs = User.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #auteurs }
end
end
def new
#auteur = User.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #auteur }
end
end
def create
#auteur = User.new(params[:auteur])
respond_to do |format|
if #auteur.save
format.html { redirect_to #auteur, notice: 'Article was successfully created.' }
format.json { render json: #auteur, status: :created, location: #auteur }
else
format.html { render action: "new" }
format.json { render json: #auteur.errors, status: :unprocessable_entity }
end
end
end
end
Here's the "_form" partial called in the "new" view :
<%= simple_form_for(#auteur) do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<%= f.input :email %>
</div>
<div class="form-actions">
<%= f.button :submit %>
</div>
<% end %>
An here's my routes :
namespace :backend do
resources :articles
root to: "articles#index"
resources :accueil
resources :users
get "users/index"
get "users/create"
get "users/new"
end
devise_for :users
But when I try to access to "backend/users/new", it drives me to this error :
NoMethodError in Backend/users#new
Showing C:/Ruby/acturevue/app/views/backend/users/_form.html.erb where line #1 raised:
undefined method `users_path' for #<#<Class:0x39616b0>:0x416f6d0>
Does somebody have any ideas of the source of the problem ?
Thanks
UPDATE
So, I modified my code like that :
In Backend::UsersController :
def new
#user = User.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #user}
end
end
def create
#user = User.new(params[:user])
respond_to do |format|
if #user.save
format.html { redirect_to backend_users_path(#user), notice: 'Article was successfully created.' }
format.json { render json: #user, status: :created, location: #user }
else
format.html { render action: "new" }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
In _form :
<%= simple_form_for(#user) do |f| %>
But I still have the error.
However the backend_users_path exists in y routes :
backend_users GET /backend/users(.:format) backend/users#
index
POST /backend/users(.:format) backend/users#
create
new_backend_user GET /backend/users/new(.:format) backend/users#
new
edit_backend_user GET /backend/users/:id/edit(.:format) backend/users#
edit
backend_user GET /backend/users/:id(.:format) backend/users#
show
PUT /backend/users/:id(.:format) backend/users#
update
DELETE /backend/users/:id(.:format) backend/users#
destroy
You need to use the namespace in your redirect:
redirect_to [:backend, #auteur] #...
See my answer to this question.