Mongoid returning object as array - ruby-on-rails

I am using tire/elasticsearch for searching with mongoid, when I update the index of my documents I am getting the error undefined method 'as_document':
#document.tire.update_index
undefined method `as_document' for #<Array:0x10a40f870>
I have researched the mongoid method 'as_document' and found out that it only accepts single objects. When my document objects do not have comments, "#document.as_document" returns a single object and there is no error, however when the document has comments, "#document.as_document" seems to return an array and returns the error "undefined method `as_document' for #".
It seems that when #document has comments, it returns an array of hashes.
Is there any way that I can return the array (Array:0x10a40f870) so I can see where it is coming from?
How can I convert #document (which seems to be an array) back into a single object so that it can pass through as_document?
Why am I getting an 'undefined method as_document'
I have a Document model with a has_many relationship to comments
Rails: 3.2.12,
Mongoid: 3.1.4

1. Logger is your homie. I would recommend printing this wherever your logic exists so you can see exactly what array you are returning.
Something like this:
# your logic here
#your_array = ..set
logger.debug "MY ARRAY: #{#your_array}"
This will give you at least a good look at what you are dealing with if you can take a look at Webrick or whatever setup you have.
2+3. Mongoid stores Documents as an array of hashes so that is what you are probably looking at (but I haven't seen the exact code).
I dont believe there is anything wrong with your document definitions but I would take a better look at the [Relations Sections] of the Mongoid docs1
More specifically to question 2: take a look at the operations section.

Related

undefined method `paginate' for #<PG::Result:0x007f8f096a3390 (Converting arel result)

I have the following method:
#vulnerabilities = Vulnerability.details(filter_version_param,
filter: filter,
sort: order)
.paginate(page: page_param, per_page: 10)
The internals of this method uses arel to find the relevant information to display on a page. However when I run into the .page method from the will_paginate gem, I receive the following error:
`undefined method `paginate' for #<PG::Result:0x007f8f096a3390>`
This is due of course to the fact that the object returned is not a class from ActiveRecord. My question is whether there is a way to convert the PG class into an ActiveRecord model? A previous implementation on the application from another developer creates a Struct.new() class and feeds the values into it. I was wondering though if there was an easier way to do this.
You have two options:
for Kaminary gem as an example : convert the query result into an
array and use Kaminary.paginate_array(array_of_result).page(#pagenumber).per(#elemnts per page), but this way could have problems with large data tables since you need to load the hole table for example, then slice the page!
you can build an object that has the sufficient methods needed for the paginator to do its job.
for more explanation and information about the above two points, please chick this link.

How do I mass update a field for models in an array?

I’m using Rails 4.2.7. How do I mass update a field of an array of my models without actually saving that information to the database? I tried
my_objcts_arr.update_all(my_object: my_object)
but this results in the error
NoMethodError: undefined method `update_all' for #<Array:0x007f80a81cae50>
I realize I could iteraet over the array and update each object individually, but I figure there's a slicker, one-line way in Ruby taht I'm not aware of.
update_all needs to be called on a class level active record model/relation, ie User or TaxReturn. Here is one somewhat related SO post showing some examples, and here is the api doc for update_all. It will send the UPDATE directly to the db (it is an active record method, after all), so it is not what you want.
You're best off iterating and updating the value yourself with collect or something similar, which is only one line.
foo = [{:a=>"a", :b=>"b"}, {:a=>"A", :b=>"B:}]
// => [{:a=>"a", :b=>"b"}, {:a=>"A", :b=>"B"}]
foo.collect{|x| x[:a]="C"}
// => ["C", "C"]
foo
// => [{:a=>"C", :b=>"b"}, {:a=>"C", :b=>"B"}]

Can I access the collection an instance method was called on in ruby on rails

I'm working on implementing a search form in a ruby on rails application. The general idea is to use form_tag to submit the search fields (via params) to a search function in the model of the class I'm trying to search. The search function will then iterate through each of the params and execute a scoping function if the name of the function appears in params.
The issue is that when I call the search on a collection like so:
#calendar.reservations.search({:search_email => "test"})
I don't know how to refer to the collection of #calendar.reservations from within the search function.
Additionally I'm confused as to why #calendar.reservations.search(...) works, but Reservations.all.search gives me an error saying you can't call an instance method on an array.
I've got the details of the search method over here: https://gist.github.com/783964
Any help would be greatly appreciated!
I don't know how to refer to the
collection of #calendar.reservations
from within the search function.
If you use self (or Reservation, it's the same object) inside the classmethod, you will access the records with the current scope, so in your case you will see only the reservations of a particular calendar.
[edit] I looked at you search function, and I think what you want is:
def self.search(search_fields)
search_fields.inject(self) do |scope, (key, value)|
scope.send(key, value)
end
end
Additionally I'm confused as to why
#calendar.reservations.search(...)
works, but Reservations.all.search
gives me an error saying you can't
call an instance method on an array.
#calendar.reservations does not return a standard array but a (lazy) AssociationCollection, where you can still apply scopes (and classmethods as your filter). On the other hand Reservation.all returns a plain array, so you cannot execute search there (or any scope, for that matter).
You don't really need a search method at all, as far as I can tell.
Simply use where:
#calendar.reservations.where(:search_email => 'test')
I would strongly encourage you to look at the MetaSearch GEM by Ernie Miller. It handles the kind of thing you're working on very elegantly and is quite easy to implement. I suspect that your view code would almost accomplish what the GEM needs already, and this would take care of all your model searching needs very nicely.
Take a look and see if it will solve your problem. Good luck!
Reservation.all.search doesn't work because it returns all the results as an array, while Reservation.where(..) returns an ActiveRecord object (AREL). Reservation.all actually fetches the results instead of just building the query further, which methods like where, limit etc do.

Accessing object values that have reserved keywords as names in Rails

I'm accessing the Amazon AWS API using the ruby-aaws gem, but without going to much into details of the API or the gem, I think my problem is more of a general nature.
When I query the API I will end up with "object array", let's call it item, containing the API response.
I can easily access the data in the array, e.g. puts item.item_attributes.artist.to_s
Now the API returns attributes whose identifier are reserved words in Rails, e.g. format or binding.
So doing this:
puts item.item_attributes.format.to_s will return method not found
while
puts item.item_attributes.binding.to_s will return some object hash like #<Binding:0xb70478e4>.
I can see that there are values under that name when doing
puts item.item_attributes.to_yaml
Snippet from the resulting yaml show artist and binding:
--- !seq:Amazon::AWS::AWSArray
- !ruby/object:Amazon::AWS::AWSObject::ItemAttributes
__val__:
artist: !seq:Amazon::AWS::AWSArray
- !ruby/object:Amazon::AWS::AWSObject::Artist
__val__: Summerbirds in the Cellar
binding: !seq:Amazon::AWS::AWSArray
- !ruby/object:Amazon::AWS::AWSObject::Binding
__val__: Vinyl
This was probably a very detailed explanation with a very simple solution, but I can't seem to find the solution.
edit
Finally found it. I guess it is because it is an array of objects, duh...
puts item.item_attributes[0].binding.to_s
You may be able to access the individual attributes by using [] instead of the method name (which is probably provided using method_missing anyway).
So, item.item_attributes[:artist].to_s may return what you want. If it doesn't it would be worth trying 'artist' as the key instead.
Finally found it. I guess it is because it is an array of objects, duh...
puts item.item_attributes[0].binding.to_s

How to get array of many_to_many assocation from array in Rails

I have the following code in Rails:
#possibleMatchingOffers = SmsOffer.valid.find(:all, :conditions => {:hub_phone_no => unhndledMsg.hub_phone_no})
#matchingContact = #possibleMatchingOffers.biz_sms_reply_queues.valid.find(:all)
The Error I'm getting:
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
#possibleMatchingOffers is an array so it's not accepting to use the association (.biz_sms_reply_queues).
I can figure out manual way to do it but I was wondering if there is better easy way to do this.
Thanks,
Tam
Without knowing what you're intention is here, it looks like you need to turn the first "find" into an named scope. So it would look something like:
SmsOffer.valid.by_hub_phone_no(unhndledMsg.hub_phone_no).biz_sms_reply_queues
Named scopes return AR Proxy objects, and thus, you can use an association on them.
What is "valid"? This isn't a rails method. Is it also a named scope? You should probably dry that up also.

Resources