How to paginate over Stripe API results? - javascript

Issue: I want to find a way to paginate over Stripe API results past a certain number. The issue is, as time goes on and more API documentation appears, a page will be loaded with way too much data. Preferably I would like to have a months worth of data per page.
Question: How can I limit to results on the views side and create pagination for it.
For example, I have this in my controller:
#payouts = Stripe::Payout.list(
{
limit: 100,
expand: ['data.destination']
},
{ stripe_account: current_user.stripe_token }
)
Views:
#table html stuffs
...
<% #payouts.each do |payout| %>
<tr>
<td><%= number_to_currency(as_table_row_payout(payout["amount"] / 100.00 )) %></td>
<td><%= as_table_row_payout(Time.at(payout["arrival_date"]).strftime('%m/%d/%Y')) %></td>
</tr>
<% end %>
...
I have the will_paginate gem but that didn't seem to work. So I figured there may be a way with jquery / JS to solve this. Does anyone have a solution to limit the amount of API JSON data that is requested on the view page?
Somewhat of an update and a bit off topic... (sorry if this strays from the post itself and starts a new conversation)
I have found a gem for will_paginate to paginate through API requests
I have found the api-pagination gem here: https://github.com/davidcelis/api-pagination
Although, when i installed the gem and followed the directions, nothing seemed to happen - I manually created an api_pagination.rb config file and did what it seems like the docs say to do as well... Anyone use this before?

