Cannot use nested routes create - ruby-on-rails

Struggling to get the create working for my nested routes in the following controller:
class BooksController < ApplicationController
before_action :set_book, only: [:show, :edit, :update, :destroy]
before_filter :load_author
# GET /books
# GET /books.json
def index
#books = #author.books.all
end
# GET /books/1
# GET /books/1.json
def show
end
# GET /books/new
def new
#book = #author.books.new
end
# GET /books/1/edit
def edit
end
# POST /books
# POST /books.json
def create
#book = #auhtor.books.new(book_params)
respond_to do |format|
if #book.save
format.html { redirect_to [#parent, #child], notice: 'Book was successfully created.' }
format.json { render :show, status: :created, location: #book }
else
format.html { render :new }
format.json { render json: #book.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /books/1
# PATCH/PUT /books/1.json
def update
respond_to do |format|
if #book.update(book_params)
format.html { redirect_to #book, notice: 'Book was successfully updated.' }
format.json { render :show, status: :ok, location: #book }
else
format.html { render :edit }
format.json { render json: #book.errors, status: :unprocessable_entity }
end
end
end
# DELETE /books/1
# DELETE /books/1.json
def destroy
#book.destroy
respond_to do |format|
format.html { redirect_to books_url, notice: 'Book was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_book
#book = Book.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def book_params
params.require(:book).permit(:name, :author_id)
end
def load_author
#author = Author.find(params[:author_id])
end
end
I am getting the following error on line #29:
undefined method `books' for nil:NilClass
Any ideas? It correctly populates the author_id field in the create view but when i click save I get this error.

I'm sure you will laugh out loud after getting solution of the issue.
You have MIS-SPELLED instance object as #auhtor. It should be #author in first line of create action.
#book = #author.books.new(book_params)

Related

Ruby - how to integrate ruby gem into my controller?

I have created this gem > https://rubygems.org/gems/badwordgem
This is my controller inside my rails project.
class AppointmentsController < ApplicationController
before_action :set_appointment, only: %i[ show edit update destroy ]
#before we run anything if the user is not signed in show index and show functions
before_action :authenticate_user!, except: [:index,:show]
#only the correct user can edit,update and destroy
before_action :correct_user, only: [:edit, :update , :destroy]
# GET /appointments or /appointments.json
def index
#appointments = Appointment.all.decorate
end
# GET /appointments/1 or /appointments/1.json
def show
end
# GET /appointments/new
def new
##appointment = Appointment.new
#appointment = current_user.appointments.build
end
# GET /appointments/1/edit
def edit
end
#function to allow for search functionality
def search
#appointments = Appointment.where("date LIKE?", "%"+params[:q]+"%")
end
# POST /appointments or /appointments.json
def create
##appointment = Appointment.new(appointment_params)
#appointment = current_user.appointments.build(appointment_params)
respond_to do |format|
if #appointment.save
format.html { redirect_to appointment_url(#appointment), notice: "Appointment was successfully created." }
format.json { render :show, status: :created, location: #appointment }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: #appointment.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /appointments/1 or /appointments/1.json
def update
respond_to do |format|
if #appointment.update(appointment_params)
format.html { redirect_to appointment_url(#appointment), notice: "Appointment was successfully updated." }
format.json { render :show, status: :ok, location: #appointment }
else
format.html { render :edit, status: :unprocessable_entity }
format.json { render json: #appointment.errors, status: :unprocessable_entity }
end
end
end
# DELETE /appointments/1 or /appointments/1.json
def destroy
#appointment.destroy
respond_to do |format|
format.html { redirect_to appointments_url, notice: "Appointment was successfully destroyed." }
format.json { head :no_content }
end
end
#function here that restricts editing so the current logged in user can edit only their records
def correct_user
#appointment = current_user.appointments.find_by(id: params[:id])
redirect_to appointments_path, notice:"NOT ALLOWED TO EDIT THIS" if #appointment.nil?
end
private
# Use callbacks to share common setup or constraints between actions.
def set_appointment
#appointment = Appointment.find(params[:id])
end
# Only allow a list of trusted parameters through.
def appointment_params
params.require(:appointment).permit(:barber, :customer, :notes, :date,:user_id)
end
end
In my schema for the appointment model I have the column 'notes' which is where I want to filter bad words.
I want to integrate Badwordgem::Base.sanitize() into my controller so I can filter bad words when I am creating the appointment.
I've tried adding it here like so
def create
##appointment = Appointment.new(appointment_params)
#appointment.notes = Badwordgem::Base.sanitize(#appointment.notes)
#appointment = current_user.appointments.build(appointment_params)
but that throws undefined method `notes' for nil:NilClass
The gem has been tested with IRB and works. I am at a loss as to how to implement it inside my own rails project.
Where inside my controller do I add the method?
I would consider moving that logic into the model.
For example as a custom setter method:
# in app/models/appointment.rb
def notes=(notes)
sanitized_notes = Badwordgem::Base.sanitize(notes)
super(sanitized_notes)
end
Or as a before_validation:
# in app/models/appointment.rb
before_validation :sanitize_notes
private
def sanitize_notes
self.notes = Badwordgem::Base.sanitize(notes)
end
Both versions have the advantage that they make sure all notes are sanitized no matter how they are created and not just in this specific controller method. For example when you import Appointments via a rake task or the Rails console. Additionally, this makes testing a bit easier and you can use the default pattern in the controller like this:
#appointment = current_user.appointments.build(appointment_params)
respond_to do |format|
if #appointment.save
# ...
Funny how once you post you figure it out. . .
I added this inside my create function it to filter the bad words.
def create
##appointment = Appointment.new(appointment_params)
#appointment = current_user.appointments.build(appointment_params)
#appointment.notes = Badwordgem::Base.sanitize(#appointment.notes)
respond_to do |format|
if #appointment.save
format.html { redirect_to appointment_url(#appointment), notice: "Appointment was successfully created." }
format.json { render :show, status: :created, location: #appointment }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: #appointment.errors, status: :unprocessable_entity }
end
end
end

how can i access boolean value to other controller in rails

i have ProjectSite model and ManagerRemark model related to many to one association. my MangerRemark model has boolean value true and false i want to access that boolean value to other controller view. please help. here is my code.i want to print decision boolean value next to each project site index list how can i do that? in other controller name new_manager_controller view
project_sites_controller.rb
class ProjectSitesController < ApplicationController
before_action :authenticate_user!
before_action :is_project_site?, except: [:show]
before_action :set_project_site, only: [:show, :edit, :update, :destroy]
# GET /project_sites
# GET /project_sites.json
def index
#project_sites = ProjectSite.all.order("created_at DESC")
end
# GET /project_sites/1
# GET /project_sites/1.json
def show
#manager_remark = ManagerRemark.new
#manager_remark.project_site_id = #project_site.id
end
# GET /project_sites/new
def new
#project_site = ProjectSite.new
end
# GET /project_sites/1/edit
def edit
end
# POST /project_sites
# POST /project_sites.json
def create
#project_site = ProjectSite.new(project_site_params)
respond_to do |format|
if #project_site.save
format.html { redirect_to #project_site, notice: 'Project site was successfully created.' }
format.json { render :show, status: :created, location: #project_site }
else
format.html { render :new }
format.json { render json: #project_site.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /project_sites/1
# PATCH/PUT /project_sites/1.json
def update
respond_to do |format|
if #project_site.update(project_site_params)
format.html { redirect_to #project_site, notice: 'Project site was successfully updated.' }
format.json { render :show, status: :ok, location: #project_site }
else
format.html { render :edit }
format.json { render json: #project_site.errors, status: :unprocessable_entity }
end
end
end
# DELETE /project_sites/1
# DELETE /project_sites/1.json
def destroy
#project_site.destroy
respond_to do |format|
format.html { redirect_to project_sites_url, notice: 'Project site was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_project_site
#project_site = ProjectSite.find(params[:id])
end
# Never trust parameters frmanager_level_twoom the scary internet, only allow the white list through.
def project_site_params
params.require(:project_site).permit(:name, :date, :file)
end
def is_project_site?
redirect_to root_path unless (current_user.role=='project_site')
end
end
This is how my manage remark controller looks.
Manager_Remarks_controller.rb
class ManagerRemarksController < ApplicationController
def create
#manager_remark = ManagerRemark.new(remark_params)
#manager_remark.project_site_id = params[:project_site_id]
#manager_remark.save
redirect_to project_site_path(#manager_remark.project_site)
end
def remark_params
params.require(:manager_remark).permit(:name, :remark, :decision)
end
end

Rails 5 multiple nested attributes no Routing Error uninitialized constant Sites

Hello I have a little app with three nested models Client, Site and Damper. When I add a client or client_site all is fine... but when i come to add a damper I get
Routing Error
uninitialized constant Sites
in the console
Started GET "/clients/1/sites/1/dampers/new" for my ip at 2018-10-26 18:05:29 +1000
ActionController::RoutingError (uninitialized constant Sites):
app/controllers/clients/sites/dampers_controller.rb:1:in `<main>'
Routes
resources :clients do
resources :sites, controller: 'clients/sites' do
resources :dampers, controller: 'clients/sites/dampers'
end
end
Models
app/models/client.rb
class Client < ApplicationRecord
has_many :sites
end
app/models/site.rb
class Site < ApplicationRecord
belongs_to :client
has_many :dampers
end
app/models/damper.rb
class Damper < ApplicationRecord
belongs_to :site
end
please note I had made a mistake and this was originally :sites but even after changing this the fault remained.
Controllers
app/controllers/clients_controller.rb
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
#client = Client.find(params[:id])
#sites = #client.sites
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(:name)
end
end
app/controllers/clients/sites_controller.rb
class Clients::SitesController < ApplicationController
before_action :set_client
before_action :set_site, except: [:new, :create]
# GET /sites
# GET /sites.json
def index
#sites = Site.all
end
# GET /sites/1
# GET /sites/1.json
def show
#client = Client.find(params[:client_id])
#site = #client.sites.find(params[:id])
end
# GET /sites/new
def new
#site = Site.new
end
# GET /sites/1/edit
def edit
end
# POST /sites
# POST /sites.json
def create
#site = Site.new(site_params)
#site.client = #client
respond_to do |format|
if #site.save
format.html { redirect_to #client, notice: 'Site 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 /sites/1
# PATCH/PUT /sites/1.json
def update
respond_to do |format|
if #site.update(site_params)
format.html { redirect_to #client, notice: 'Site was successfully updated.' }
format.json { render :show, status: :ok, location: #site }
else
format.html { render :edit }
format.json { render json: #client.errors, status: :unprocessable_entity }
end
end
end
# DELETE /sites/1
# DELETE /sites/1.json
def destroy
#site.destroy
respond_to do |format|
format.html { redirect_to sites_url, notice: 'Site was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_site
#site = Site.find(params[:id])
end
def set_client
#client = Client.find(params[:client_id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def site_params
params.require(:site).permit(:name, :client_id)
end
end
app/controllers/clients/sites/dampers_controller.rb
class Sites::DampersController < ApplicationController
before_action :set_client
before_action :set_site
before_action :set_damper, except: [:new, :create]
# GET /dampers
# GET /dampers.json
def index
#dampers = Damper.all
end
# GET /dampers/1
# GET /dampers/1.json
def show
end
# GET /dampers/new
def new
#damper = Damper.new
end
# GET /dampers/1/edit
def edit
end
# POST /dampers
# POST /dampers.json
def create
#damper = Damper.new(damper_params)
#damper.site = #site
respond_to do |format|
if #damper.save
format.html { redirect_to #site, notice: 'Damper was successfully created.' }
format.json { render :show, status: :created, location: #site }
else
format.html { render :new }
format.json { render json: #site.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /dampers/1
# PATCH/PUT /dampers/1.json
def update
respond_to do |format|
if #damper.update(damper_params)
format.html { redirect_to #site, notice: 'Damper was successfully updated.' }
format.json { render :show, status: :ok, location: #site }
else
format.html { render :edit }
format.json { render json: #site.errors, status: :unprocessable_entity }
end
end
end
# DELETE /dampers/1
# DELETE /dampers/1.json
def destroy
#damper.destroy
respond_to do |format|
format.html { redirect_to dampers_url, notice: 'Damper was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_damper
#damper = Damper.find(params[:id])
end
def set_site
#site = Site.find(params[:site_id])
end
def set_client
#client = Client.find(params[:client_id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def damper_params
params.require(:damper).permit(:location, :number, :site_id, :client_id)
end
end
ActionController::RoutingError (uninitialized constant Sites)
The dampers_controller.rb sits under controllers/clients/sites, so you need to change the class name to
class Clients::Sites::DampersController < ApplicationController
instead of
class Sites::DampersController < ApplicationController
for the sake of namespacing
Also, I recommend you to have a look at controller-namespaces-and-routing
You created a controller named Sites::DampersController, which is a class DampersController defined inside the namespace (module, class,...) named Sites, but you forgot to define this last one.
You could create it this way:
module Sites
class DampersController < ApplicationController
end
end
Or just get rid of the Sites:: part.
You will also need to update your routes, to specify the correct controller name.
More generally, it is easier to follow rails default route generation:
resources :clients do
resources :sites do
resources :dampers
end
end
Which will create routes pointing to the following controllers:
ClientsController
SitesController
DampersController
If you really intend on putting the other controllers in a sub folders, following your original routes, you will need to define the following:
controller ClientsController
module Clients
controller SitesController inside module Clients
module Sites inside module Clients
controller DampersController inside module Clients::Sites
Which, for autoloading to works, would have to be organized in subfolders too:
app/controllers
clients_controllers.rb
clients/
sites__controllers.rb
sites/
dampers_controllers.rb

NoMethodError in MoviesController#upvote

I'm working on a project, and for the life of me, I'm not sure what's going on. My code was working earlier, now I'm getting
NoMethodError in MoviesController#upvote
When I try and vote on a certain movie, here is my "movie_controller.rb"
class MoviesController < ApplicationController
before_action :set_movie, only: [:show, :edit, :update, :destroy, :upvote, :downvote]
before_action :authenticate_user!
# GET /movies
# GET /movies.json
def index
#movies = Movie.all
end
# GET /movies/1
# GET /movies/1.json
def show
end
# GET /movies/new
def new
#movie = Movie.new
end
# GET /movies/1/edit
def edit
end
# POST /movies
# POST /movies.json
def create
#movie = Movie.new(movie_params)
respond_to do |format|
if #movie.save
format.html { redirect_to #movie, notice: 'Movie was successfully created.' }
format.json { render :show, status: :created, location: #movie }
else
format.html { render :new }
format.json { render json: #movie.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /movies/1
# PATCH/PUT /movies/1.json
def update
respond_to do |format|
if #movie.update(movie_params)
format.html { redirect_to #movie, notice: 'Movie was successfully updated.' }
format.json { render :show, status: :ok, location: #movie }
else
format.html { render :edit }
format.json { render json: #movie.errors, status: :unprocessable_entity }
end
end
end
# DELETE /movies/1
# DELETE /movies/1.json
def destroy
#movie.destroy
respond_to do |format|
format.html { redirect_to movies_url, notice: 'Movie was successfully destroyed.' }
format.json { head :no_content }
end
end
def upvote
#movie.upvote_from current_user
redirect_to movies_path
end
def downvote
#movie.downvote_from current_user
redirect_to movies_path
end
private
def set_movie
#movies = Movie.find(params[:movie_id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def movie_params
params.require(:movie).permit(:title, :image)
end
end
In particular it's saying there's a problem with is line:
private
def set_movie
#movies = Movie.find(params[:id])
end
I'll also attach my routes for good measure. Thank you guys.
Rails.application.routes.draw do
devise_for :users
root 'home#index'
resources :movies do
put "like", to: "movies#upvote"
put "unlike", to: "movies#downvote"
end
end
The problem is that you are setting a #movies variable instead of #movie. That's why you are getting a undefined method upvote_from' for nil:NilClass def upvote #movie.upvote_from
Change this part of the code
private
def set_movie
#movies = Movie.find(params[:id])
end
to this
private
def set_movie
#movie = Movie.find(params[:id])
end

Current_user in Controller for Rails 4

I have a Listings Controller where Users can Create their Listings.
To prevent users to edit other users listings i just had to update every action from
Listing to current_user.listings
but with Rails 4 the controller got changed and i can't find how to set this up.
My Controller File->
class ListingsController < ApplicationController
before_action :set_listing, only: [:show, :edit, :update, :destroy]
before_filter :authenticate_user!, :only => [:index]
# GET /listings
# GET /listings.json
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 action: 'show', status: :created, location: #listing }
else
format.html { render action: '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 { head :no_content }
else
format.html { render action: '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 }
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(:title, :description)
end
end
Anyone knows a Solution ?
change from #new to build. So, change all #listing = Listing.new to:
#listing = current_user.listings.build
Then, in set_listing change to:
#listing = current_user.listings.find(params[:id])

Resources