Undefined method 'zero' for ... ActiveSupport::OrderedHash - ruby-on-rails

Check the note below. Why is it before I do p variant_attributes, blank? method returned error, while after it, it works fine?
Ruby 1.9.2-p0 on Rails 3.0.3
p variant_attributes.blank?
# => NoMethodError Exception: undefined method `zero?' for {"Brocade w/ Grande Stripe backing"=>3}:ActiveSupport::OrderedHash
p variant_attributes
# => [#<VariantAttribute id: 1251, variant_id: 561, product_option_id: 838, value: "Brocade w/ Grande Stripe backing">]
p variant_attributes.blank?
# => false

If variant_attributes is a kind of ActiveRecord collection of records (which it looks like) then it is probably because rails uses lazy loading to fetch records from the database but the blank? method does not trigger the actual loading.
You may want to call the all method on variant_attributes to manually trigger the loading, or if you don't want to do that, you may go for variant_attributes.count.zero? instead of variant_attributes.blank?
See Pratik Naik's blog post about ActiveRecord 3.0 query interface for the details

Related

Contentful Rails Test if Object is Empty

p entry # <Contentful::Entry[item] id='3oXocy0iJX8ksdfe435RjWjE'>
i = entry.image
p i.present? # true
p i.nil? # false
p i.respond_to?(:url) # true
p i.url # undefined method `url' for nil:NilClass
p i # undefined method `url' for nil:NilClass
I'm pulling an item from Contenful CMS and trying to render it in Rails. My content admin managed to delete the image (the field is actually called "image") on the entry, thereby causing the render to break. The code above is me trying to test for a missing image so I can skip rendering the section and not break my website.
As you can see, this is mindnumbingly insane. Rails says the entry is there (it is), it says it's not nil, then immediately below it throws an error for nil:NilClass.
The last line is probably the most interesting - even if I just try to print or inspect "i" I still get the error as if I'm trying to access the url attribute. I feel like I'm taking crazy pills.

Memcache basic use in rails 3

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]

Ruby === not acting as it when left-hand argument is a class

I'm using Ruby 1.8.7 with Rails 3.0.1 and am having a problem whose root cause appears to be the "Array === object" operation. I saw the same behavior before in a class of my own creation, and programmed around it by not using the "===" operator (I assumed that there was some flaw in my knowledge of Ruby, which is still rather limited). But now that it is happening inside ActionPack, I need to do something about it.
This surfaced when the FormHelper "fields_for" was not acting the way it should. The following view code snippet ("<% %>" removed to improve readability):
form_for #coupon do |f|
...
f.fields_for #coupon.participants do |cp|
...
end
end
gave the error "ActionView::Template::Error (undefined method `model_name' for Array:Class):"
inside the form_for helper method. I determined that it was executing the wrong branch of a "case" command, set a breakpoint and started testing. Here are the results:
/Library/Ruby/Gems/1.8/gems/actionpack-3.0.1/lib/action_view/helpers/form_helper.rb:1152
case record_or_name_or_array
(rdb:1) pp record_or_name_or_array.instance_of? Array
true
(rdb:1) pp Array === record_or_name_or_array
false
(rdb:1) pp Array.object_id
2148267660
(rdb:1) pp record_or_name_or_array.class.object_id
2148267660
This shows pretty definitively that, while "record_or_name_or_array" is definitely an array, "Array === record_or_name_or_array" is returning false.
BTW, in case you're suspecting that "#f.fields_for" is the wrong syntax, I tried it both with and without the "#f." and got the same result. I have also restarted RoR and my machine and the results remain unchanged.
Try this:
#coupon = Coupon.last
Array === #coupon.participants #=> false
Array === #coupon.participants.find(:all) #=> true
Association #coupon.participants is not an array, it is a proxy. The reason why #coupon.participants.class == Array is true is described in activerecord-3.0.9/lib/active_record/associations/association_proxy.rb:25
Added: Another interesting experiment would be #coupon.participants.superclass.
From the console (rails c) try running:
#coupon = Coupon.last
Array == #coupon.participants
If that call returns false, it is most likely that your associations are incorrectly setup (i.e. has_many :participants and belongs_to :coupon).
#coupon.is_a? Array should return true, #coupon === Array would mean #coupon was equal to the singleton instance of Array