The Stripe API uses cursors for pagination rather than just specifying a page and a page size (which is what will_paginate and kaminari do).
If you look at the api docs for listing payouts the arguments you'll need to use are ending_before and starting_after.
If you retrieve 10 payouts with ids [1, 2, ..., 10] and you want the next "page" of results you'll need to make the request again with starting_after=10. I.e. from the payout with id=10 get me the next 10 payouts.
I'm not aware of any gem support for this (although that definitely doesn't mean that there isn't any!) and I've tended to roll my own by generating "Next" and "Previous" links to set starting_after the id of the last payout in my current page or ending_before the id of the first payout in my current page. E.g.
<%= link_to 'Previous', list_payouts_url(first_payout_id: #payouts.first.id) %>
<%= link_to 'Next', list_payouts_url(last_payout_id: #payouts.last.id) %>
and then setting the ending_before or starting_after to params[:first_payout_id] and params[:last_payout_id].

Related

Why am I not able to execute AJAX through rails while going through controller index action?

This is my first time trying AJAX request on Ruby on Rails. I followed the RoR guide to come up with this script. My code is as follows.
course_controller
def index
#course = Course.all
respond_to do |format|
format.html{}
format.js {}
end
end
views/courses/index.js.erb
$('#dummy_div').hide();
views/courses/trial.html.erb (view from where I am calling the AJAX / index controller)
<body>
<%= form_for(Course.new, :method => :get, remote: true) do |f| %>
<%= submit_tag "Search", :name => 'course_list' %>
<%end%>
<div id = "dummy_div" style = "width:100px; height: 100px;background-color:black;"></div>
</body>
My expected result is that the div should disappear once I have submitted the Search function. However, this does not happen. I have not put in embedded ruby because I am just testing whether plain JS works in the first place. My intention is to put in erb later (just to be clear that I am testing this for AJAX). Why does the JS in the index.js.erb file not get executed?
Additionally, how do I debug AJAX requests in Ruby on Rails?
What I have done above was absolutely correct and should be the correct way to route to the js file. This was actually an issue with initializing the model object course and had nothing to do with the code above (I had a small typo mismatch with the model name - Course).
A better way to test the ajax than making the div disappear is using the console.log("i'm at: views/courses/index.js.erb"); or alert("i'm at: views/courses/index.js.erb"); as mentioned by John in the comment above.

star rating rails 4 jquery ajax javascript raty

I am attempting to follow this tutorial and I am getting stuck: Adding a 5 star ratings feature to a Rails 4 model.
Im a begginer with javascript and ajax so I spent a few hours learning how ajax works with javascript. I believe the problem has to do with where the average_rating method is (rails problem?).
def average_rating
ratings.sum(:score) / ratings.size
end
Currently I have followed the tutorial exactly how it says, while replacing comment with review. In the tutorial it says to define the average_rating in the comment model (mine is in the review model), and I am not sure why I would do that.
Also I have added this (not sure if It belongs in the current controller or if it belongs in rating controller):
#this is the controller used for the view which displays the stars
def page
#rating = Rating.where(review_id: #review.id, user_id: #current_user.id).first
unless #rating
#rating = Rating.create(review_id: #review.id, user_id: #current_user.id, score: 0)
end
end
When I try to load the page here is the error I get: ZeroDivisionError below it says divided by 0 and it highlights this line score: <%= #review.average_rating %>,
UPDATE When I delete this script from the view which has the average_rating, the stars show for my_rating. So something is messing up with the average part:
<script> #did not delete this line
$('#star').raty({
readOnly: true,
score: <%= #review.average_rating %>,
path: '/assets'
});
Deleted part^^^
Basically, i would love to get more info, but here are some pointers that might help:
make sure the relation is working: make sure you have has_many :ratings for the user/review and 'belongs_to :user/:review' for the ratings. other direction- are you getting the ratings in a controller method? if so, consider changing it to #ratings.
use first_or_XXXX - this is a great rails option to save conditional instantiation. there is first_or_create that would do exactly what you did:
Rating.where(review_id: #review.id, user_id: #current_user.id).first_or_create do |rating|
rating.score = 0
end
finally, ratings.size, will not update after create, which might explain the zero devision. read more in this question's selected answer and comments. Therefore, it's recommended to use count (will check on the db, so only saved ratings will be counted) or length (i.e. user/review.ratings.length which will count also built (not saved) objects.
hope that helps.

Rendering partial with AJAX link_to in Rails

After completing Hartl's tutorial I'm trying to implement #replies for the Micropost model.
I wanted the reply button on a micropost to render the micropost form right there under said post a la twitter. I also wanted to pass the :micropost_id of said post to the reply so that I could later reference which post it was a reply to, again a la twitter.
I've been trying to implement some of that based on the answer to this question.
My microposts controller has
def reply_form
respond_to do |format|
format.js
end
end
The link in the view is
<%= link_to 'reply', 'shared/reply_form', remote: true, locals: { object: :id } %>
With my attempt there to pass on the micropost :id
After a post I have this for the partial to be rendered in:
<div id="ReplyContainer"></div>
I then have _reply_form.js.erb
$('#ReplyContainer').html('<%=j render partial: 'shared/reply_form', locals: { object: :id } %>')
It's not throwing errors but clicking the 'reply' link has no effect and does not render the _reply_form.html.erb partial.
My ultimate goal is you click reply, that renders the micropost form, with #username at the start of the message (derived from the micropost_id?) submitting that form then saves the new micropost including the micro post_id of the original post in the reply_to column that I've created in my microposts table. Any nudges in the right direction much appreciated. Don't want to be barking up the completely wrong tree. Thanks.
EDIT: I'm currently getting a routing error when clicking the reply link.
(No route matches [GET] "/shared/reply_form")
But as far as I can see everything is in the right place.
Ok, sorry, I've just read better your question and the problem is related to the wrong structure.
you have a controller with an action that will render the post
your post page will be composed by the "post" and many replies
each reply I guess is made of a partial (let's say a _reply.html.erb file).
The structure of the page will be then the following:
<div>
... my post here...
</div>
<div id='repliesContainer'>
<%- #replies..each do |id| -%>
<%= render :partial => "shared/reply", :locals => { :object => id} %>
<%- end -%>
</div>
And we call it post.html.erb.
This is will be your shared/_reply.html.erb file:
// note here that the id of the div contains the ID of the reply: each ID must be unique in the page....
<div id='ReplyContainer-#{object}'>
...reply content here...
</div>
Now, your post.js.erb file contains the following:
$('#repliesContainer').append("<%= escape_javascript( render :partial => 'shared/reply', :locals => { :object => id}) -%>");
The content of the append() function will be rendered on the server as a string from the partial.
You have several problems here:
As you discovered, the route to your reply form is incorrect. Until you get this fixed, you won't be able to debug the rest of the system. Run rake routes | grep reply_form to find the URL for it (it won't be under /shared most likely), then see what the response is for that URL. I bet it throws an error (see #2).
Your reply form file has the wrong name: _reply_form.js.erb is a partial but it needs to be 'reply_form.js.erb'. If you hit the correct route for that controller, you'll get a 'Missing Template' error because it is looking for a normal template, not a partial.
Finally, the reply_form.js.erb code needs to point to the shared reply_form partial, so if is really in shared/_reply_form.html.erb then the JS response should be rendered correctly.
Having said that...I really dislike sending Javascript back to the browser, in part because it makes debugging JS much harder - how are you going to find the returned code in your browser debugger? There may be some use cases for this type of design but they are probably very rare.
The better / more idomatic solution is to send JSON data (eg. the rendered text) back to the browser and have some handler parse the JSON and update the DOM. This way all of your JS code is present in the browser and all you are receiving is data. This will be much easier to debug.

Backbone: Pre-fetching collections

I have a backbone application which, upon load, needs to fetch data from four different collections (Rails-->JSON back end).
That's four hits to the server, and I'm guessing there's a better way.
I started out by trying to pass Rails to_json() of the query results into the router initialization in the Rails view such as:
<script type="text/javascript">
$(function() {
window.router = new Backbonedemo.Routers.CalendarsRouter({calendars: [], tasks: <%= #tasks %>});
Backbone.history.start();
});
</script>
but that brought no joy.
So, what's the correct way to run the equivalent of fetch() at startup, without having to hit JSON for each collection I want to collect?
Check out the rabl gem. It allows you to customize your json response to a much greater degree than regular to_json will allow.
Here's a basic way to set up a project where you need to deliver a load of JSON up front:
First, set up your controller to pull data on page load, for examlpe localhost:3000/home would look in the home controller index:
class HomeController < ApplicationController
def index
#user = current_user
render 'user.json' # this line is not actually required most of the time when using backbone and proper ajax/json requests
end
end
Next, set up a rabl template, this takes the place of a view or a partial, and returns JSON to your client. I'm actually going to use a partial, to make loading into the home/index.html view nice and easy:
# views/home/_user.json.rabl
object #user
attributes :id, :first_name, :last_name, :birthdate, :gender, :nickname, :email
node(:avatar_thumb_url) { |u| u.avatar.url :thumb }
node(:roles) { |u| u.roles }
node(:name) { |u| "#{u.first_name} #{u.last_name}".strip }
node(:errors) { |u| u.errors.to_hash if u.errors.present? }
child :awesome_calendars => :calendars do
attributes :id, :date, :description
child :events do
attributes :title, :description
end
end
That's some relatively fancy rabl that will deliver a bunch of json, including a related set of records, all in one JSON object.
In your html view that loads up backbone, you need to pass the controller's object to the partial:
# views/home/index.html.erb
<script type='text/javascript'>
$(function() {
window.router = new Backbonedemo.Routers.CalendarsRouter(<%= render('user.json.rabl', user: #user).html_safe -%>);
Backbone.history.start();
});
</script>
To recap:
controller renders regular html.erb view (the one that starts up backbone)
that view also renders a partial--this partial is a rabl template that returns strictly JSON
backbone takes that JSON and does whatever you want with it.
The beauty of this is that you can set up json.rabl responses for any of your controller actions and have them return a variety of json stuff, all easily controllable. The thing I did above is the "difficult" part where you want to load up stuff from many tables into a single JSON call on your first page load--avoiding multiple AJAX/backbone fetch requests.
Make sense? I hope so... : / let me know if anything is unclear.
I don't know Rails, but see the "bootstrap" example in the Backbone docs:
<script>
Accounts.reset(<%= #accounts.to_json %>);
Projects.reset(<%= #projects.to_json(:collaborators => true) %>);
</script>
Generally, I think you need to create the collection objects, then reset() them with inline JSON data.

How to implement a 'safe' periodical executer without using the Rails helpers?

I am very new to Ruby on Rails and was never really big on writing JavaScript, so the built in helpers were like a tiny silce of heaven.
However I have recently learned that using the helper methods creates "obtrusive javascript" so I am doing a tiny bit of refactoring to get all this messy code out of my view. I'm also using the Prototype API to figure out what all these functions do.
Right now, I have:
<%= periodically_call_remote(:url => {:action => "tablerefresh", :id => 1 }, :frequency => '5', :complete => "load('26', 'table1', request.responseText)")%>
Which produces:
<script type="text/javascript">
//<![CDATA[
new PeriodicalExecuter(function() {new Ajax.Request('/qrpsdrail/grids/tablerefresh/1', {asynchronous:true, evalScripts:true, onComplete:function(request){load('26', 'table1', request.responseText)}, parameters:'authenticity_token=' + encodeURIComponent('dfG7wWyVYEpelfdZvBWk7MlhzZoK7VvtT/HDi3w7gPM=')})}, 5)
//]]>
</script>
My concern is that the "encodeURIComponent" and the presence of "authenticity_token" are generated by Rails. I'm assuming these are used to assure the validity of a request. (Ensuring a request comes from a currently active session?)
If that is the case, how can I implement this in application.js 'safely'? It seems that the built in method, although obtrusive, does add some beneficial security.
Thanks, in advance, to all who answer.
Rails generates an authentication token to protect against XSS attacks. See: ActionController::RequestForgeryProtection You can turn it off but, you're right that it's much safer to use it.
The easiest workaround that comes to mind would be to just put the authentication token somewhere at the top of your page:
<% javascript_tag do %>
<%= "var AUTH_TOKEN=encodeURIComponent(#{form_authenticity_token.inspect});" %>
<% end %>
It's obtrusive but, at least then you could use the AUTH_TOKEN variable freely in your application.js file.

Categories