def refresh_menu
#menu_pages = []
$menu_items.each do |id|
#menu_pages[id - 1] = Page.find(id)
end
end
$menu_items is just an array [1,2]. Obviously what I want to do is populate #menu_pages with all the pages found as per $menu_items.
Mind you,
#menu_pages = Page.all
works just fine. So how come I can't add them one-by-one with Page.find(id)?
The error returned:
You have a nil object when you didn't expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.each
Why not just do?...
def refresh_menu
#menu_pages = Page.where(:id => $menu_items)
end
And in relation to the error, where is $menu_items defined?
nowk, thanks for the neat trick.
To those who might find this through search: don't forget to restart the server when you make changes to initializers.
Where are you defining $menu_items? From your error message, it looks like the refresh_menu method can't see it - and thus thinks it's nil.
Related
I have a long loop that results in this:
csv_code = CSV.generate do |csv|
csv << ["Product ID","Name", "Url"]
#all_products.each do |product|
if product.page_url("en_US") != nil
turl = product.page_url("en_US")
end
csv << [product.name,product.d_id, turl]
end
end
The method uses products 1-17 works great resulting in a url printed. When I get to my 18th record I have problems
Product.find(18) // product found!
product.find(18).page_url("en_US")
NoMethodError: undefined method `page_url' for nil:NilClass
How can I protect against these undefined events?
url = product.page_url("en_US")
The issue is that a product is nil:
undefined method 'page_url' for nil:NilClass". Solution:
(It has nothing to do with page_url maybe returning nil.)
Make sure product can't be nil: but be wary that this may be a deeper issue. In any case, "fixing" this issue is easy to deal with.
Consider either using a collection restriction (such as Enumerable#reject):
#all_products.reject(&:nil?).each do {
...
}
The above uses the Symbol#to_proc "Rails magic", but could just as easily have been {|x| x.nil?} as the restriction. The downside is it's not practical to use this for a "no URL" condition per-product although Enumerable#partition could help with that: use the right tool for the job.
Another solution is to expand the conditional check itself:
if product && product.page_url("en_US")
# yay
else
# uhm
end
The short-circuit nature of && will ensure page_url is only invoked upon a truthy value (which excludes nil).
I also took the liberty of assuming page_url can't return false as I find this makes the intent more clear.
Happy coding.
Try this:
product.find(18).try(:page_url, "en_US")
But it's a perf killer.
Are you sure Product.find(18) doesn't return nil ?
Anyway, you could do:
url = product.nil? ? "no_url" : product.page_url("en_US")
So I'm trying to learn how to use memcache. I installed it in my system. I'm running it. I installed the dalli gem.
All that seems to be just fine.
Lets say I'd like to cache my users table.
I put this in my User.rb file:
def self.all_cached
Rails.cache.fetch('User.all') { all }
end
Then in my controller file, I used to have:
#users = User.where(:group_id => current_user.group_id)
So now I'd like to have something like:
#users = User.all_cached.where(:group_id => current_user.group_id)
I'm getting a no method error for where... Any ideas for how I should accomplish this?
Based on your comment there, I take it you are getting an error like:
undefined method `where' for #<Array:0x00000004d92520>
That's because where works on a model, but when you do User.all, it returns basically an array, and there is no where method defined for an array.
You may want to use the find_all method for enumerables (and arrays) instead (as seen here: http://www.ruby-doc.org/core/classes/Enumerable.html#M001484), or even try a different approach all together. That's your choice.
Here is the example they give to give you an idea off the bat of how it would work:
(1..10).find_all {|i| i % 3 == 0 } #=> [3, 6, 9]
This question already has answers here:
How to avoid NoMethodError for missing elements in nested hashes, without repeated nil checks?
(16 answers)
Closed 7 years ago.
I have the following very ugly ruby code in a rails app I'm working on:
if params.present?
if params[:search].present?
if params[:search][:tags_name_in].present?
...
end
end
end
All I'm trying to ask is whether params[:search][:tags_name_in] has been defined, but because params, and params[:search], and params[:search][:tags_name_in] might all be nil, if I use...
if params[:search][:tags_name_in].present?
... I get an error if there are no params or no search params.
Surely there must be a better way to do this... suggestions??
if you are just trying to see if its defined why not keep it simple and use the defined? function?
if defined?(params[:search][:tags_name_in])
Params will always be defined, so you can remove that.
To reduce the amount of code you can do
if params[:search] && params[:search][:tags_name_in]
#code
end
If params[:search] is not defined, the condition will short circuit and return nil.
You can use andand for this. It handles this exact situation:
if params[:search].andand[:tags_name_in].andand.present?
You have many choices that will return the value of params[:search][:tags_name_in] or nil if params[:search] is nil.
Clear but lengthy:
params[:search] && params[:search][:tags_name_in]
Using try (from active_support):
params[:search].try(:[], :tags_name_in)
Using rescue:
params[:search][:tags_name_in] rescue nil
Using fetch:
params.fetch(:search, {})[:tags_name_in]
Note that fetch can sometime be used to avoid the if altogether, in particular if there is nothing to do when the param is not specified:
def deal_with_tags
MyModel.where :tags => params.fetch(:search){ return }[:tags_name_in]
end
Haha, if you want to be terrible and monkeypatch nil:
class NilClass
def [](key)
nil
end
end
I would recommend a short-circuited if like the other answers suggest, though.
I usually end up doing something like this:
if params.has_key?(:search) && params[:search].has_key?(:tags_name_in)
...
end
Although if you don't mind testing against nils in your if statement you could also do this:
if params[:search] && params[:search][:tags_name_in] ...
This will not throw an error because ruby short-circuits the && operator.
I has a model "modela" that has a has_many_through relationship with model "submodelb". In a controller I want to check if modela has any submodelb associated with it. I have tried the two code examples below; however, the both throw the error "undefined method `submodelbs'" if modela does not have any submodelbs. Please help me see what I am doing wrong.
Sample 1:
if !#modela.submodelbs.nil?
#submodelbs = #modela.submodelbs
else
#submodelbs = []
end
Sample 2:
if !#modela.submodelbs.empty?
#submodelbs = #modela.submodelbs
else
#submodelbs = []
end
You can use .present? which is the opposite of blank?
#submodelbs = #modela.submodelbs.present? ? #modela.submodelbs : []
But I think your problem is that #modela may be nil or you may have not defined associations correctly in the model.
The reader method produced by has_many_through always returns something that looks like an Array, so it should never return nil. So, can't you just return #modela.submodelbs always?
I use blank?
unless #modela.submodelbs.blank?
#modela has submodelbs
end
but error messege suggests that you may have something wrong with association definition...
Also what you are trying to achieve can be done with one-liner
#modela.submodelbs ||= []
if submodelbs are nil empty array will be assigned.
Why not just put your checks in a begin...rescue...end block?
I'm some what new with ruby on rails, so I'm attempting to debug this error that I'm getting but, from my understanding, is working on the prod code.
The error:
NoMethodError in JoinController#index
undefined method `join_template' for nil:NilClass
/app/controllers/join_controller.rb:5:in `index'
Okay, so line 5 in index is:
elsif current_brand.join_template == 'tms'
So clearly current_brand is nil. The controller is a child class of AppController, so checking that out I see that current_brand is a method:
def current_brand
return #current_brand if defined?(#current_brand)
url_array = request.env['HTTP_HOST'].split('.').reverse
url = url_array[1] << "." << url_array[0]
#current_brand = Brand.find(:first, :conditions => ["url LIKE ?", "%" << url << "%"])
end
It seems that #current_brand is always returned, yet it's continuing to be Nil. What could the problem be?
It may be your query is not returning anything. You can use a debugger, but it's pretty easy to just output #current_brand and see what it evaluates to.
logger.debug(#current_brand)
You must check two things:
Does Rails build the SQL query properly with the url passed in on the last line of that method?
Does the record exist in the brands table? you're not actually checking for that.
Also, passing in the url like that opens you up to a potential SQL injection attack.
You need to rewrite your definition with a rescue or if/else so if you do get a nil element then it won't be a fatal error.
This is your problem:
#current_brand = Brand.find(:first, :conditions => ["url LIKE ?", "%" << url << "%"])
#current_brand is not finding anything so make sure you find something.
#current_brand = Brand.find(:first)
If this fixes the problem then you know it is not finding anything and you will need to change your code that if it returns nil then it doesn't provide the function or it finds a default brand such as what I suggested.