Rails TMDB API Browse to Find - ruby-on-rails

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 :)

Related

EmberJS 2.7, Rails 5, AMS 0.10.2 - GET resources collection where fieldX=[B or C]

I have an EmberJS filter like this:
/app/routes/trails/new.js
model: function (filterCurrentEmployees) {
return Ember.RSVP.hash({
trail: this.store.createRecord('trail'),
employees: this.store.query('employee', { status: '1,2'}).then(
function(data) {return data})
})
},
I was hoping that status: '1,2' would end up as a normal Rails param so I could do params[:status] and then filter the returned employees (you know so the db would get a query like 'where status IN ['1','2']')
But when this filter query is sent to Rails API I get this error:
ActiveModelSerializers::Adapter::JsonApi::Deserialization::InvalidDocument (Invalid payload ({:data=>"Expected hash"}): {"status"=>"1,2", "controller"=>"employees", "action"=>"index"}):
which occurs here in the controller:
api/app/controllers/employees.rb
def employee_params
ActiveModelSerializers::Deserialization.jsonapi_parse!(params)
end
but that is needed for AMS to work with Ember.
So I presume something is wrong with the way I am sending/creating the query in EmberJS?
It seems to be trying to make a GET collection request. Not sure really and this explains sort-of what is going on at the Rails end, but I don't know how to get Ember to create the filter properly so that AMS is happy to accept it.
EDIT - JSON-API Spec Reference
I was under the impression that AMS and Ember 2.7 with JSON-API 'just work out of the box'. I was actually expecting the Ember filter to comply with the spec and send
/employees?filter=status[1,2]
but it seems to not be doing that. AMS says the same thing here.
UPDATE
So with some pointers from the comments (thank you) I learned that the structure of the query hash might be incorrect. I also tried changing 'query' to filter but that then raises an actual Ember error:
The filter API has been moved to a plugin. To enable store.filter using an environment flag, or to use an alternative, you can visit the ember-data-filter addon page.
Now I don't know what the difference is between an Ember query and an Ember filter, perhaps a filter only runs on the client? Who knows, the docs are so sparse and so many questions on this are 1 or 2 years old.
So after much digging around for Ember Gold Nuggets, I found out that Controllers are STILL needed for...you guessed it...Query Parameters.
I've never used a Controller, and thought I never needed one.
So it seems I was basing my attempt at using query parameters on outdated information and code examples.
For those who run into this, the gold nuggets are here and here.
Also, it seems Javascript Object parameters as per JSON-API spec are not yet supported in Ember, according to this, although it's nearly a year old so do not know if that is still true.
UPDATE
So, after further gold mining, it seems I was confused and that Controllers are needed for Query Parameters in Ember on the client side, to assist the frontend application when it transitions from one route to another (and that is when you need a Controller to set them up).
But I want to just send a query parameter from within the Route code directly to the API, and examples of doing that are very hard to find.
So in the Rails Log I would expect to see BEFORE deserialization by ASM:
Rails.logger.info "Params are: #{params.to_json}"
something like this:
Params are:
{"data":{"filter":{"status["1,2"]}},
"controller":"employees","action":"index"}
ASM expects 'data' to be the root element of the hash, and then inside that I can place my filter. For example, from the Ember Route:
model: function () {
let myFilter = {};
myFilter.data = { filter: {status: ['1,2']}};
return Ember.RSVP.hash({
trail: this.store.createRecord('trail'),
employees: this.store.query('employee', myFilter).then(function(data) {return data})
})
},

How to efficiently update many ShopifyAPI::Product instances using ShopifyAPI (Ruby on Rails)?

I am writing an app which will sit between a vendors proprietary inventory management system and their Shopify shop. The app will periodically update Shopify from new data generated by the inventory management system. It will also provide end-points for Shopify webhooks.
I am currently doing something like this (pseudo-ruby with much stuff omitted):
def update_product_with_proxy(product_proxy)
product_proxy.variant_proxies.dirty.each do |variant_proxy|
update_variant_with_proxy(variant_proxy)
end
if product_proxy.dirty_proxy
shopify_product = ShopifyAPI::Product.find(product_proxy.shopify_id)
shopify_product.update_attributes({some attributes here})
end
end
Elsewhere:
def update_variant_with_proxy(variant_proxy)
shopify_variant = ShopifyAPI::Variant.find(variant_proxy.shopify_id)
shopify_variant.update_attributes({some attributes here})
end
This seems terribly inefficient as I have to fetch each updated ShopifyAPI::Product and ShopifyAPI::Variant before I can update them (I have their id's cached locally). It takes about 25 minutes for an update cycle updating 24 products each with 16 variants. Rails spends less than 2 seconds updating my product/variant proxies. The other 99% of the time is spent talking to Shopify. I must be doing something wrong.
Given that I know the id of the remote object is there a way to updated it directly without having to fetch it first?
cheers,
-tomek
First things first: You can update variants through their parent product. Once you've grabbed the product it'll have the variant info with it so you can edit them, save, and the changes will be persisted in a single API call. That'll save you some time.
Second: You can create an object locally using the gem, give it an id, and then call save to initiate the PUT request without first fetching the object from Shopify. Something like this should do the trick:
product = ShopifyAPI::Product.new(:id => 1, :title => "My new title")
product.save
Putting those two things together should give you what you want: The ability to update a product's variants in a single API call.
Note: For future reference, the shopify_api gem is built on Active Resource, so anything you can do with that library you can do with the gem.

How to find documentation for ActiveRecord::Base.update?

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

Not able to set meta data on a resque-status hash

As per the resque-status home page on GitHub I should be able to pass back data from a job. For some reason this does not seem to be working for me. If anyone else has encountered this problem and worked around it I would like to know how.
I am using resque-status with JRuby 1.6.5 in a Rails 3.2.3 application.
Passing back data from the job
You may want to save data from inside the job to access it from outside the job.
A common use-case is web-triggered jobs that create files, later available for download by the user.
A Status is actually just a hash, so inside a job you can do:
status['filename'] = '/myfilename'
Also, all the status setting methods take any number of hash arguments. So you could do:
complete('filename' => '/myfilename')
Apparently such functionality is not implemented, as read on
https://github.com/quirkey/resque-status/issues/66
we've found a work around using the function set_status to add the required data to the status hash:
set_status({"my variable" => "my value" })
hope this helps!

What is the best way to access Google Calendar from ruby?

I'm writing an app for a company that uses Google Calendar internally and would need to use events they already have in their calendar in the app. So I need to get read only access to their calendars from the app (namely I need the events title, start and end dates and attendee emails for all future events).
What is the simplest way to do this in ruby (I would need it to work relatively seamlessly on Heroku)?
I tried using the GCal4Ruby gem which seemed the least outdated of the ones I found but I'm unable to even authenticate through the library (HTTPRequestFailed - Captcha required error) let alone get the info I need.
Clarification: What I'm talking about is the Google Apps version of the calendar, not the one at calendar.google.com.
OK I got the api via GCal4Ruby working. I'm not exactly sure what went wrong the first time. Thanks to Mike and James for their suggestions. This is sample code I used for anyone interested:
require "rubygems"
require "gcal4ruby"
serv = GCal4Ruby::Service.new
serv.authenticate "username#example.com", "password"
events = GCal4Ruby::Event.find serv, {'start-min' => Time.now.utc.xmlschema,
:calendar => 'example-cal%40example.com'}
events.each do |event|
puts event.title
puts event.attendees.join ", "
puts event.start_time
puts event.end_time
puts '-----------------------'
end
You should be able to use the Google Calendar private xml address feature to pull out the needed data.
You could then parse it with hpricot or nokogiri to extract whatever fields you need.

Resources