ActionController::UrlGenerationError in ModelController#create - ruby-on-rails

Working in a Rails app with a model called Shootings. It has several fields in it, so I'm using the Wicked gem to collect them in several steps.
I'm able to create Shooting records correctly, and I'm able to start the Wicked wizard correctly if I manually type the path. However I'm not able to set the redirection after the Shooting creationg with the first step of the wizard.
I get this error in the build_controller.rb once I try to redirect after I create the shooting, to the first step of the wizard
No route matches {:action=>"show", :controller=>"shootings/build", :shooting_id=>#<Shooting id: 100, title: "cwe AVER", created_at: "2021-02-13 20:01:26.212909000 +0000", updated_at: "2021-02-13 20:01:26.212909000 +0000", user_id: 1, typeshooting: nil, numberimages: nil, proservices: nil, goals: nil, status: nil>}, missing required keys: [:id]
I'll let the code speak for itself
shootings_controller.rb
class ShootingsController < ApplicationController
before_action :set_shooting, only: %i[ show edit update destroy ]
# GET /shootings/new
def new
#shooting = Shooting.new
end
# POST /shootings or /shootings.json
def create
#shooting = Shooting.new(shooting_params)
respond_to do |format|
if #shooting.save
format.html { redirect_to shooting_build_path(#shooting), notice: "Shooting was successfully created." }
format.json { render :show, status: :created, location: #shooting }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: #shooting.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /shootings/1 or /shootings/1.json
def update
respond_to do |format|
if #shooting.update(shooting_params)
format.html { redirect_to #shooting, notice: "Shooting was successfully updated." }
format.json { render :show, status: :ok, location: #shooting }
else
format.html { render :edit, status: :unprocessable_entity }
format.json { render json: #shooting.errors, status: :unprocessable_entity }
end
end
end
end
build_controler.rb (in controllers > shootings)
class Shootings::BuildController < ApplicationController
include Wicked::Wizard
steps :add_typeshooting, :add_numberimages, :add_proservices, :add_goals
def show
#shooting = Shooting.find(params[:shooting_id])
render_wizard
end
def update
#shooting = Shooting.find(params[:shooting_id])
params[:shooting][:status] = 'active' if step == steps.last
#shooting.update(shooting_params)
render_wizard #shooting
end
def create
#shooting = Shooting.create
redirect_to wizard_path(steps.first, shooting_id: #shooting.id)
end
private
def redirect_to_finish_wizard options = nil, params = {}
redirect_to root_url, notice: 'Thanks for your shooting'
end
# Only allow a list of trusted parameters through.
def shooting_params
params.require(:shooting).permit(:title, :user_id, :typeshooting, :numberimages, :proservices, :goals)
end
def set_shooting
#shooting = Shooting.find(params[:id])
end
end
routes.rb
Rails.application.routes.draw do
resources :users
resources :shootings do
resources :build, controller: 'shootings/build'
end
resources :photos
# For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
root "shootings#index"
end
and rail routes
shooting_build_index GET /shootings/:shooting_id/build(.:format) shootings/build#index
POST /shootings/:shooting_id/build(.:format) shootings/build#create
new_shooting_build GET /shootings/:shooting_id/build/new(.:format) shootings/build#new
edit_shooting_build GET /shootings/:shooting_id/build/:id/edit(.:format) shootings/build#edit
shooting_build GET /shootings/:shooting_id/build/:id(.:format) shootings/build#show
PATCH /shootings/:shooting_id/build/:id(.:format) shootings/build#update
PUT /shootings/:shooting_id/build/:id(.:format) shootings/build#update
DELETE /shootings/:shooting_id/build/:id(.:format) shootings/build#destroy
shootings GET /shootings(.:format) shootings#index
POST /shootings(.:format) shootings#create
new_shooting GET /shootings/new(.:format) shootings#new
edit_shooting GET /shootings/:id/edit(.:format) shootings#edit
shooting GET /shootings/:id(.:format) shootings#show
PATCH /shootings/:id(.:format) shootings#update
PUT /shootings/:id(.:format) shootings#update
DELETE /shootings/:id(.:format) shootings#destroy
shootings form
<%= form_with(model: shooting) do |form| %>
<% if shooting.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(shooting.errors.count, "error") %> prohibited this shooting from being saved:</h2>
<ul>
<% shooting.errors.each do |error| %>
<li><%= error.full_message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= form.label :title %>
<%= form.text_field :title %>
</div>
<div class="field">
<%= form.label :user_id %>
<%= form.text_field :user_id %>
</div>
<div class="actions">
<%= form.submit %>
</div>
<% end %>

You have to change following url, and it is working
format.html {
flash.now[:notice] = 'Shooting was successfully created.'
redirect_to shooting_build_index_path(#shooting)
}
Or rails way
format.html do
flash.now[:notice] = 'Shooting was successfully created.'
redirect_to shooting_build_index_path(#shooting)
end
But personally I think it should work like above but some how it is not working.

Related

can't save to database with hidden field

I have 2 models, one of patients and another of indicadions, I think I have the relationships between the models correctly placed, what I cannot make it work is that the patient_id is placed in the hidden field
my models:
patient: has_many :prescription, dependent: :destroy
indication: belongs_to :patient
my view:
<%= form_with(model: prescription) do |form| %>
<% if prescription.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(prescription.errors.count, "error") %> prohibited this prescription from being saved:</h2>
<ul>
<% prescription.errors.each do |error| %>
<li><%= error.full_message %></li>
<% end %>
</ul>
</div>
<% end %>
<%= form.hidden_field :patient_id, value: "patient_id" %>
<div class="form-group">
<%= form.label :content %>
<%= form.text_area :content, class:'form-control' %>
</div>
<%= form.submit "SAVE",class:'btn save' %>
<% end %>
The controller:
class PrescriptionsController < ApplicationController
before_action :set_prescription, only: %i[ show edit update destroy ]
# GET /prescriptions or /prescriptions.json
def index
#prescriptions = Prescription.all
end
# GET /prescriptions/1 or /prescriptions/1.json
def show
end
# GET /prescriptions/new
def new
#prescription = Prescription.new
end
# GET /prescriptions/1/edit
def edit
end
# POST /prescriptions or /prescriptions.json
def create
#prescription = Prescription.new(prescription_params)
respond_to do |format|
if #prescription.save
format.html { redirect_to #prescription, notice: "La receta se creó con éxito." }
format.json { render :show, status: :created, location: #prescription }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: #prescription.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /prescriptions/1 or /prescriptions/1.json
def update
respond_to do |format|
if #prescription.update(prescription_params)
format.html { redirect_to #prescription, notice: "Prescription was successfully updated." }
format.json { render :show, status: :ok, location: #prescription }
else
format.html { render :edit, status: :unprocessable_entity }
format.json { render json: #prescription.errors, status: :unprocessable_entity }
end
end
end
# DELETE /prescriptions/1 or /prescriptions/1.json
def destroy
#prescription.destroy
respond_to do |format|
format.html { redirect_to prescriptions_url, notice: "Prescription was successfully destroyed." }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_prescription
#prescription = Prescription.find(params[:id])
end
# Only allow a list of trusted parameters through.
def prescription_params
params.require(:prescription).permit(:content, :patient_id)
end
end
Instead of using a hidden input you might actually want to nest the routes to makes the relationship explicit instead of implicit:
resources :patients do
resources :perscriptions, shallow: true
end
class PrescriptionsController < ApplicationController
before_action :set_patient
before_action :set_prescription, only: %i[ show edit update destroy ]
# GET /patients/1/prescriptions or /patients/1/prescriptions.json
def index
#prescriptions = #patient.perscriptions
end
# GET /prescriptions/1 or /prescriptions/1.json
def show
end
# GET /patients/1/prescriptions/new
def new
#prescription = Prescription.new
end
# GET /prescriptions/1/edit
def edit
end
# POST /patients/1/prescriptions or /patients/1/prescriptions.json
def create
#prescription = #patient.perscriptions.new(prescription_params)
respond_to do |format|
if #prescription.save
format.html { redirect_to #prescription, notice: "La receta se creó con éxito." }
format.json { render :show, status: :created, location: #prescription }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: #prescription.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /prescriptions/1 or /prescriptions/1.json
def update
respond_to do |format|
if #prescription.update(prescription_params)
format.html { redirect_to #prescription, notice: "Prescription was successfully updated." }
format.json { render :show, status: :ok, location: #prescription }
else
format.html { render :edit, status: :unprocessable_entity }
format.json { render json: #prescription.errors, status: :unprocessable_entity }
end
end
end
# DELETE /prescriptions/1 or /prescriptions/1.json
def destroy
#prescription.destroy
respond_to do |format|
format.html { redirect_to prescriptions_url, notice: "Prescription was successfully destroyed." }
format.json { head :no_content }
end
end
private
def set_patient
#patient = Patient.find(params[:patient_id])
end
def set_prescription
#prescription = Prescription.find(params[:id])
end
# Only allow a list of trusted parameters through.
def prescription_params
params.require(:prescription).permit(:content)
end
end
<%= form_with(model: [#patient, #perscription]) do |form| %>
<% if prescription.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(prescription.errors.count, "error") %> prohibited this prescription from being saved:</h2>
<ul>
<% prescription.errors.each do |error| %>
<li><%= error.full_message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="form-group">
<%= form.label :content %>
<%= form.text_area :content, class:'form-control' %>
</div>
<%= form.submit "SAVE", class:'btn save' %>
<% end %>

How to update created_by field in scaffolding generated code?

I use devise gem for authentication. I generated a scaffold for model M. I would like to update the created_by field with the user id from the login page. How do I achieve this?
I have 2 fields in the model F1 and F2.
The form that scaffold creates shows input for users to enter values for F1 and F2. How do I update the value for created_by field using the current_user from devise? Because the create action seems to be entering only the fields from the form.
<%= form_with(model: M, local: true) do |form| %>
<% if M.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(M.errors.count, "error") %> prohibited this movie from being saved:</h2>
<ul>
<% M.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= form.label :F1 %>
<%= form.text_field :F1 %>
</div>
<div class="field">
<%= form.label :F2 %>
<%= form.text_field :F2 %>
</div>
<div class="actions">
<%= form.submit %>
</div>
<% end %>
How to I update the model with current_user value in the above form without exposing that field to the user?
This is my controller:
class MsController < ApplicationController
before_action :set_M, only: [:show, :edit, :update, :destroy]
# GET /Ms
# GET /Ms.json
def index
#Ms = M.all
#categories = #Ms.uniq.pluck(:category)
#Ms_by_category = Hash.new
#categories.each do |category|
#Ms_by_category[category] = M.where(:category => category)
end
end
# GET /Ms/1
# GET /Ms/1.json
def show
end
# GET /Ms/new
def new
#M = M.new
end
# GET /Ms/1/edit
def edit
end
# POST /Ms
# POST /Ms.json
def create
#M = M.new(M_params)
respond_to do |format|
if #M.save
format.html { redirect_to #M, notice: 'M was successfully created.' }
format.json { render :show, status: :created, location: #M }
else
format.html { render :new }
format.json { render json: #M.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /Ms/1
# PATCH/PUT /Ms/1.json
def update
respond_to do |format|
if #M.update(M_params)
format.html { redirect_to #M, notice: 'M was successfully updated.' }
format.json { render :show, status: :ok, location: #M }
else
format.html { render :edit }
format.json { render json: #M.errors, status: :unprocessable_entity }
end
end
end
# DELETE /Ms/1
# DELETE /Ms/1.json
def destroy
#M.destroy
respond_to do |format|
format.html { redirect_to Ms_url, notice: 'M was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_M
#M = M.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def M_params
params.require(:M).permit(:title, :category, :rating)
end
end
So simple in creating action change your method, for example, you just need to create the client
before_action :authenticate_user!
def create
#client = Client.new(name: params[:name], address: params[:address],created_by: current_user.email )
if #client.save
redirect_to #client
else
render 'new'
end
end
There should be a field like created_by exist in the table.
You need to add users reference to M model and add associations. created_by is not the best name for it. Let imagine that M is abbreviation for Music. In this case you need to create a migration
add_reference :musics, :user
Add to the Music model
belongs_to :user
And to the User model
has_many :musics
And change in the controller
def new
#music = current_user.musics.new
end
def create
#music = current_user.musics.new(M_params)
respond_to do |format|
if #music.save
format.html { redirect_to #music, notice: 'Music was successfully created.' }
format.json { render :show, status: :created, location: #music }
else
format.html { render :new }
format.json { render json: #music.errors, status: :unprocessable_entity }
end
end
end

Ruby on Rails Goal has-many Steps association. How to create steps for a goal?

I'm trying to create a has-many association within a ruby on rails app where a user has-many goals and a goal has-many steps
I can't seem to figure out how to link the creation of a Step for a certain Goal. I've been playing around with it for a while and looking around on here but haven't found a solution.
Below are my Goal_controller, Step_Controller, Step form, and Goal form
Goal Controller:
class GoalsController < ApplicationController
before_action :set_goal, only: [:show, :edit, :update, :destroy]
before_filter :authorize
# GET /goals
# GET /goals.json
def index
#goals = Goal.all
end
# GET /goals/1
# GET /goals/1.json
def show
#goal = Goal.find(params[:id])
session[:current_goal] = #goal.id
end
# GET /goals/new
def new
#goal = Goal.new
end
# GET /goals/1/edit
def edit
end
# POST /goals
# POST /goals.json
def create
#goal = current_user.goals.new(goal_params)
respond_to do |format|
if #goal.save
format.html { redirect_to #goal, notice: 'Goal was successfully created.' }
format.json { render :show, status: :created, location: #goal }
else
format.html { render :new }
format.json { render json: #goal.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /goals/1
# PATCH/PUT /goals/1.json
def update
respond_to do |format|
if #goal.update(goal_params)
format.html { redirect_to #goal, notice: 'Goal was successfully updated.' }
format.json { render :show, status: :ok, location: #goal }
else
format.html { render :edit }
format.json { render json: #goal.errors, status: :unprocessable_entity }
end
end
end
# DELETE /goals/1
# DELETE /goals/1.json
def destroy
#goal.destroy
respond_to do |format|
format.html { redirect_to goals_url, notice: 'Goal was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_goal
#goal = Goal.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def goal_params
params.require(:goal).permit(:Goal, :Description, :Date, :DueDate, :user_id)
end
end
Step Controller:
class StepsController < ApplicationController
#before_action :set_step, only: [:show, :edit, :update, :destroy]
before_filter :authorize
# GET /steps
# GET /steps.json
def index
#steps = Goal.find(params[:goal_id]).steps.all
end
def new
#step = Goal.find(params[:goal_id]).steps.new
end
# GET /steps/1
# GET /steps/1.json
def show
end
# GET /steps/1/edit
def edit
end
def create
#step = Goal.find(params[:goal_id]).steps.new(step_params)
respond_to do |format|
if #step.save
format.html { redirect_to #step, notice: 'Step was successfully created.' }
format.json { render :show, status: :created, location: #step }
else
format.html { render :new }
format.json { render json: #step.errors, status: :unprocessable_entity }
end
end
redirect_to(goal_steps_url(#goal))
end
def update
#step.update(step_params)
respond_to do |format|
if #step.update(step_params)
format.html { redirect_to #step, notice: 'Step was successfully updated.' }
format.json { render :show, status: :ok, location: #step }
else
format.html { render :edit }
format.json { render json: #step.errors, status: :unprocessable_entity }
end
end
end
# POST /steps
# POST /steps.json
def destroy
#step.destroy
respond_to do |format|
format.html { redirect_to steps_url, notice: 'Step was successfully destroyed.' }
format.json { head :no_content }
end
end
private
def set_step
#step = Goal.find(params[:goal_id]).Step.find(params[:id])
end
def step_params
params.require(:step).permit(:requirement, :completionTime, :goal_id)
end
end
Step Form:
<%= form_for(#step) do |f| %>
<% if #step.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#step.errors.count, "error") %> prohibited this step from being saved:</h2>
<ul>
<% #step.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :requirement %><br>
<%= f.text_field :requirement %>
</div>
<div class="field">
<%= f.label :completionTime %><br>
<%= f.number_field :completionTime %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Goal Form:
<%= form_for(#goal) do |f| %>
<% if #goal.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#goal.errors.count, "error") %> prohibited this goal from being saved:</h2>
<ul>
<% #goal.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :Goal %><br>
<%= f.text_field :Goal %>
</div>
<div class="field">
<%= f.label :Description %><br>
<%= f.text_area :Description %>
</div>
<div class="field">
<%= f.label :Date %><br>
<%= f.date_select :Date %>
</div>
<div class="field">
<%= f.label :DueDate %><br>
<%= f.date_select :DueDate %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
It looks like you will be missing your goal_id when you submit your step creation form. You will need to store it either in a hidden field in your step form, or as part of the route (e.g. POST /goals/10/steps).

Post and Location Association with ancestry gem

My Rails application have two model. Location and Post, Location have many post.I am Using
ancestry gem.
class Post < ActiveRecord::Base
belongs_to :location, :counter_cache => true
end
class Location < ActiveRecord::Base
include Tree
has_ancestry :cache_depth => true
has_many :posts
end
My Post Controller
class PostsController < ApplicationController
before_action :set_post, only: [:show, :edit, :update, :destroy]
def index
#posts = Post.all
end
def show
end
def new
#post = Post.new
end
def edit
end
def create
#post = Post.new(post_params)
respond_to do |format|
if #post.save
format.html { redirect_to #post, notice: 'Post was successfully created.' }
format.json { render action: 'show', status: :created, location: #post }
else
format.html { render action: 'new' }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #post.update(post_params)
format.html { redirect_to #post, notice: 'Post was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
def destroy
#post.destroy
respond_to do |format|
format.html { redirect_to posts_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_post
#post = Post.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def post_params
params.require(:post).permit(:name)
end
end
If i am create new Post with which Location belongs in _form.html.erb
<%= form_for(#post) do |f| %>
<% if #post.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#post.errors.count, "error") %> prohibited this post from being saved: </h2>
<ul>
<% #post.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<%= select :location_id, Location.all.at_depth(4) { |l| [ l.name, l.id ] } %>
<div class="actions">
<%= f.submit %>
</div>
Browser show error message which is display bellow
ArgumentError in Posts#new
Not sure if this fixes your error, but:
To make the dropdown working, change the select line to:
<%= f.select :location_id, Location.all.at_depth(4) { |l| [ l.name, l.id ] } %>
This is because you want the formbuilder f to handle the creation of the form element.
You also have to whitelist the :location_id parameter in the controller:
def post_params
params.require(:post).permit(:name, :location_id)
end

Getting a "NoMethodError in Boards#show" error when going to #new action (not trying to access a method, and the variable exists)

I'm very new to Ruby on Rails, so forgive if this is a stupid mistake.
I used a rails generate scaffold command to generate a "board" scaffold with a title:string and message:text. Now, I'm trying to go to localhost:3000/boards/new and I'm getting a "NoMethodError in Boards#show" error when I try to access board.message. I don't get any error when I try to access board.title.
Code:
form.html.erb
<%= form_for(#board) do |f| %>
<% if #board.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#board.errors.count, "error") %> prohibited this board from being saved:</h2>
<ul>
<% #board.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :title %><br />
<%= f.text_field :title %>
</div>
<div class="field">
<%= f.label :message %><br />
<%= f.text_area :message %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
I'm specifically getting the error on line 20 (<%= f.text_area :message %>)
board.rb
class Board < ActiveRecord::Base
attr_accessible :message, :title
has_many :posts
end
*boards_controller.rb*
class BoardsController < ApplicationController
# GET /boards
# GET /boards.json
def index
#boards = Board.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #boards }
end
end
# GET /boards/1
# GET /boards/1.json
def show
#board = Board.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #board }
end
end
# GET /boards/new
# GET /boards/new.json
def new
#board = Board.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #board }
end
end
# GET /boards/1/edit
def edit
#board = Board.find(params[:id])
end
# POST /boards
# POST /boards.json
def create
#board = Board.new(params[:board])
respond_to do |format|
if #board.save
format.html { redirect_to #board, notice: 'Board was successfully created.' }
format.json { render json: #board, status: :created, location: #board }
else
format.html { render action: "new" }
format.json { render json: #board.errors, status: :unprocessable_entity }
end
end
end
# PUT /boards/1
# PUT /boards/1.json
def update
#board = Board.find(params[:id])
respond_to do |format|
if #board.update_attributes(params[:board])
format.html { redirect_to #board, notice: 'Board was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #board.errors, status: :unprocessable_entity }
end
end
end
# DELETE /boards/1
# DELETE /boards/1.json
def destroy
#board = Board.find(params[:id])
#board.destroy
respond_to do |format|
format.html { redirect_to boards_url }
format.json { head :no_content }
end
end
end
routes.rb
Anonymous::Application.routes.draw do
resources :boards
resources :posts
root :to => "boards#index"
end
Can anyone please explain this to me?

Resources