Finding sets in Rails - ruby-on-rails

I'm a Rails noob, but I'd like to use it as a backend for an Ember application with Ember Data. Unfortunately, I have some unknown unknowns.
The RESTAdapter documentation says:
Comments for a post can be loaded by post.get('comments'). The REST
adapter will send a GET request to /comments?ids[]=1&ids[]=2&ids[]=3.
It will generate similar urls if you use something like App.Post.find({title: "Some Title"}), in about the format you'd expect: /posts?title=Some+Title
Is there some option, or gem I can use to handle that sort of simple query, or do I have to go parse parameters in my controllers manually?
To clarify, I'm aware that I can tell my Rails controller to return a set like:
#comments = Comment.find(params[:ids])
respond_with(#comments)
But it seems like querying on ids or accessible attributes like that would be a common enough use case for REST APIs that something would be built in, or have a gem written to handle it.
Can anyone point me in the right direction?
Thanks.

This might be helpful in your case:
https://github.com/ernie/ransack/
Or
https://github.com/ernie/squeel

Related

ACRCloud webapi in Rails

I'm a newb hobbyist developer. Can I just throw this repo of their ACRCloud's ruby example code into a controller? I'd like to use an audio fingerprinting song recognition database as a name validation for songs users are uploading using paperclip. Not sure if it's possible, just starting to research it, any hints or suggestions would be appreciated.
Obviously I'd have to replace
file_name = ARGV[0]
etc, but I'm also wondering about the require 'openssl' etc
Definitely! But there are few points to be taken care of. That's a pure ruby script, when it comes to rails there are certain rules/best practices. One of which is thin controller and fat model..
You need to create a route/action in your app which will ask the app to execute this request with required params.
Write a method in your model which contains the code and call it from controller and pass the permitted params to it.
Instead of hardcoding your credentials in the model, make them environment variables.
Would suggest using Httparty gem wgich will reduce many lines of your code and you just need to pass headers, params, etc. as hash in the arguments.
Last, but not the least...if you notice..there's a puts in the end however, rails uses mvc and so you need to have a view for the controller action you created in step1. Return and save the response.body in the class variable like #response = res.body and you can play with the body depending on the response type.
Hope it helps..
P.S. I wish I could write few lines of code/optimise it for you but i m using my mobile right now. But I think this much information should be enough to convert that script to mvc rails structure..

Shopify API calls not working in Rails background job

In my Rails controller action, I have a method that does a bunch of Shopify API calls. Things like:
ShopifyAPI::Product.all()
ShopifyAPI::Product.find(:all, params: {title: title})
ShopifyAPI::Product.create(title: title, body_html: description, images: images, tags: tags, product_type: product_type)
All of it does what I want...very neat.
The problem is that I'm going to be uploading a CSV and using this controller method. It's fine if I have like 8 line items, but very quickly it gets slow. So, I thought, let's move it to a background worker.
I'm using Redis/Resque to get everything going and using some dummy outputs (i.e. puts 'Hi there champ!') I've confirmed that the background worker is configured properly and executing when and where it should be. Neat.
So then I put bits and pieces of my controller action in and output that. That all works until I hit my Shopify API calls. I can call .new on about any object, but the when I try to .find, .all, or .create any valid object (which worked before I abstracted it to the background job), it sort of goes dead. Super descriptive! I've tried to output what's going on via logger and puts but I can't seem to generate much output of what's going on, but I have isolated it down to the Shopify API work. I thought that, even though I have an initializer that specifies my passwords, site, API keys, secrets, etc, I might need to reinitialize my Shopify session, as per their setup docs here. I either did it wrong, or that did solve the issue.
At this point I'm sure I'm just missing something in the docs, but I cannot find out how to make these necessary API calls from my background job. Any thoughts on what I might be doing obviously wrong that could solve this? Anyone dealt with anything similar?
Turns out this has to do with where the Shopify Engine was mounted. In my routes.rb I have the following (in addition to other routes; these are the two pertinent ones):
mount ShopifyApp::Engine, at: '/'
root to: 'products#index'
This is all fine and good, but sort of forces the context of your Shopify API calls to be made within the context of the products.rb index controller action...without some changes. 2 ways to do this, one obviously the more Railsy way to do it:
Option 1:
Include
session = ShopifyApp::SessionRepository.retrieve(1)
ShopifyAPI::Base.activate_session(session)
at the beginning of any file in which you want to make Shopify API calls. This sets the session (assuming you only have 1 store, by the way...this is using the retrieve method to retrieve store 1. Risky assumption), authenticate to the API, and everything in life is good.
Option 2:
Class inheritance for the win. Have all your controllers that are making API calls inherit from ShopifyApp::AuthenticatedController. This makes the initializer actually work, and that's it. This is (in retrospect) the clear and obvious way to go. Have an order controller? class OrdersController < ShopifyApp::AuthenticatedController and done: order = ShopifyAPI::Order.find(params[:id]) does exactly what you'd expect it to.

How to connect Rails collection route to Ember JSON API Adapter?

I have a Rails resource like this...
resources :listings do
collection do
get :stats
end
...
end
such that GETting /listings/stats?various_params gives me a JSON API compliant response with statistics about the Listing model according to the parameters I provide.
In my Ember frontend, also using the JSON API Adapter, I would like to be able to something like this:
model() {
return this.store.query('listing/stats', {startdate: startDate.toISOString, otherparams: etCetera});
}
What's the "Ember Way" to accomplish this, if any? I would like to avoid hacking the JSON API Adapter as much as possible, and it's my understanding that custom methods defined on an Ember model's file are mostly for interacting with a specific record (i.e., /listings/:id/whatever)
Thanks
I ended up using Mike North's ember-api-actions add on, which is working pretty well. If anyone has a short solution though, it would be welcome.

Friendly URLs in Github

How has Github managed to get friendly URLs for representing repos of users? For a project called abc by username foo, how do they work around with a URL like: http://github.com/foo/abc. Are they fetching the abc model for the DB from the title in the URL (which sounds unreasonable as they are modifying the titles). How are they transferring the unique ID of the abc repo which they can fetch and show in the view?
The reason I ask is that I am facing a similar problem of creating friendlier URLs to view a resource. MongoDB's object IDs are quite long and make the URL look horrific. Is there a workaround? All the tutorials that demonstrate CRUD (or REST) URLs for a resource always include the object's unique ID(e.g. http://mysite.org/post/1 or http://mysite.org/post/1/edit. Is there a better way to do it?
Not having seen their code, I couldn't tell you exactly how they do it, but if you're using Rails there are at least two Ruby gems that will give you similar results:
Take a look at Slugged and friendly_id
http://github.com/foo/abc is a unique repository identifier (for that repo's master branch). I'd assume that somewhere they have a table that looks like:
repository-id | user-id | project-id
and are just looking up based on user and project rather than repository-id.
You'd need to do some domain-specific mapping between internal and user-friendly ids, but you'd need to make sure that was a 1:1 mapping.
See this rails cast on methods, gems and solutions to common problems you might get while modifying the application to use friendly urls.
http://railscasts.com/episodes/314-pretty-urls-with-friendlyid?view=asciicast
(although Ryan Bates deserves the rep+ for this)
I mocked a structure like this using FriendlyID and Nested Resources.
Essentially, use friendly ID to get the to_param-ish slugs in your routes, then set up nested resources. Using GitHub as an example:
routes.rb
resources :users do
resources :repositories
end
Then in your controller, say, for repositories, you can check the existence of params[:user_id] and use that to determine the user from the route. The reason I check for existence is because I did something like (roughly):
/myrepositories/:repository_id
/:user_id/:repository_id
So my controller does:
def show
#user = params[:user_id] ? User.find(params[:user_id]) : current_user
end
I followed this tutorial here to get started with this same project.
This is called URL rewriting if the web server does it (such as Apache), and routing when it happens in a web application framework (such as Ruby on Rails).
http://www.sinatrarb.com/intro#Routes
http://httpd.apache.org/docs/current/mod/mod_rewrite.html

Tag chaining in Rails URLs

I want to implement tags in my Rails application but I'm having trouble with one specific feature of that implementation. You see I want to make it possible for users to specify multiple tags in the url scheme, something like http://domain/tags/:id1/:id2/.... Has anyone implemented something like this in Rails or know how to do it?
You want something called "Route Globbing":
match 'tags/*tag_ids' => 'tags#lots_of_tags'
Then in lots_of_tags action you'd have params[:tag_ids] array of provided tag ids or a string in form of id1/id2 (not sure which one, you should test it by yourself).
More info on this in rails guides:

Resources