Rails undefined method count - ruby-on-rails-3

I am trying to check that an address isn't being used before I delete it. My code is as follows:
def destroy
#address = current_user.addresses.find_by_id(params[:id])
redirect_to user_addresses_path(current_user) if #address.nil?
if Organisation.find_by_address_id(params[:id]).count == 0 && Event.find_by_address_id(params[:id]).count == 0
#address.destroy
redirect_to user_addresses_path(current_user)
else
flash[:error] = "Cannot delete address because it is being used"
redirect_to user_addresses_path(current_user)
end
end
however, this gives me an error:
undefined method `count' for nil:NilClass
What am I doing wrong?

Organisation.find_by_address_id(params[:id]) will return a single object, or nil if one without that address_id does not exist.
Perhaps you meant Organisation.find_all_by_address_id(params[:id]).

Related

How to handle exceptions caused by nil:NilClass

I have a model called quiz, which has many questions models. I want to add some kind of esception handling so that when the user types in a wrong quiz_id in the URL, an error page would be rendered.
I wrote some helper methods in my QuestionsController to handle the exceptions:
private
def render_error(message)
#error_message = message
render 'error'
end
def active_quizzes_safe
active_quizzes = Quiz.active_quizzes(current_user.id)
render_error('Sorry! The request is invalid! Please log in again!') if active_quizzes.nil?
active_quizzes
end
def active_quiz_safe(quiz_id)
active_quiz = active_quizzes_safe.where(id: quiz_id).first
render_error('The quiz does not exist or you are not allowed to take this quiz!') if active_quiz.blank?
active_quiz
end
And here is the action in QuestionsController which has problems:
def show_quiz
if current_user
#quiz = active_quiz_safe(params[:quiz_id])
#questions = #quiz.questions
end
end
So if the :quiz_id in the URL localhost:3000/MY_URL/:quiz_id is not correct(that is, a record cannot be found), an error page should be rendered by the render_error mothod. However, when I tired a wrong :quiz_id, I got undefined method 'questions' for nil:NilClass. I guess this is because of the #questions = #quiz.questions in show_quiz method.
However, is the execution supposed to halt after the render_error action, which is before #questions = #quiz.questions? Why #questions = #quiz.questions is executed anyway?
In addtion, are there any standard ways to handle nil:NilClass errors like this?
Thank you!!
Look in your public/404.html, public/422.html and public/500.html files. Rails will automatically redirects if error occurs anyway. So I think you don't need to manually handle exceptions, except you have specific case. To test and view this error pages run application in production bundle exec rails s RAILS_ENV=production.
Calling render method does not halt the action. So you should carefully design your action to ensure that you return immediately after rendering. Like this:
def show_quiz
if current_user
active_quizzes = Quiz.active_quizzes(current_user.id)
if active_quizzes.nil?
render_error('Sorry! The request is invalid! Please log in again!')
else
#quiz = active_quizzes_safe.where(id: quiz_id).first
if #quiz.blank?
render_error('The quiz does not exist or you are not allowed to take this quiz!')
else
#questions = #quiz.questions
end
end
end
end
But in this case, I think it's better to use some exception control, like this:
def show_quiz
if current_user
active_quizzes = Quiz.active_quizzes(current_user.id)
#quiz = active_quizzes_safe.find(quiz_id)
#questions = #quiz.questions
end
rescue ActiveRecord::RecordNotFound
render_error 'The quiz does not exist or you are not allowed to take this quiz!'
end

How to know whether a request param is missing and throw exception using Rails 3

When I get a request from client in my controller I do:
def index
if (params[:event] == nil || params[:year] == nil || params[:country] == nil)
raise some_error
end
end
Is there a better way to perform it in rails 3.2?
Thanks.
This does the same thing, and though it's a bit more verbose, it's DRYer because it alleviates the need to directly specify each param key in the conditional:
params_hash = []
keys = [:event, :year, :country]
params.each do |key, value|
if keys.include?(key)
params_hash << value
end
end
if params_hash.include?(nil)
raise some_error
end
try:
keys = [:event, :year, :country]
unless (keys - (params.keys & keys)).blank?
raise some_error
end

How to stop a helper method from applying to a specific controller?

I have a helper_method that allows links to escape from a subdomain. However it is impacting my videos_controller, as it essentially seems to negate the 'current_event' method when not in the events controlller.
I've tried several dozen different ways over the last 4 days to make it so I can still escape my links from the subdomain, but still allow the videos_controller to work.
I think the best way to achieve this is to exclude the videos_controller from the helper method, but I'm not sure how (or if it is actually the best way forward - I'm obviously a noob!) Any suggestions please?! Relevant code below:
module UrlHelper
def url_for(options = nil)
if request.subdomain.present? and request.subdomain.downcase != 'www' and !options.nil? and options.is_a?(Hash) and options.has_key? :only_path and options[:only_path]
options[:only_path] = false
end
super
end
end
Videos_controller
def new
if current_event?
#video = current_event.videos.new
else
#video = Video.new
end
end
def create
if current_event.present?
#video = current_event.videos.new(params[:video])
#video.user_id = current_user.id
key = get_key_from_the_cloud
#video.key = key
else
#video = current_user.videos.new(params[:video])
#video.user_id = current_user.id
key = get_key_from_the_cloud
#video.key = key
end
if #video.save
flash[:success] = "Video uploaded!"
redirect_to root_url(subdomain: => current_event.name)
else
flash[:error] = "#{#video.errors.messages}"
render :new
end
end
current_event method
def current_event
if request.subdomain.present?
#event = Event.find_by_name(request.subdomain)
end
end
Did you take a look at this post yet?
You might want to create a new function test that only does something like
module UrlHelper
def test
puts "Test is called"
end
end
If that works you know its not including that fails but it has to be the method.
Otherwise you know the module is not included and you can narrow down the search.

Rails pulling attributes in an observer

I have this observer which monitors the Comments table and will send an email after something is created. It doesn't seem that I'm doing the associations correctly in the observer though because I receive an error or ArgumentError (wrong number of arguments (0 for 5)): using this code:
class CommentObserver < ActiveRecord::Observer
def after_create(comment)
if comment.guest_comment == true
if comment.name?
InvoiceMailer.message(comment.name, comment.content, comment.email, comment.user.email, comment.order_id).deliver
elsif comment.email?
# do something if there's no email yet
InvoiceMailer.message(comment.name, comment.content, comment.order.customer.email, comment.user.email, comment.order_id).deliver
else
InvoiceMailer.message(comment.email, comment.content, comment.email, comment.user.email, comment.order_id).deliver
end
else
# owner made the comment
if comment.user.account.company_name?
InvoiceMailer.message(comment.user.name+", "+comment.user.account.company_name, comment.content, comment.user.email, comment.email, comment.order_id).deliver
else
InvoiceMailer.message(comment.user.name, comment.content, comment.user.email, comment.email, comment.order_id).deliver
end
end
end
end
Is there a way to write correct associations inside an observer?
So I found that that observers don't/shouldn't have access to the database. I moved my logic to the mailer for now (will move to a helper later). Then make sure not to use "message" as your method name since it's reserved ;)

undefined method id for TrueClass Rails

def can_save(board,role)
if ar_user = already_registered?(email) || user = self.save
Participant.make(ar_user||user, board, role)
end
user
end
I do this rspec test on it:
it "should return the user if the user is not already registered" do
lambda do
user = #new_user.can_save(#board, "Manager")
end.should change(User,:count).by(1)
end
I get this error:
undefined method `id' for true:TrueClass
Why is that?
save method returns true or false, not a saved instance of object.