I'm quite new to rails and I'm using grape to build an API rails app.
I've been getting this error message after I click on the 'Create Event' button :-
NameError at /events
undefined local variable or method `event_params' for #<EventsController:0x00000008f76400>
The error points to the controller file for events,
class EventsController < ApplicationController
before_action :authenticate_user!
before_action :authenticate_user_from_token!
before_action :set_event, only: [:show, :edit, :update, :destroy]
def index
#events = Event.all
if user_signed_in?
if current_user.is_admin?
#events = Event.all
respond_to do |format|
format.html
format.json { render json: #events }
end
else
#events = current_user.events
respond_to do |format|
format.html
format.json { render json: #events }
end
end
else
render json: {}, status: :unauthorized
end
end
def new
#event = Event.new
end
def edit
end
def create
#event = current_user.events.new(event_params)
respond_to do |format|
if #event.save
format.html { redirect_to #event, notice: 'Event was successfully created.' }
format.json { render :show, status: :created, location: #event }
else
format.html { render :show, notice: 'You are not allowed to view this.' }
format.json { render json: {}, status: :unauthorized}
end
end
end
And here's the event_params method,
def event_params
params.require(:event).permit(:event_name, :event_description, :event_date, :event_time)
end
The log file shows,
Started POST "/events" for 127.0.0.1 at 2015-08-10 14:38:16 +0800
Processing by EventsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"yRVn4uuxpMVejs/gsG004PIi2JRaWnovGBm7TweGgkf2XpTLzjOZNGanCRVVKSPAV6JzNRWmDzRRbq/dC2KOKQ==", "event"=>{"event_name"=>"ddwq", "event_description"=>"rqreqreqr", "event_date(1i)"=>"2015", "event_date(2i)"=>"8", "event_date(3i)"=>"10", "event_time(1i)"=>"2015", "event_time(2i)"=>"8", "event_time(3i)"=>"10", "event_time(4i)"=>"06", "event_time(5i)"=>"38"}, "commit"=>"Create Event"}
[1m[36mUser Load (1.6ms)[0m [1mSELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT 1[0m [["id", 1]]
Completed 500 Internal Server Error in 34ms
NameError - undefined local variable or method `event_params' for #<EventsController:0x000000082a6540>:
app/controllers/events_controller.rb:37:in `create'
actionpack (4.2.0) lib/action_controller/metal/implicit_render.rb:4:in `send_action'
...
...
bin/rails:4:in `<main>'
Started POST "/__better_errors/beb9cf3b65f0e36a/variables" for 127.0.0.1 at 2015-08-10 14:38:16 +0800
def create
#event = current_user.events.new(event_params)
respond_to do |format|
if #event.save
format.html { redirect_to #event, notice: 'Event was successfully created.' }
format.json { render :show, status: :created, location: #event }
else
respond_to do |format|
format.html { render :show, notice: 'You are not allowed to view this.' }
format.json { render json: {}, status: :unauthorized}
end
end ##You have missed the end here
And here's the event_params method,
def event_params
params.require(:event).permit(:event_name, :event_description, :event_date, :event_time)
end
Try build instead of new
replace
#event = current_user.events.new(event_params)
by
#event = current_user.events.build(event_params)`
The error message indicates that, event_params method is not available for the EventsController. I think you mistakenly put the event_params inside another method or missed an end to end the create method. It should be an instance method of your EventsController class.
This code should work as it is:
class EventsController < ApplicationController
before_action :authenticate_user!
before_action :authenticate_user_from_token!
before_action :set_event, only: [:show, :edit, :update, :destroy]
def index
#events = Event.all
if user_signed_in?
if current_user.is_admin?
#events = Event.all
respond_to do |format|
format.html
format.json { render json: #events }
end
else
#events = current_user.events
respond_to do |format|
format.html
format.json { render json: #events }
end
end
else
render json: {}, status: :unauthorized
end
end
def new
#event = Event.new
end
def edit
end
def create
#event = current_user.events.new(event_params)
respond_to do |format|
if #event.save
format.html { redirect_to #event, notice: 'Event was successfully created.' }
format.json { render :show, status: :created, location: #event }
else
format.html { render :show, notice: 'You are not allowed to view this.' }
format.json { render json: {}, status: :unauthorized}
end
end
end
private
def event_params
params.require(:event).permit(:event_name, :event_description, :event_date, :event_time)
end
end
So, the error was a missing 'end' for show method which I didn't post that part.
I completely missed that part because the error was misleading and I assume that it has something to do with the event parameters since the error points there.
Related
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
I'm building a video website and I've been getting this error when I try to add a title to my static page where users can watch a video:
watch.html.erb
<div class="panel panel-default">
<div class="panel-body">
<div class="col-md-4">
<p>You're watching:</p>
<h1><%= #movie.title %></h1>
</div>
</div>
</div>
And here's my movies_controller.rb file:
class MoviesController < ApplicationController
before_action :set_movie, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!, except: [:index, :show]
def watch
end
def index
#movies = Movie.all
end
def show
#reviews = Review.where(movie_id: #movie.id).order("created_at DESC")
end
def new
#movie = current_user.movies.build
end
def edit
end
def create
#movie = current_user.movies.build(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
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
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 set_movie
#movie = Movie.find(params[:id])
end
private
def movie_params
params.require(:movie).permit(:title, :description, :movie_length, :director, :rating, :image)
end
end
My watch method is above "private" in my controller file, which I'm told is one of the primary reasons why this error shows up. But every time I try to go to the page, the error still appears. Can someone tell me what I'm doing wrong?
The error message is very clear: #movie is nil. Nowhere in your watch action do you try to define that variable as anything other than nil, and your before_action callback that populates #movie very clearly does not include watch in the list of actions for which it runs.
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)
I get this error:
NoMethodError in CycleRoadsController#destroy
undefined method `destroy' for nil:NilClass(rails).
This is code from controller and theyt include a method 'destroy ':
respond_to do |format|
if #cycle_road.save
format.html { redirect_to #cycle_road, notice: 'Cycle road was successfully created.' }
format.json { render action: 'show', status: :created, location: #cycle_road }
else
format.html { render action: 'new' }
format.json { render json: #cycle_road.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #cycle_road.update(cycle_road_params)
format.html { redirect_to #cycle_road, notice: 'Cycle road was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #cycle_road.errors, status: :unprocessable_entity }
end
end
end
# DELETE /cycle_roads/1
# DELETE /cycle_roads/1.json
def destroy
#cycle_road.destroy
respond_to do |format|
format.html { redirect_to cycle_roads }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_cycle_road
#cycle_road = CycleRoad.find(params[:id])
end
def cycle_road_params
params.require(:cycle_road).permit(:name, :begin, :finish, :km, :description)
end
end
Anybody know, what's wrong?
Set the instance variable #cycle_road before calling destroy on it.
Currently its nil as the error clearly says undefined method 'destroy' for nil:NilClass.
As per the shared controller code, you would need to add destroy action in the before_action callback of set_cycle_road
class CycleRoadController < ApplicationController
before_action :set_cycle_road, only: [:show, :edit, :update, :destroy]
## ... ^
## Add this
end
This callback would take care of setting the #cycle_road instance variable before calling destroy action.
As the previous person mentioned it looks like #cycle_road is nil. Make sure that you have a before action:
class CycleRoadController < ApplicationController
...
before_action :set_cycle_road
...
And ensure that it runs for your destroy method. ie.
before_action :set_cycle_road, only: [:show, :edit, :update, :destroy]
I've created an activity model and I'm trying to have it so that when a user deletes their activity it also deletes the corresponding status. I've been able to do it when deleting the status, it deletes the activity but not sure how to do it in the opposite direction. I tried finding the status by targetable_id but I get:
undefined method `find_by_targetable_id' for #<Class:0x8df4a70>
Parameters:
{"_method"=>"delete",
"authenticity_token"=>"s2wKOZxCBVarT5uge3AIFNXHepFuvNGM+kU/q+ArOjA=",
"id"=>"18"}
If you're familiar with the public_activity gem then targetable is the same thing as trackable and in this example, the activity id is 18 and it's corresponding status id is 53
ActivitiesController
class ActivitiesController < ApplicationController
before_filter :authenticate_member!, only: [:destroy]
before_filter :find_activity, only: [:destroy]
def index
following_ids = current_member.following_members.map(&:id)
#activities = Activity.where("member_id in (?)", following_ids.push(current_member.id)).order("created_at desc").all
end
def destroy
#status = Activity.targetable
if #status
#status.destroy
end
#activity.destroy
respond_to do |format|
format.html { redirect_to :back }
format.json { head :no_content }
end
end
private
def find_activity
#activity = current_member.activities.find(params[:id])
end
end
StatusesController
class StatusesController < ApplicationController
before_filter :authenticate_member!, only: [:new, :create, :edit, :update, :destroy]
before_filter :find_member
before_filter :find_status, only: [:edit, :update, :destroy, :show]
rescue_from ActiveRecord::RecordNotFound do
render file: 'public/404', status: 404, formats: [:html]
end
# GET /statuses
# GET /statuses.json
def index
#statuses = Status.order('created_at desc').all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #statuses }
end
end
# GET /statuses/1
# GET /statuses/1.json
def show
respond_to do |format|
format.html # show.html.erb
format.json { redirect_to profile_path(current_member) }
end
end
# GET /statuses/new
# GET /statuses/new.json
def new
#status = Status.new
#status.build_document
respond_to do |format|
format.html # new.html.erb
format.json { render json: #status }
end
end
# GET /statuses/1/edit
def edit
end
# POST /statuses
# POST /statuses.json
def create
#status = current_member.statuses.new(params[:status])
respond_to do |format|
if #status.save
current_member.create_activity(#status, 'created')
format.html { redirect_to :back }
format.json
else
format.html { redirect_to profile_path(current_member), alert: 'Post wasn\'t created. Please try again and ensure image attchments are under 10Mbs.' }
format.json { render json: #status.errors, status: :unprocessable_entity }
end
end
end
# PUT /statuses/1
# PUT /statuses/1.json
def update
if params[:status] && params[:status].has_key?(:user_id)
params[:status].delete(:user_id)
end
respond_to do |format|
if #status.update_attributes(params[:status])
format.html { redirect_to profile_path(current_member), notice: 'Status was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #status.errors, status: :unprocessable_entity }
end
end
end
# DELETE /statuses/1
# DELETE /statuses/1.json
def destroy
#activity = Activity.find_by_targetable_id(params[:id])
if #activity
#activity.destroy
end
#status.destroy
respond_to do |format|
format.html { redirect_to :back }
format.json { head :no_content }
end
end
private
def find_member
#member = Member.find_by_user_name(params[:user_name])
end
def find_status
#status = current_member.statuses.find(params[:id])
end
def sortable_date
created_at
end
end
Should not this line
#status = Activity.targetable
be
#status = #activity.targetable
?
Second note: it probably will be better to move status destroying to Activity model before_destroy callback.