Cannot access data in active record using dot notation

I created a model in Ruby and am stuck on a n00b issue. In Rails Console:
s = Survey.where(:keyword => 'foo')
=> [#]
s.inittxtmsg
NoMethodError: undefined method inittxtmsg' for #<ActiveRecord::Relation:0x10350f8f8>
from /Library/Ruby/Gems/1.8/gems/activerecord-3.0.5/lib/active_record/relation.rb:371:inmethod_missing'
from (irb):3
Shouldn't I be able to see the values by typing s.Survey_id, s.inittxtmsg, s.keyword, s.store?
Thank you!
Survey.where(:keyword => 'foo')
returns an array of results, so you are really calling .inittxtmsg on an array, which obviously doesn't exist.
You could do something like:
Survey.where(:keyword => 'foo').first.inittxtmsg, in which it is calling it on the actual model object.
Or if you know that there is only one survey with the keyword = foo... you can use the find method to only return a single model object:
s = Survery.find_by_keyword("foo")
s.inittxtmsg

Rails 3 - Undefined method on certain collections

I have a search method written for my model Link.
I've been able to called this method without error until implementing voting. For example, these all work:
Link.search(params[:search])
current_user.links.search(params[:search])
current_account.links.search(params[:search])
The following does not work:
#links = current_user.votes.collect {|vote| vote.voteable}
#favorites = #links.search(params[:search])
and return this error:
undefined method `search' for #<Array:0x00000006919ac8>
I've done some testing, to see if my class is wrong, in the console:
links = user.votes.map {|vote| vote.voteable}
links.class
=> Array
links.first.class
=> Link
This should be no different than my working examples:
user.links.class
=> Array
user.links.first.class
=> Link
I thought maybe the error was from me calling search on an array and not a link. But in previous examples I'm also calling it on an array.
I'm using vote_fu to handle the voting thus the vote/voteable.
The search function or scope that you have defined is defined on the Link object and is usable in Link relations, but it is not defined on a simple array, which is what is getting returned from the first collect example. Here is a simple distinction:
class User
scope :search, lambda{ |name| where(name: name) }
end
User.search('Kombo').all # Returns an array of the SQL result run against the DB
User.all.search('Kombo') # NoMethodError: undefined method `search' for #<Array:0x000001079b15b0>
In your first example, Link.search(params[:search]), you are performing the equivalent of User.search.all, and User is a scoped ActiveRecord relation/object, which means it can continue to be combined with other scopes, like where, limit and group. In the second example, #links = current_user.votes.collect {|vote| vote.voteable}, collect is acting on such a relation and is returning a simple array which can no longer be acted upon with these scoped functions. The second example is like doing User.all.search.
It's confusing because both of these examples resolve to an Array eventually, but the difference is what is happening before that resolution to an Array, and when you are actually calling the search function. To get around this you'll have to actually call the search scope or function on an ActiveRecord object, like Link or an ActiveRecord Relation like current_user.links, but you won't be able to call it on a result. Just to clarify:
Link.search(params[:search]) # will work
Link.all.search(params[:search]) # will not work
current_user.links.search(params[:search]) # will work
current_user.links.all.search(params[:search]) # will not work
current_account.links.search(params[:search]) # will work
current_account.links.all.search(params[:search]) # will not work
When you call .collect you are implicitly calling .all, which breaks the scope chain. The following two commands are equivalent in that respect:
#links = current_user.votes.collect {|vote| vote.voteable}
#links = current_user.votes.all.collect {|vote| vote.voteable}

Resources