Rails throwing error instead validating - ruby-on-rails

I am building a fairly straightforward Rails 5 application. You create "Movies," and then can create "Reviews" for those movies. Rails is doing something odd. I have my application set up so instead of a "new" action and a corresponding view, I have the form to create new movies in a modal contained in the application.html.erb file. I then provide #newmovie = Movie.new in the controller for all the movie views, so the data is available everywhere.
I have validations for the movie object setup like this:
class Movie < ApplicationRecord
has_many :reviews
validates :title, :director, :poster, :synopsis, presence: true
end
When I fill out the form to create a new movie in the modal on my index view and intentionally leave fields blank (to trigger the validation), I get this:
instead of the form simply not accepting the input. What's going on here? I can't have this error happening like this. Previously, I had a "new" view. This did not happen in the previous setup. Help!
Here is my entire movies controller:
class MoviesController < ApplicationController
before_action :find_movie, only: [:show, :edit, :update, :destroy ]
before_action :authenticate_user!, only: [:new, :create, :edit, :update, :destroy]
before_action :find_newmovie, only: [:show, :index, :new, :edit]
def show
#reviews = #movie.reviews.all.order(created_at: :desc).paginate(:page => params[:page], :per_page => 3)
#review = Review.new
if #movie.reviews.blank?
#average_review = 0
else
#average_review = #movie.reviews.average(:rating).round(2)
end
end
def index
#movies = Movie.all.order(title: :asc).paginate(:page => params[:page], :per_page => 3)
#newmovie = Movie.new
end
def new
#movie = Movie.new
end
def create
#movie = Movie.create(movie_params)
#movie.user_id = current_user.id
if #movie.save
flash[:success] = "Your movie was created!"
redirect_to root_path
else
flash[:danger] = "There was a problem with your request"
render :new
end
end
def edit
end
def update
if #movie.update(movie_params)
flash[:success] = "Your movie was updated"
redirect_to movie_path
else
flash[:danger] = "There was a problem with your request"
end
end
def destroy
if #movie.destroy
flash[:success] = "Your movie was removed"
redirect_to movies_path
else
flash[:danger] = "There was a problem with your request"
render :index
end
end
private
def movie_params
params.require(:movie).permit(:title, :director, :poster, :synopsis, :user_id)
end
def find_movie
#movie = Movie.find(params[:id])
end
def find_newmovie
#newmovie = Movie.new
end
end

In new action of movies_controller, you missed to initalize the instance variable #newmovie.
add below code in movies_controller:
class MoviesController < ApplicationController
def new
#newmovie = Movie.new
end
...
end

Related

why does my routes give me wrong direction

I'm having a association between user, store and item like this:
user has one store
store has many items
item belongs to store
So when I create item it must belongs to the current user's store
Now, I logged in as user_1 , I want to search for user_2's item. But if I didn't create user_1's store, It keep redirecting me to localhost:3000/stores
in items_controller.rb:
class ItemsController < ApplicationController
before_action :find_item, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!, only: [:new, :edit]
def index
if params[:category].blank?
#items = Item.all.order("created_at DESC")
end
if params[:category]
#category_id = Category.find_by(name: params[:category]).id
#items = Item.where(category_id: #category_id).order("created_at DESC")
end
end
def show
end
def new
#store = current_user.store
#item = #store.items.build
#categories = Category.all.map{ |c| [c.name, c.id] }
end
def update
#item.category_id = params[:category_id]
if #item.update(item_params)
redirect_to item_path(#item)
else
render 'edit'
end
end
def create
#store = current_user.store
#item = #store.items.build(item_params)
#item.category_id = params[:category_id]
if #item.save
flash[:success] = "Creating item success"
redirect_to #item
else
render 'new'
end
end
private
def item_params
params.require(:item).permit(:code, :name, :description, :producer, :item_img, :store_id,
:category_id )
end
def find_item
#item = Item.find(params[:id])
end
def find_user
#user = User.find_by(params[:user_id])
end
end
in stores_controller.rb:
class StoresController < ApplicationController
before_action :find_store, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!
before_action :find_user
def show
if current_user.store.blank?
redirect_to new
else
#items = Item.where(store_id: #store.id)
end
end
def index
#stores = Store.all.order("created at DESC")
end
def new
#store = current_user.build_store
end
def create
#store = current_user.build_store(store_params)
if #store.save
session[:store_id] = #store.id
flash[:success] = "Creating item success"
redirect_to #store, notice: 'success'
else
render 'new'
end
end
private
def store_params
params.require(:store).permit( :name , :user_id)
end
def find_store
#store = Store.find(params[:id])
end
def find_user
#user = Store.find_by(params[:user_id])
end
end
The error raised whenever I click on the button in items/show.html.erb.
In items/show.html.erb:
<button>see more item from:<%= link_to #item.store.name, store_path(#item.store.id)%></button>
in routes.rb:
devise_for :users
resources :items
resources :stores
In the show method for stores_controller, I still want to load the current_user's store in navbar section to make sure he can add more items to his store when he logged in.
I'm still a newbie in rails and I'm looking for solutions to solve this problem :-)
If a store requires a user_id then you don't need before_action :find_user because you can get the store's user just by calling store.user
It looks like you require the current_user to have a store but what if they are not logged in? Shouldn't it be this?
def show
if current_user && current_user.store.blank?
redirect_to new
else
#items = Item.where(store_id: #store.id)
end
end

