find_or_create_by_facebook_id method not found - ruby-on-rails

I'm trying to find out where this function comes from. Any one have any clue? It's used by this:
http://github.com/fluidtickets/facebooker-authlogic-bridge
with a working example here:
http://facebooker-authlogic-bridge.heroku.com
Downloading the code, it throws: undefined method 'find_or_create_by_facebook_id' for #<Class:0xb04dd1c>
I have no clue where this function comes from.
Thanks all!

ActiveRecord creates dynamic finders based on columns in your database. So for example if you have a user with a username attribute then activerecord creates a number of dynamic finders:
find_by_username
find_or_initialize_by_username #=> calls new if not found
find_or_create_by_username #=> calls create if not found
You can string a few attributes together like
find_by_username_and_email
To get back to your problem - I suspect that you haven't run some required migration that adds the facebook_id to your users table in the db and therefore ActiveRecord isn't adding the dynamic finder for facebook_id to the class.

Related

private method `catch' called for Hotel (ruby 2.1 rails 4)

There's a column named catch in hotels table.
I created an object:
obj_hotel = Hotel.new
and then :
obj_hotel.catch = 'xxx'
Error occurred when I did the following thing:
puts obj_hotel.catch
There is no problem when obj_hotel.catch at the left of =, but when we want to use the value of obj_hotel.catch, I get the error private method 'catch' called for Hotel happened.
So, is catch a private method of rails?
Thank you.
Kernel#catch is a private method, and Kernel is present in the ancestor chain of all objects that descent (including) Object.
Ah, it would definitely seem so. As pointed out by azlazarov, Kernel#catch is a private method. You should avoid having column-names matching with ruby reserved names. So if possible rename the column (migrate the database).
If that is not possible, there is an easy workaround, you can always use
obj_hotel["catch"]
to get or set an attribute.
You can also alias an attribute name, using
alias_attribute :new_column_name, :catch
which is a very clean solution, but also potentially dangerous/confusing, imho, because when writing queries (in arel, e.g. a where) you will have to refer to catch instead of your alias).

Mongoid returning object as array

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.

How to refer to the current record in a Rails query?

In a Rails controller I'm using a JSON request to an external database to return integers that are used to order a collection of records:
Model.order(JSON.parse(open("http://myapp.com/models/#{:id}")).read)['attribute'])
I want to make this dynamic to aid switching between environments. Something like:
Model.order(JSON.parse(open(model_url(model))).read)['attribute'])
This is not correct, and model_url(model) is returning an error:
undefined local variable or method 'model'
How do I refer to self in query?
There must be a more elegant solution than
...JSON.parse(open("#{root_url}/models/{:id}"))....
EDIT:
Lightswitch05's answer below does anser the question I asked. The query should reference params[:id] to get the url of the current record.
In fact, I have decided to move this JSON call into a virtual attribute on the model. This means I can simply call Model.order(:my_virtual_attribute). While this solution brings its own share of issues—I needed to make url_helpers available to the model—in the long run I think this will be a cleaner solution.
As per our discussion the problem is that model is not defined. Since all you are trying to do with model is get the url to it, all you really need is params[:id]. This will fix your error message:
Model.order(JSON.parse(open(model_url(params[:id]))).read)['attribute'])
where model has been replaced with params[:id]
Change your code:
Model.order(JSON.parse(open(model_url(model))).read)['attribute'])
to:
model_tableized = Model.to_s.tableize
model_url = "#{model_tableized}_url(#{model_tableized.chomp('s')})"
Model.order(JSON.parse(open(model_url).read)["attribute"])
I think that should work.
You need the name method.
If you're using the model, and not an instance of the model, it would be Model.name
If you're using an instance, it would be
#model = Model.first
#model.class.name

Check if record exists in Rails before creating

I am trying to search my database before I enter the record, by doing this:
Product.update_or_create_by_name_and_date_and_applicationURL_and_server_and_addi_servers(app_name, app_date,url_app,server_name,addi_servers)
the problem is that I get an undefined method exception!
Is there another way to search for the same record before entering one?
You should use two steps:
#Suggestion 1
obj = Product.find_or_create_by_...
#Suggestion 2
obj = Product.find_or_initialize_by_...
obj.update_attributes hash_here
Rereading, your question, I can't really understand what do you want to update if you try to find an object with known attributes. Anyway, you would just have to adapt my answer a little if some fields are for identifying and some for update.
I would define a function in your model: something like
Product.find_by_everything
where you write out all the parameters of the search, instead of using the the long naming method.
Then, if that returns nil, create the product. This doesn't seem to be a good use case of using the built in activerecord naming methods.

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.

Resources