How to find documentation for ActiveRecord::Base.update? - ruby-on-rails

What is the process of finding the documentation for a method in Ruby/Rails api http://api.rubyonrails.org/ .
Let's take method ActiveRecord::Base.update as an example. It is used in one of the railscasts.
There is no mention of update in the api doc for the class
http://api.rubyonrails.org/classes/ActiveRecord/Base.html
There's
nothing about update method in the source code for Base
https://github.com/rails/rails/blob/0065f378262dc3f47880ce6211c7474bc7d11f0b/activerecord/lib/active_record/base.rb
In fact, I can't even find this method in any classes included in
ActiveRecord::Base.
I suspect this method is in ActiveRecord::Relation. However, I'm not sure.
I'm a beginner in Ruby/Rails, and I come from Java world, where I would normally expect to see all methods (inherited as well) in a javadoc for the class. What is the most effective finding relevant documentation for mixed-in/inherited methods in case of Ruby/Rails?
Thanks in advance!

You probably can't find any good documentation about ActiveRecord::Base#update because the method has been deprecated since Rails version 2.3.8, according to APIdock..
The reason you can still use it is because it has been moved to ActiveRecord::Relation which can be seen in rails/activerecord/lib/active_record/relation.rb.
rails/activerecord/lib/active_record.rb contains all the autoloads for ActiveRecord which includes :Relation.
The documentation for ActiveRecord::Relation#update is as follows:
Updates an object (or multiple objects) and saves it to the database,
if validations pass. The resulting object is returned whether the
object was saved successfully to the database or not.
==== Parameters
+id+ - This should be the id or an array of ids to be updated.
+attributes+ - This should be a hash of attributes or an array of hashes.
==== Examples
# Updates one record
Person.update(15, :user_name => 'Samuel', :group => 'expert')
# Updates multiple records
people = { 1 => { "first_name" => "David" }, 2 => { "first_name" => "Jeremy" } }
Person.update(people.keys, people.values)
EDIT: To answer your initial question, under most circumstances, doing a search on api.rubyonrails.org is enough to find the information you are looking for, as long as the information is up-to-date.
For potentially older API details, use apidock.com/rails. Doing a search there for 'update' actually shows both versions (::Base and ::Relation) and gives you details about each and what version of Rails each are used in.

ActiveRecord::Base.update doesn't exist anymore as you can see here : http://apidock.com/rails/ActiveRecord/Base/update/class, it's ActiveRecord::Relation now as here : http://apidock.com/rails/ActiveRecord/Relation/update

Related

Clone a mongodb collection from within Rails Mongoid

I am trying to implement this solution in rails, using the collection aggregate method, to clone an entire collection within the same database.
In mongo shell, this works perfectly, and a cloned collection is created successfully:
db.source_collection.aggregate([ { $match: {} }, { $out: "target_collection" } ])
The rails-mongoid alternate, according to my research, should be this, which runs without errors:
SourceCollection.collection.aggregate({"$match" => {}, "$out" => "target_collection"})
#<Mongo::Collection::View::Aggregation:0x000000055bced0 #view=#<Mongo::Collection::View:0x44951600 namespace='DB_dev.source_collection' #filter={} #options={}>, #pipeline={"$match"=>{}, "$out"=>"target_collection"}, #options={}>
I also tried with an array
SourceCollection.collection.aggregate([{"$match" => {}}, {"$out" => "target_collection"}])
#<Mongo::Collection::View::Aggregation:0x000000054936d0 #view=#<Mongo::Collection::View:0x44342320 namespace='DB_dev.source_collection' #filter={} #options={}>, #pipeline=[{"$match"=>{}}, {"$out"=>"target_collection"}], #options={}>
UPDATE
This simplest syntax also works in Mongo console:
db.source_collection.aggregate( { $out: "target_collection" } )
But the respective syntax does not seem to work in Ruby:
SourceCollection.collection.aggregate({"$out" => "target_collection"})
Unfortunately, although there are no errors, the collection is not created.
Any clues as to the way I can make this happen?
Mongo gem version 2.5.3
Update2
Apparently $out is not considered in the pipeline, thus rendering the aggregation invalid.
This can be fixed with code... I am looking for a module/class/method override, as contacting mongodb issue tracking system for a change request might not be as quick..
UPDATE - FINAL
This issue has been solved, by help of Thomas R. Koll (thank you).
I add an update to post the response I got from the ticketing service of MongoDB, which pretty much describes Thomas's solution.
The reason you're not seeing the results without count is that the
aggregate method returns a lazy cursor; that is, the query does not
execute until the return value of aggregate is iterated over.
Calling count is one way to do this. This is the same behavior
you'll see if you call find or if you call aggregate without
specifying $out; the difference is that $out has an side-effect
beyond just returning the results, so it's more obvious when exactly
it occurs.
Found the solution, and I have to explain a few thigs:
This returns a Mongo::Collection::View::Aggregation object, it won't send a query to the database
User.collection.aggregate({"$out": "target_collection"})
Only when you call a method like count or to_a on the aggregation object it will be sent to the server, but if you pass a hash you'll get an error, so the pipeline has to be an array of hashes to work
User.collection.aggregate([{"$out": "target_collection"}]).count