How to access a variable from a different controller to make a custom download action work

I have a resumes controller and a welcomes controller in my app. The welcomes controller has only an index action which is there for the root page. The purpose of the resumes controller is to upload(new/create), download(download) etc. pdf files as an logged in user and it works great so far.
I want to implement the resume download feature on the rootpage as well.(welcomes_controller /index).
How can I accomplish this?
Since I can not call the variable to access the resume model from the welcomes controller. How should the routes be? What should I modify on the welcomes_controller?
routes.rb
Rails.application.routes.draw do
devise_for :users
root 'welcomes#index'
resources :resumes do
get :download, on: :member
end
get '*path' => redirect('/')
end
resumes_controller.rb
class ResumesController < ApplicationController
around_filter :catch_not_found
before_action :find_resume, only: [ :show, :edit, :update, :destroy, :download ]
before_action :authenticate_user!
def show
end
def new
if #resume = current_user.resume
redirect_to #resume
else
#resume = Resume.new
end
end
def create
#resume = current_user.build_resume(resume_params)
if #resume.save
redirect_to #resume
else
render :new
end
end
def edit
end
def update
if #resume.update resume_params
redirect_to #resume, notice: "Your resume was successfully saved!"
else
render 'edit'
end
end
def destroy
#resume.destroy
redirect_to new_resume_path, notice: "Your resume was successfully deleted!"
end
def download
send_data #resume, type: "application/pdf", disposition: "attachment"
end
private
def resume_params
params.require(:resume).permit( :user_id, :download_file, :remove_download_file)
end
def find_resume
#resume = Resume.find(params[:id])
end
def catch_not_found
yield
rescue ActiveRecord::RecordNotFound
redirect_to(root_url, :notice => 'Record not found')
end
end
resumes/show.html.erb
...
...
<%= link_to "Download", download_resume_path(#resume), "data-turbolinks" => false %>
welcomes_controller.rb
class WelcomesController < ApplicationController
def index
end
end
you can access Resume model from welcome controller, although controller is welcome you can call Resume model see sample below
class WelcomesController < ApplicationController
def index
# you can call Resume model frome here
#resumes = Resume.all
end
def show
#resume = Resume.find(params[:id])
end
end

Special Access To Edit Pieces Model Devise User ID 1

I am using devise, and have a pieces model in my Ruby on Rails web app. A user has_many pieces. Right now, in my pieces controller, I have a method called correct_user, which allows only users who own the pieces to edit and destroy them. I want to add a line to this method which allows the user with a devise user id of 1 to be able to edit and destroy anyone else's pieces (if current_user.id ==1, then allow the edit/destroy actions). I have tried a few combinations, but I keep getting errors.
Here is my pieces controller: (the correct_user method is towards the end)
class PiecesController < ApplicationController
before_action :set_piece, only: [:show, :edit, :update, :destroy]
before_action :correct_user, only: [:edit, :update, :destroy]
before_action :authenticate_user!, except: [:index, :show]
respond_to :html
def index
#pieces = Piece.all
respond_with(#pieces)
end
def show
respond_with(#piece)
end
def new
#piece = current_user.pieces.build
respond_with(#piece)
end
def edit
end
def create
#piece = current_user.pieces.build(piece_params)
flash[:notice] = 'Piece was successfully created.' if #piece.save
respond_with(#piece)
end
def update
flash[:notice] = 'Piece was successfully updated.' if #piece.update(piece_params)
respond_with(#piece)
end
def destroy
flash[:notice] = 'Piece was successfully deleted.' if #piece.destroy
respond_with(#piece)
end
private
def set_piece
#piece = Piece.find(params[:id])
end
def correct_user
#piece = current_user.pieces.find_by(id: params[:id])
redirect_to pieces_path, notice: "Access Denied! Not authorized to edit this piece." if #piece.nil?
end
def piece_params
params.require(:piece).permit(:title, :image, :genre, :size, :price, :description, :status)
end
end
Thanks guys!
In correct_user, change the conditional on redirect_to to and return if #piece.nil? and current_user.id != 1, then add a new line below that: #piece = Piece.find(params[:id]) if current_user.id == 1, which will only run if the redirect_to ... and return does not.
(Also, you have current_user.pieces.find_by(id: ...), which can be just .find(...) for simplicity.)

Rails Action Can't Be Found For Controller

I have A comments Controller Where a User can go tip the comment (right now clicking it will flash a sentence, will add functions later). The problem I'm having is that the page is loading but when I click the link nothing is happening. I'm getting this error when I go to the console:
AbstractController::ActionNotFound - The action 'tip' could not be found for CommentsController
But I have the action in our controller here:
def tip
redirect_to :back, :notice => "Thank you for the Tip. The User will Love it"
end
Here's the route for the tip:
get "/:id/tip" => "comments#tip", :as => "tip"
Here's the Link_to also"
= link_to(tip_path(comment), :class => "story-likes-link", :remote => true, :title => "Tip comment" ) do
%i.fa.fa-money.fa-lg
Tip
Thank you so much for the help : )
edit: whole Controller
class CommentsController < ApplicationController
before_action :authenticate_user!
before_action :set_user
before_action :set_resource, :except => [:destroy]
before_action :set_parent, :except => [:destroy]
before_action :set_comment, :only => [:update, :destroy]
respond_to :js
# Create the comments/replies for the books/comics
def create
#comment = current_user.comments.new(comment_params)
if #comment.save
#comment.move_to_child_of(#parent) unless #parent.nil?
end
respond_with #comment, #resource
end
# Update the comments for the user
def update
#comment.update_attributes(comment_params)
respond_with #comment, #resource
end
# Delete the comments for the books/comics
def destroy
#resource = #comment.commentable
#comment.destroy
respond_with #resource
end
private
# Permitted parameters
def comment_params
params.require(:comment).permit(:body, :commentable_id, :commentable_type, :parent_id)
end
# Set the parent resource for the comments and replies
def set_resource
if params[:comment][:commentable_type].eql?("Book")
#resource = Book.find(params[:comment][:commentable_id])
else
#resource = Comic.find(params[:comment][:commentable_id])
end
end
# Set the parent for the comments to make then as the child of the parent
def set_parent
#parent = params[:comment].has_key?(:parent_id) ? Comment.find(params[:comment][:parent_id]) : nil
end
# Set the comment for the source
def set_comment
#comment = Comment.find(params[:id])
end
def tip
redirect_to :back, :notice => "Thank you for the Tip. The User will Love it"
end
def set_user
#user = User.find(params[:user_id])
end
end
The problem is the action #tip method is hidden in private section, so the router sees not the method at all.
Well, then move the method's code above the private keyword:
def tip
redirect_to :back, :notice => "Thank you for the Tip. The User will Love it"
end
private
NOTE: that action method should not be place to private or protected sections, only to public, which is default section for ruby class definition flow.

How to fix undefined method error in rails app using has_many?

I get an error when I try to visit the below url in my rails app.
http://localhost:3000/origtexts/1/reviews/new
routes.rb
resources :origtexts do
resources :reviews
end
It passes the param of the review (1) correctly but I the error I get is undefined method `review' for the line in ReviewsController#new.
reviews_controller.rb
class ReviewsController < ApplicationController
before_filter :find_origtext
before_filter :find_review, :only => [:show, :edit, :update, :destroy]
def new
#review = #origtext.review.build
end
def show
end
def create
#review = #origtext.reviews.build(params[:review])
if #review.save
flash[:notice] = 'Review has been created'
redirect_to [#origtext, #review]
else
flash[:alert] = 'Review has not been created'
render :action => 'new'
end
end
private
def find_origtext
#origtext = Origtext.find(params[:origtext_id])
end
def find_review
#review = #origtext.reviews.find(params[:id])
end
end
Any advice on how to fix this?
Change review to reviews in this line
#review = #origtext.review.build
To
#review = #origtext.reviews.build

Resources