I have in my orders/edit.html.erb a form that begins like this:
<%= simple_form_for [#reservation, #order] do |f| %>
Orders Controller:
def edit
#reservation = Reservation.find_by_id(params[:reservation_id])
#order = Order.find_by_id(params[:id])
end
Association:
Reservation :has_one Order
Routes:
resources :reservations do
resources :orders
end
If my path resembles something like /reservations/10/orders/10/edit I end up getting an error from Rails saying NoMethodError in Orders#edit and undefined method 'model_name' for nil:NilClass
When I create a new order the form works perfectly fine so not sure why i'm getting an error all of a sudden, can someone help me with this issue?
Current implementation is prone to failure when the URL supplied either a reservation ID or an order ID that is not valid. Two ways to handle this:
First, let Rails do it for you:
def edit
#reservation = Reservation.find(params[:reservation_id])
#order = Order.find(params[:id])
end
This will raise an ActiveRecord::RecordNotFound error, which, in production, should lead users to your 404 page.
If you'd prefer to keep find_by_id and handle this manually, or to rescue from this error in a different way, you can do:
def edit
#reservation = Reservation.find_by_id(params[:reservation_id])
#order = Order.find_by_id(params[:id])
if #reservation.nil? || #order.nil?
raise ActiveRecord::RecordNotFound.new # Or, do something else
end
end
That would yield the same result as above ... just more code.
Related
Rails 5.2
In my inventories_controller.rb, I have the following:
before_action :fetch_product, only: [:show]
def show
........
end
def fetch_product
if params.has_key?(:sku)
#product = Product.get_product(params)
end
end
This works fine, when I do: http://0.0.0.0:3000/sku/12345678
I am trying to implement search functionality, so I modified nventories_controller.rb as follows:
def fetch_product
if params.has_key?(:search) && !params[:search].blank?
product = Product.find_by_sku(params[:search])
if !product
params = params.except[:search]
redirect_to product_show_path, alert: 'Product was not found'
end
params = params.merge!(:sku, product.sku)
end
if params.has_key?(:sku)
#product = Product.get_product(params)
end
end
When I do: http://0.0.0.0:3000/sku/12345678
I get an instant error message:
undefined method `has_key?' for nil:NilClass
Using my debugger, I find that on entry into the fetch_product method, params is nil
Any idea what's going on?
params = params.merge!(:sku, product.sku) modifies the hash in place and returns nil, don't do that assignment, just call params.merge! (if you still want to do the assignment, remove the "!").
Personally, I wouldn't modify the params hash unless it's really really needed, I would use another variable.
Every time I submit the form I get this error: undefined method `each' for nil:NilClass. If everything is correct I can submit the form without any problems, but when there is one thing missing it gives me that error. The error sends me to this line:
views/users/new.html.haml
- #subscriptions.each do |fbs|
= fb.radio_button :subscription_id, fbs.id, class: 'radiobtn', required: true
controllers/users_controller.rb
def new
#user = Users::Business.new
#subscriptions = Businesses::Subscription.all
end
def create
#user = Users::Business.new(user_params)
if #user.save
sign_in(#user)
else
render :new
end
end
Assigns subscriptions in a create action too:
before_filter :set_subscriptions, only: %w(new create) #for edit and update if needed
private
def set_subscriptions
#subscriptions = Businesses::Subscription.all
end
Or add #subscriptions = Businesses::Subscription.all directly to create action after the saving is failed and you re-render new form.
It is happening because there is no value persisted with that model .
You can check the data into the rails console
like ,
$rails console
> Businesses::Subscription.count
And if you see that there is no data then you can write a if ... end block to check for null value and handle it.
I have a model “Thing,” each of which has_many “Comments,” each of which in turn has_many “Votes.” I want to be able to vote on comments on the Thing show page. This is what I have so far:
Comments Controller:
def votecomment
#comment = Comment.find(params[:id])
Vote.create!(voteable_id: params[:id], voteable_type: 'Comment')
redirect_to current_thing
end
Things View:
<%= link_to “Vote”, vote_comment_path(:id => comment.id), method: :post %>
Routes:
post 'comments/:id/vote' => 'comments#vote', as: 'vote_comment'
But I'm getting back this error:
NameError in CommentsController#votecomment
undefined local variable or method `current_thing' for #<CommentsController:0x007f98efa69c00>
I tried moving the method to the Things controller, but I got the exact same type of error.
What am I doing wrong?
Assuming you have the following relation in comment.rb
belongs_to :thing
You can access the thing object of a comment using #comment.thing. Since redirect_to accepts objects, you can do
redirect_to #comment.thing
You have to understand that nothing is called current_thing if you are familiar with devise and you see ex current_user this is a method in the gem not a populated method with each model you create.
So if you want something like that add method to your application_controller or even application helper to get current_thing
def current_thing
Thing.find() --> or whatever the way you get that current thing.
end
on my edit action I never rise the record not found if the record does not exist. What I'm doing wrong.
Here is my edit action
class OffersController < ApplicationController
rescue_from ActiveRecord::RecordNotFound, with: :record_not_found
def show
#offer = Offer.find(params[:id])
end
def edit
#offer = Offer.find_by(edit_hash: params[:edit_hash])
#country = Country.find_by(name: #offer.country)
#states = State.find(:all, :conditions => { country_id: #country })
end
private
def record_not_found
render text: "404 Not Found", status: 404
end
end
I always get undefined method `country' for nil:NilClass for my unexist edit record.
Also I raise the record not found on my show action, but I would like to use the 404.html page that I have on my public folder. How can I use this file???
Thanks in advance
The problem is that your line #offer = Offer.find_by(edit_hash: params[:edit_hash]) is not responding with ActiveRecord::RecordNotFound. It's responding with nil.
You can see this by opening up your Rails console from your app's directory with rails c. In the console, put this in:
#offer = Offer.find_by(edit_hash: params[:edit_hash])
You'll see that its output is => nil. You can then type #offer and you'll see its output, again, is => nil. Now, put this line into the console:
#offer = Offer.find(99999)
You'll see that its output is ActiveRecord::RecordNotFound: Couldn't find Offer with id=99999.
To fix the problem, add a ! to your find_by calls, so they are like this:
#offer = Offer.find_by!(edit_hash: params[:edit_hash])
This will cause Rails to respond with ActiveRecord::RecordNotFound: ActiveRecord::RecordNotFound instead of nil.
I am getting
NoMethodError in ProjectsController#edit
undefined method `projects' for
#<User:0x28356d8>`app/controllers/projects_controller.rb:154:in `correct_user'
The params are: {"user_id"=>"1", "id"=>"1"}
The offending line in the projects_controller is:#project = current_user.projects.find_by_id(params[:id]) as part of
def correct_user
#project = current_user.projects.find_by_id(params[:id])
redirect_to show_user_path if #project.nil?
end
My projects_controller#edit method is:
def edit
#project = Project.find(params[:id])
#project.current_step = #project.first_step
#user = current_user
end
This is being triggered by a button,
<%= link_to image_tag('img_blank.png'), edit_user_project_path(current_user), :class => "btn_edit_project" %>
with the HTML output as:
<a class="btn_edit_project" href="/users/1/projects/1/edit"><img src="/assets/img_blank.png" alt="Img_blank"></a>
My routes file contains the following:
resources :users do
resources :projects
end
and rake routes shows:
edit_user_project GET /users/:user_id/projects/:id/edit(.:format) projects#edit
This problem keeps surfacing in different forms, but never quit gets resolved. Any ideas?
Thanks to #jvnill for the answer...
The association between the user and the project is a 1 to 1. The user has_one :project and the project belongs_to :user. As #jvnill pointed out, there is no need to qualify the lookup with .find_by_id(params[:id]) because the user_id will only be in the projects table once and Rails can find it.