i am newbee want learn ruby on rails
i learn this code from tutorial on youtube.
i stuck to find undefined method `description'.
Here my code jobs_controller.rb
class JobsController < ApplicationController
before_action :find_job, only: [:show, :edit, :update, :destroy]
def index
#jobs = Job.all.order("created_at DESC")
end
def show
end
def new
#job = Job.new
end
def create
#job = Job.new(jobs_params)
if #job.save
redirect_to #job
else
render "New"
end
end
def edit
end
def update
end
def destroy #to delete
end
private
def jobs_params
params.require(:job).permit(:title, :description, :company, :url)
end
def find_job
#job = Job.find(params[:id])
end
end
Description is not an attribute of Job model/table and still you are using it in your form_for that's why it's giving undefined method description.
You haven't got a description on your job model. Run this command in your console:
rails g migration add_description_to_jobs description
'add_description_to_jobs' creates the migration file itself, and 'description' will create a string field 'description'. If you said 'description:integer' it would instead create it as an integer, but you won't need that in this instance.
What I can see is you are using simple simple_form_for with #job, and in the code you have
f.input :description, label: "Job Description"
So this error means your #job object is not having "description" attribute, which you have used with f.input, please check for that.
Related
I'd like to ask why i'm always getting nil value when running rspec controller test ?
I already read in this site and most of answers because plurals word using inside assigns
but in my case thats not working and i still got the same value
This is my Controller
class ContactsController < ApplicationController
load_and_authorize_resource
before_action :find_contact, only: [:show,:edit,:update,:destroy]
def index
authorize! :index, Contact
#contact = Contact.accessible_by(current_ability)
# #contact = Contact.all
end
def show
end
def new
#contact = Contact.new
end
def edit
end
def create
#contact = current_user.contact.new(contact_params)
if #contact.save
redirect_to #contact
else
render 'new'
end
end
def update
# #contact = Contact.find(params[:id])
if #contact.update(contact_params)
redirect_to #contact
else
render 'edit'
end
end
def destroy
#contact.destroy
redirect_to contacts_path
end
private
def contact_params
params.require(:contact).permit(:firstname,
:lastname,
:alamat,
details_attributes: [:id, :number, :_destroy])
end
def find_contact
#contact = Contact.find(params[:id])
end
end
And this is my simple controller test
require 'rails_helper'
RSpec.describe ContactsController do
describe "Contact" do
it "succesfully create the contact" do
contact = FactoryGirl.create(:contact)
get :index
# byebug
expect(assigns(:contacts)).to eq([contact])
end
end
end
Even i change assigns(:contacts) to assigns(:contact) i still got the same value. So where is that i am do wrong ?
Please kindly answer this, big thanks
Even i change assigns(:contacts) to assigns(:contact) i still got the
same value. So where is that i am do wrong ?
assigns and assert_template have been remove and extracted to a gem in Rails 5.
Source
You have an authorization check
authorize! :index, Contact
before the assignment to #contact.
But your test has no setup in order to grant permissions to the requesting user in any way.
It probably makes sense to have an additional test alongside the one you show in order to spot errors like this. E.g:
it "returns 200 (OK)" do
get :index
expect(response.response_code).to eq(200)
end
I'm trying to created a multi-layered controller inside my app.
with the following structure :
--Business_and_units_controller (main controller)
--↳ Business_units_controller ( sub controller )
----↳ Business_managers_controller ( sub controller to Business_units_controller )
----↳ Business_divisions_controller ( sub controller to Business_units_controller )
----↳ business_units_strats_attributes_controller ( sub controller to Business_units_controller )
It's pretty complex and maybe overly?
Anyways, I've created the controller called:
business_and_units_controller.rb
with a model:
business_and_unit.rb
I've added the controller to my routes.rb (to test it and see if it works)
get '/testunit', to: 'business_and_units#index'
resources :business_and_units
After seeing if the code worked i got the following error:
NoMethodError in BusinessAndUnitsController#index
undefined method `businessandunits' for #<User:0x007f55666f2a58>
Extracted source (around line #6):
1
2
3
4 def index
6 #business_and_units = current_user.businessandunits
7
8 end
I understand that the cause of the problem is that my business_and_units is not defined. But i don't understand why it isn't defined.
Can any of you see the cause of my problem?
To summarize:
My problem: according to ruby my business_and_units_controller.rb is not defined in the index.
Goal of this post: To understand why it isn't defined.
ps: I've searched for numerous similar posts in search to the solution of my problem, but haven't been able to find a solution.
my controller file
class BusinessAndUnitsController < ApplicationController
before_action :logged_in_user, only: [:create, :destroy]
before_action :correct_user, only: :destroy
def index
#business_and_units = current_user.business_and_units
end
def show
#business_and_units = Business_and_unit.find_by(id: params[:id])
if !#business_and_unit
raise ActionController::RoutingError.new('Not Found')
end
#user = #business_and_unit.user
end
def new
#user = User.new
#business_and_unit = Business_and_unit.new
end
def edit
#business_and_unit = Business_and_unit.find(params[:id])
end
def create
#business_and_unit = current_user.business_and_units.build(business_and_unit_params)
if #business_and_unit.save
flash[:success] = "business_and_unit created!"
redirect_to #business_and_unit
else
#feed_items = current_user.feed.paginate(page: params[:page])
render 'new'
end
end
def update
#business_and_unit = Business_and_unit.find(params[:id])
if #business_and_unit.update(business_and_unit_params)
redirect_to #business_and_unit
else
render 'edit'
end
end
def destroy
#business_and_unit.destroy
flash[:success] = "business_and_unit deleted"
redirect_to business_and_units_path
end
private
def business_and_unit_params
params.require(:business_and_unit).permit(
:corporate_strategy, :future_sale_value,
:industry, :market_focus, :business_unit,
business_units_attributes: [
:id, :business_units,
:_destroy],
business_managers_attributes: [
:id, :business_managers,
:_destroy],
business_divisions_attributes: [
:id, :business_divisions,
:business_divisions_managers,
:_destroy],
business_units_strats_attributes: [
:id, :business_units_strats,
:_destroy])
end
def correct_user
#business_and_unit = current_user.business_and_units.find_by(id: params[:id])
redirect_to business_and_units_path if #business_and_unit.nil?
end
end
The problem has nothing to do with your controller.
The error is that there is no method #businessandunits in your User model.
Based on the information you provided, I think you missed a relation definition has_many :business_and_units in your User class.
Then you will be able to call current_user.business_and_units
I have a model called Thing and a controller called Things.
I followed this tutorial to try and set a maximum amount of Things a user can create.
Here's the warning: the terminal is giving a warning (not a huge issue) of DEPRECATION WARNING: Passing an argument to force an association to reload is now deprecated and will be removed in Rails 5.1. Please call "reload" on the result collection proxy instead. What should I do to make it go away?
Here's the problem: The line self.errors.add(:base, "Exceeded Things Limit") isn't displaying an alert or notice in the view. How would I achieve this? It's not creating a new Thing (because I met the maximum limit of 2) which is good, but it's just reloading a new form which would be horrible for user experience.
I'm working Rails 5 and Devise.
Here's my Thing model:
class Thing < ApplicationRecord
belongs_to :user
validate :thing_count_within_limit, :on => :create
attr_accessor :validation_code, :flash_notice
def self.search(search)
if search
where("zipcode LIKE ?", "%#{search}%")
else
all
end
end
def thing_count_within_limit
if self.user.things(:reload).count >= 2
self.errors.add(:base, "Exceeded Things Limit")
end
end
end
And here's my Things controller:
class thingsController < ApplicationController
before_action :find_thing, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user_first, only: [:edit, :update, :destroy]
before_action :authorized_pilot, only: [:edit, :update, :destroy, :profile]
def index
#things = Thing.all.order("created_at ASC")
#things = Thing.search(params[:search])
end
def new
#thing = current_user.things.build
end
def create
#thing = current_user.things.build(thing_params)
if #thing.save
redirect_to #thing
else
render "new"
end
end
def profile
#things = Thing.where(user_id: current_user)
end
def show
end
def edit
end
def update
if #thing.update(thing_params)
redirect_to #thing
else
render "edit"
end
end
def destroy
if #thing.destroy
redirect_to root_path
else
redirect_to #thing
end
end
private
def thing_params
params.require(:thing).permit(:title, :description, :image).merge(zipcode: current_user.zipcode)
end
def find_thing
#thing = thing.find(params[:id])
end
def authenticate_user_first
if current_user != thing.find(params[:id]).user
redirect_to #thing
else
end
end
end
Can anyone help? Help is greatly appreciated.
There are two things that aren't connected to each other.
First, there is the deprecation warning. Because it is just a warning, not an error, you can choose to ignore it at the moment. If you want to remove the warning, just follow its instruction and change this line
if self.user.things(:reload).count >= 2
to
self.user.things.reload.count >= 2
Seconds, your code works like expected. Rails validations do not raise any errors, but they add error messages to the object. Just make sure that you display the errors to the user. To display the error you added to :base, add something like the following to your new.html.erb view:
<% if #thing.errors[:base].any? %>
<div class="error_message">
<%= #thing.errors.full_messages_for(:base).to_sentence %>
</div>
<% end %>
I've been going round in circles all day with this. I have a large multi-step form using the Wicked gem and Ruby on Rails. It works perfectly but I can't figure out how to to get back into the form to edit individual entries.
Iim trying to make the ability to go into the client show page, click an individual client and then from there go back into the quote to edit and update it. As the Wicked gem only seems to work with show and update actions, if I try to build a standard edit action Wicked expects to be on a step therefore doesn't work.
I read the I would have to factor the edit action into my show/update actions but I'm having difficulties. Any help would be great thanks!
Clients Controller:
class ClientsController < ApplicationController
before_action :authenticate_user!, only: [:index, :show, :edit]
before_action :set_client, only: [:edit, :show, :update]
def index
#clients = Client.order('created_at DESC').paginate(page: params[:page], per_page: 10)
end
def show; end
def new
#client = Client.new
end
def edit; end
def update
if #client.update_attributes(client_params)
redirect_to client_quotes_path
flash[:success] = 'Client successfully updated'
else
render 'edit'
end
render_wizard #client
end
# After client is completed:
def create
#client = Client.new(client_params)
if #client.valid?
#client.save
session[:current_user_id] = #client.id
ClientMailer.new_client(#client).deliver
redirect_to quotes_path
else
flash[:alert] = 'Sorry, there was a problem with your message. Please contact us directly at ...'
render :new
end
end
private
def set_client
#client = Client.find(params[:id])
end
def client_params
params.require(:client).permit(:first_name, :last_name, :title, :email, :email_confirmation,
:phone, :time, :reminder, :ref_number, :day, :note, :logs_reminder)
end
end
Quotes Controller:
class QuotesController < ApplicationController
include Wicked::Wizard
before_action :set_client, only: [:show, :update, :quote_success]
steps :profile, :employment, :general_questions, :indemnity_details, :declarations
def show
#client.build_doctor unless #client.doctor.present?
#client.build_dentist unless #client.dentist.present?
#client.old_insurers.build
#client.practice_addresses.build
render_wizard
end
def update
#client.update(client_params)
render_wizard #client
end
def quote_success; end
private
def set_client
current_user = Client.find_by_id(session[:current_user_id])
#client = current_user
end
# After full quote form is completed:
def finish_wizard_path
if #client.valid?
ClientMailer.new_quote(#client).deliver
ClientMailer.new_quote_user_message(#client).deliver
end
quote_success_path
end
end
def client_params
params.require(:client).permit(:name, :email, :email_confirmation, :phone, :date_required,
:title, :first_name, :last_name, :date_of_birth, :nationality, :reg_body, :reg_date, :reg_type, :reg_number,
:qual_place, :qual_year, :post_grad, :membership ...
Routes:
Rails.application.routes.draw do
devise_for :users
root 'clients#new'
get 'client', to: 'clients#new', as: 'client'
post 'client', to: 'clients#create'
get '/client_quotes', to: 'clients#index', as: 'client_quotes'
get '/client_quotes/:id', to: 'clients#show', as: 'client_quote'
get '/client_quotes/:id/edit', to: 'clients#edit', as: 'edit_client_quote'
patch '/client_quotes/:id', to: 'clients#update'
put '/client_quotes/:id', to: 'clients#update'
resources :quotes, only: [:index, :show, :update, :quote_success]
get 'quote-success' => 'quotes#quote_success'
devise_scope :user do
get '/login' => 'devise/sessions#new'
end
end
My solution to this in the end was rather than have the edit form as a multi step wizard, I've joined the form data together in a separate view page and got a traditional route to it as you mention. Not perfect but does the job!
When you are updating it is like you are "editing" the element, so you need to redirect to the wizard when you want to edit and when you call the update method you really would be editing that entry. So call the wicked path.
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