Rails 4: One-to-one controller issue - ruby-on-rails

I'm building an app which consists on sharing résumés. I am using Devise gem. Each user is able to create only one résumé. I made the models and and their relations. Resume belongs_to User and User has_one 'Resume'.
After making the views, I wanted to test my app but I got the error: undefined methodbuild' for nil:NilClass`
Here is my ResumeController and my routes.rb
class ResumeController < ApplicationController
before_action :find_resume, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!, except: [:show]
def show
# #resume = Resume.find_by(params[:id])
end
def new
#resume = current_user.resume.build
end
def create
#resume = current_user.resume.build(resume_params)
if #resume.save
redirect_to #resume, notice: "resume was successfully created"
else
render 'new'
end
end
def edit
end
def update
if #resume.update(pin_params)
redirect_to #resume, notice: "resume was successfully updated"
else
render 'edit'
end
end
def destroy
#resume.destroy
redirect_to root_path
end
private
def resume_params
params.require(:resume).permit(:title, :description)
end
def find_resume
#resume = resume.find(params[:id])
end
end
Routes.rb
Rails.application.routes.draw do
devise_for :users
resources :resume, except: [:index]
get 'static_pages/index'
root to: "static_pages#index"
end
I just want the user to be able to create only one Resume and then he will be able to share it.
Update: After following messanjah's answer there was another error coming from the _form.html.erb: undefined method resumes_path' for #<#<Class:0x00...>. Here is the gist with forms and model: goo.gl/XvW2LH So you can see all the files closely.

Without more knowledge of where the error is happening, I can only suggest some areas that might be suspect.
To build a has_one relationship, you must use the build_*association* constructor.
def new
#resume = current_user.build_resume
end
def create
#resume = current_user.build_resume(resume_params)
end

Related

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

ActiveRecord::RecordNotFound (Couldn't find Story with 'id'=):

I have been looking at other people's posts about this question. Unfortunately, still a while later I am stuck on it. I understand that a couple of the controller methods cannot find a story with the relevant 'ID' and render that to the views, hence my error.
However, I don't understand how I can edit my controller methods/routing so it can actually find the id of '1,2,3,4 etc'. I believe it is trying to look for a different from of ID. The 'create' and 'show' methods are creating the same error.
Error on screen:
ActiveRecord::RecordNotFound in StoriesController#create
Couldn't find Story with 'id'=
def find_story
#story = Story.find(params[:id])
end
Here, I have put in ID as the params for the story find method but it isn't finding it. Why?
class StoriesController < ApplicationController
before_action :find_story, only: [:destroy, :create, :show, :edit, :update]
def index
#stories = Story.order('created_at DESC')
end
def new
#story = Story.new
end
def create
#story = Story.new(story_params)
if #story.save
flash[:success] = "Your beautiful story has been added!"
redirect_to root_path
else
render 'new'
end
end
def edit
end
def update
if #story.update.attributes(story_params)
flash[:success] = "More knowledge, more wisdom"
redirect_to root_path
else
render 'edit'
end
end
def destroy
if #story.destroy
flash[:success] = "I think you should have more confidence in your storytelling"
else
flash[:error] = "Can't delete this story, sorry"
end
end
def show
#stories = Story.all
end
private
def story_params
params.require(:story).permit(:name, :description)
end
def find_story
#story = Story.find(params[:id])
end
end
My routes.rb:
Rails.application.routes.draw do
get 'stories/new/:id' => 'posts#show'
resources :stories
devise_for :users
root to: 'stories#index'
end
You want to change the ":find_story" to not include the create as that is what is telling it to look for an id, but there is no id when on the create page, you are creating a new one, not finding one that exists
so change the before_action to this
before_action :find_story, only: [:destroy, :show, :edit, :update]
Your issue with stories is the route you are trying to use. Show looks for an id, for the same reason I mentioned above, so the route need to be something like
stories/show/1
where "1" is the id of the story you want.
ActiveRecord::RecordNotFound in StoriesController#create
you have before_action :find_story with create method which is trying to find Story but there is no :id in params
So you need to remove :create action from the list of before_action and change it to
before_action :find_story, only: [:destroy, :show, :edit, :update]
I have got the same problem.
#table = Table.find(params[:id])
ActiveRecord::RecordNotFound - Couldn't find Table with 'id'=12222:
app/controllers/tables_controller.rb:27:in `edit'
Sol: Try this query
#table = Table.find_by_id(params[:id])

Route redirecting issue with devise and rails

I have a has_one association in my model with my user. What I'm trying to do here is simple but I'm having a hard time understanding whats wrong here. So since I have a has_one association with my model, in my mind I was simply thinking that if the user has already created the model associated with the has_one association if he tries accessing "localhost3000/model/new" I would redirect him to the edit page of this particular model. Here is what I have but its telling me its not working as intended. It's as if my if statement is not catching anything
class BusinessesController < ApplicationController
before_action :set_business, only: [:show, :edit, :update, :destroy]
def index
#businesses = Business.all
#buzzs = Buzz.all
end
def show
end
def new
if current_user.business.nil?
#business = current_user.build_business
else
render 'edit'
end
end
def edit
end
def create
#business = current_user.build_business(business_params)
if #business.save
redirect_to #business, notice: 'Business was successfully created.'
else
render "new"
end
end
This error does not make a lot of sense to me because it says its an error in the "new" controller which would have rendered it to the edit path thus not being nil
This is happening because you're not setting #business when redirecting to 'edit'. Try this:
def new
if current_user.business.nil?
#business = current_user.build_business
else
#business = current_user.business
render 'edit'
end
end

superclass mismatch for class when namespacing admin controller

Hey I am trying to namespace a bunch of controllers that I only want admins to be able to access. For example, I want routes like admin/products or admin/categories, but when I call any of those controllers located in my controllers/admin folder, I get the following error message
superclass mismatch for class CategoriesController
If I restart the server right after, I get this
Unable to autoload constant Admin::CategoriesController
and
Circular dependency detected while autoloading constant Admin::CategoriesController
These are my routes
Rails.application.routes.draw do
root 'pages#home'
devise_for :admins
namespace :admin do
resources :categories, :except => [:new, :show]
resources :products
end
resources :products
resources :carts, :only => [:show]
resources :line_items, :only => [:create, :destroy]
# Shop controller
get 'shop/index
# Admin controller
get 'admin/index'
This is my categories controller
class CategoriesController < ApplicationController
before_filter :authenticate_admin!
def index
#categories = Category.all
#category = Category.new
end
def create
category = Category.new(categories_params)
if category.save
flash[:notice] = "You have added a new category"
redirect_to categories_path
else
flash[:error] = "An error occured"
render "index"
end
end
def edit
#category = Category.find(params[:id])
end
def update
#category = Category.find(params[:id])
if #category.update(categories_params)
flash[:notice] = "Succesfully updated #{#category[:name].titleize}"
redirect_to categories_path
else
flash[:error] = "An error occured trying to update #{#category[:name].titleize}"
render "edit"
end
end
def destroy
#category = Category.find(params[:id])
if #category.destroy
flash[:notice] = "You succesfully removed #{#category.name}"
else
flash[:error] = "An error occured trying to remove #{#category.name}"
end
redirect_to categories_path
end
private
def categories_params
params.require(:category).permit(:name)
end
end
This has been troubling me for some time now so any help will be greatly appreciated
You forgot to namespace the Controller class :
class Admin::CategoriesController < ApplicationController
which is why you receive Unable to autoload constant Admin::CategoriesController error as Rails is looking for namespaced class Admin::CategoriesController and what you have is CategoriesController

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