Query/scope not including unsaved records in association

Scenario: I have a quiz type setup where Questions have many Answers and also have a Response provided by the user (omitted). A response has a selected attribute to indicate the user's choice and a correct? method that compares selected with the correct_answer.
Code: is here in this GitHub repo, along with seed data. Quick links to:
Question.rb
Answer.rb
Response.rb
Problem: I want to return all responses for a question that are correct however, unsaved records are not included.
I've tried a couple of different ways, as you'll see in the code including scope, question.correct_responses and also inverse_of (which I've read is supposed to be automatic now) - but to no avail.
Basically, I'm expecting following code to return 1, not 0.
q=Question.first
r=q.responses.build
r.selected = q.correct_answer
q.responses.correct.size # => 0??! wtf man!?
Your assistance is greatly appreciated.
When you use a scope you're going to the database.
Since you aren't saving the response, you don't want to go to the database. Instead, you should use something like the line below, which will select all of the question's "correct" responses and then count them.
q.responses.select { |r| r.correct? }.size
EDIT: or the short syntax for select:
q.responses.select(&:correct?).size

Rails TMDB API Browse to Find

TMDB.org recently made a change to their API which removes the capability to browse their database.
My Rails app used to use the tmdb-ruby gem to browse the TMDB database, but this gem only worked with v2.0 of the API, which is now defunct.
TMDB.org recommends using this gem, and since it is forked from the gem I previously used, it makes it a bit easier.
My PostgreSQL database is already populated with data imported from TMDB when v2.0 was still extant and when I could use the browse feature.
How can I now use the find feature (ie: #movie = TmdbMovie.find(:title => "Iron Man", :limit => 1) ) to find a random movie, without supplying the title of the Movie.
This is my rake file which worked with the older gem.
I would like to know how to have it work the same way but whilst using the find instead of the browse.
Thanks
I don't think find is what you need in order to get what you want (getting the oldest movies in the database and working its way up to the newest movie). Looking at the TMDb API documentation, it looks like they now have discover that may have replaced the browse that you used to use.
I don't see discover anywhere in Irio's ruby-tmdb fork, but it looks like most of the specific methods they have (like TmdbMovie.find) call a generic method Tmdb.api_call.
You should be able to use the generic method to do something like:
api_return = Tmdb.api_call(
"discover/movie",
{
page: 1,
sort_by: 'release_date.asc',
query: '' # Necessary because Tmdb.api_call throws a nil error if you don't specify a query param value
},
"en"
)
results = api_return["results"]
results.flatten!(1)
results.uniq!
results.delete_if &:nil?
results.map!{|m| TmdbMovie.new(m, true)} # `true` tells TmdbMovie.new to expand results
If this works, you could even fork Irio's fork, implement a TmdbMovie.discover method supporting all the options and handling edge cases like TmdbMovie.find does, and send them a pull request since it just looks like they haven't gotten around to implementing this yet and I'm sure other people would like to have this method as well :)

is there any core function find_by_controller in ruby on rails framework?

My first project as a software engineer is adding features to an existing ruby on rails crm application. I had to add functionality for sending an automated email, for which I just copied and pasted from another place in the program, where this was happening. The trouble is that now I want to modify it. Here's the code that does it?
recipient = session[:registration][:email]
subject = ManagedContent.get_email_subject("checkout", session[:registration][:id])
message = ManagedContent.find_by_controller("checkout").content_text
RegistrationConfirmationMailer.deliver_registration_message(recipient, subject, message, #registration_transaction.registration.id, render_to_string(:template => "registration_invoices/show.haml", :layout => 'none', :locals => {:registration => #registration_transaction.registration, :event => #registration_transaction.registration.event}) )
From what I gather from this that the message to be sent is being crafted in third line by calling find_by_controller() function. However, I can't find that function either in ManagedContent model or controller. I have even done a grep search of the entire workspace for this project, I didn't find any definition. Googling too didn't return anything that I could make sense of. Where can I look for this method definition as I need to make a little modification in the message
Thank you!
find_by_(field) is an ActiveRecord construction letting you find a record based on the value of a field.
See http://guides.rubyonrails.org/active_record_querying.html (especially section 14 on Dynamic Finders).
So you should look for a "controller" column in your managed_content table. Based on the code you copied, there is a row in that table with a value "checkout" for the controller column. In that same row, the value for the "content_text" field is the value you want to change.
PS: Congrats on your first software gig. Enjoy it while still untainted. :)
If your ManagedContent is a ActiveRecord class, doing find_by_controller generates an SQL request on your ManagedContent table to do a restriction on controller columns.
All is in dynamic finder documentation

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