This should be a fairly simple error to fix (I hope). When a joke on my app is approved, I want that user to be awarded 5 manpoints (don't ask). I currently have this in my 'jokes_controller`:
def approve
#joke = Joke.find(params[:id])
#joke.update_attributes(approved: true)
if #joke.user.manpoints = nil
#joke.user.manpoints = 5
else
#joke.user.manpoints += 5
end
#joke.save
redirect_to jokes_path
end
I'm getting this error when I try to approve a joke:
undefined method `+' for nil:NilClass
I thought += was the "Ruby way" to do this? Can anyone set me straight?
Change = in if condition to ==. I assume you need to compare manpoints with nil, not to assign nil to manpoints.
It should be like:
if #joke.user.manpoints == nil
...
You can omit == operator here:
unless #joke.user.manpoints
...
PS. Why are you excepting that manpoints will be nil?
Related
after setup a search into a serializer!
Rails spits out
no implicit conversion of nil into Hash
So, please someone can point out whats wrong with this code?
class SearchController < ApplicationController
def results
results_query = PgSearch.multisearch(params[:q]).paginate(page: page, per_page: 20)
result = results_query.map(&:searchable).map do |result_item|
case result_item.class.name
when 'Post'
PostSerializer.new(result_item)
else
raise NotImplementedError
end
end
render json: {
items: result,
page: page,
pages: results_query.total_pages
}
end
def page
params[:page] || 1
end
def serialize(data, serializer)
ActiveModel::Serializer::CollectionSerializer.new(data, each_serializer: serializer)
end
end
Since your case statement isn't checking many values, you could always make it into a standard if/else statement:
if result_item && result.class.name == 'Post'
PostSerializer.new(result_item)
else
raise NotImplementedError
end
Well, on the screenshots you've provided we can see the log message specifies that the error is on line 5.
According to your code, line 5 is: case result_item.class.name
The error message is TypeError (no implicit conversion of nil into Hash).
You're trying to get the class then the name of result_item. So the problem is with result_item which is equal to nil.
In order the resolve your problem you might want to check the ouput of results_query.map(&:searchable).map.
Based on the screenshot you've provided, I've quickly checked the source code. The offending line seems to be this one: https://github.com/Casecommons/pg_search/blob/master/lib/pg_search/document.rb#L22. The only reason why this would raise the described TypeError is if PgSearch.multisearch_options is nil – which, as far as I understand the code, would only be possible if you accidentally overwrote it in a wrong way. So I'd suggest doublechecking your global setup for PgSearch.multisearch_options to make sure this is actually set.
The east way to check the setting is by using a debugger or putting something like puts PgSearch.multisearch_options or Rails.logger.info 'PgSearch.multisearch_options' into the controller directly above the call that's failing.
I get an error when I try to iterate through params
When running code below:
def create_score
#quiz = Test.find_by(password: session[:test_password])
#points = 0
#quiz.tasks.each_with_index do |task, index|
#task = Task.find_by(id: task)
#points += #task.score if #task.correct_answers.to_s == send("params[:test][:task#{index}]")
end
#score = Score.new(user_id: 2, name: "Test1", points: #points)
if #score.save
redirect_to root_url
else
redirect_to signup_path
end
end
I get:
undefined method `params[:test][:task0]' ...
at the
#points += #task.score if #task.correct_answers.to_s == send("params[:test][:task#{index}]")
Which means that it has problem with send method
Parameters look like this:
{"utf8"=>"✓",
"authenticity_token"=>"8h7rtv2yWio11DFo6kBKutdZl7RDBBaTrt7e8qel8fR5R5XsoXRhRrBeDQPPoZeuBlZ7N5PmqCxik06Z/gQLZQ==",
"test"=>{"task0"=>["4"], "task1"=>["0"], "task2"=>["10"]},
"commit"=>"Zakończ test",
"locale"=>"pl"}
Which means that there is params[:test][:task0], but still for some reason it fires an error, but I don't really know why. Any ideas why this happens?
You want to index with dynamic key, not call a method dynamically. Aka:
params[:test]["task#{index}"]
Should do. Note that params are have indifferent access for strings and symbols.
To give you more food for thought, here is how you might have done the same with #send:
params[:test].send(:[], "task#{index}")
And here is how to define a method that would have the name you are trying to call:
define_method("params[:test][:task#{index}]") do
puts 'WTF'
end
You're calling your params with a symbol but instead you should use a string.
This means you should use one of the following approaches:
params["test"]["task0"]
or
params[:test.to_s][:task0.to_s]
Hope that helped :)
You should use params object something likeparams[:test][:task]) instead of send("params[:test][:task#{index}]".
I'm trying to do something like this:
if user = User.find_by(email: 'example#example.com') && !user.activated?
# do something
end
but I get an error thrown saying "no method 'activated' for nil:NilClass"
Is there a way for me to accomplish this functionality without using a nested conditional?
You can use the control flow operator and over the logical operator && like so:
if user = User.find_by(email: 'example#example.com') and !user.activated?
# do something
end
Example:
if a = 12 && a.even?
"Working"
end
#=> undefined method `even?' for nil:NilClass
if b = 12 and b.even?
"Working"
end
#=> "Working"
This works because and has a lower precedent than assignment so the assignment will occur prior to the second conditional check.
As long as you don't mind the found = in conditional, should be == warnings.
Second Option:
Your other option is explicit parentheses ie.
if a = 12 && a.even?
"Working"
end
#=> undefined method `even?' for nil:NilClass
if (b = 12) && b.even?
"Working"
end
#=> "Working"
This works because the parentheses () will be evaluated first before the conditional is evaluated so the assignment will occur inside the parens and then be evaluated as part of the conditional.
More on Ruby Operator Precedence
Nope, You can not assign and use the same var in same line, you will need to break it up.
user = User.find_by(email: 'example#example.com')
if user && !user.activated?
# do something
end
Let me know if this helps. You can check user.nil? but above will work as well.
Thats the case when a user is not found. You should add exception handling in condition:
if user = User.find_by(email: 'example#example.com') && !user.try(:activated)?
# do something
end
I am running a spree app.
I am getting below error when I try to add any product in the cart.
undefined method `+' for nil:NilClass
This error comes only when I add option types and variants of the same product.
I am not sure what's exactly going wrong here, because I am not doing any changes in the code or something.
This is the extracted source it shows.
if quantity.between?(1, 2_147_483_647)
begin
order.contents.add(variant, quantity, options)
rescue ActiveRecord::RecordInvalid => e
error = e.record.errors.full_messages.join(", ")
end
Here's my order controller's populate function.
# Adds a new item to the order (creating a new order if none already exists)
def populate
order = current_order(create_order_if_necessary: true)
variant = Spree::Variant.find(params[:variant_id])
quantity = params[:quantity].to_i
options = params[:options] || {}
# 2,147,483,647 is crazy. See issue #2695.
if quantity.between?(1, 2_147_483_647)
begin
order.contents.add(variant, quantity, options)
rescue ActiveRecord::RecordInvalid => e
error = e.record.errors.full_messages.join(", ")
end
else
error = Spree.t(:please_enter_reasonable_quantity)
end
if error
flash[:error] = error
redirect_back_or_default(spree.root_path)
else
respond_with(order) do |format|
format.html { redirect_to cart_path }
end
end
end
Please help me out here.
You need to ensure the values of variant, quantity and options before sending them to spree.
The fact that you get this error could be considered as a bug on their side, since you'd expect a nice error message saying "variant is nil" or the like.
To fix your problem though, I'd check that these values are valid ones before sending them to spree.
For future views about this issue.
Check if the Variant cost_currency attribute is the same that is configured in Spree. You can check it in a rails console doing:
Spree::Config.get(:currency)
Sometimes it happens when spree is initialized with some currency by default and then the default currency is changed.
Can someone tell me why this code doesn't work? On my local server for testing, it keeps flashing "You have already upvoted this" when I haven't.
This is in my code for the votes controller.
def upvote
#vote = Vote.find(params[:post_id])
if current_user.votes.where(post_id: params[:post_id], value: 1)
flash[:notice] = "You have already upvoted this!"
redirect_to :back
else
#vote.update_attributes(value: 1)
#vote.user_id = current_user.id
end
end
Is the 4th line if current_user.votes.where(post_id: params[:post_id], value: 1) the correct way to implement the where method?
You should use exists?
if current_user.votes.where(post_id: params[:post_id], value: 1).exists?
If you use only current_user.votes.where(...), you get a Relation object that will always be interpreted as a true value in the if, even if tyhe Relation do not match any line (only false and nil are considered as falsy values in Ruby).