Problems using controller on postgres DB on AWS RDS from Heroku app - ruby-on-rails

I've setup a postgres DB to use postgis for a Heroku App I have, running on Ruby on Rails.
My steps have been:
Create RDS DB running pg 9.4.9
Enable rds.force_ssl on RDS Parameter Group.
Backup and load my Heroku database into new postgres DB.
Download Amazon RDS CA Certificate and place it under config/amazon-rds-ca-cert.pem.
Add gem 'activerecord-postgis-adapter' to my gem file.
Update database.yml file to the below:
:
default: &default
adapter: postgis
encoding: unicode
pool: 5
production:
<<: *default
encoding: utf8
database: <%= ENV['RDS_DB_NAME'] %>
username: <%= ENV['RDS_USERNAME'] %>
password: <%= ENV['RDS_PASSWORD'] %>
host: <%= ENV['RDS_HOSTNAME'] %>
port: <%= ENV['RDS_PORT'] %>
postgis_extension: postgis
schema_search_path: public,postgis
Update DATABASE_URL parameter on Heroku to postgres://myuser:mypassword#mydbinstance.xxxxxxxxxxx.us-west-2.rds.amazonaws.com/mydbname?sslmode=verify-full&sslrootcert=config/amazon-rds-ca-cert.pem
Additional steps in this very helpful question: Enabling Ruby PostGIS support on Heroku
Push updated code and access my App.
When I try to access the database to verify connectivity it works ok:
nc -zv mydbinstance.xxxxxxxx.us-west-2.rds.amazonaws.com 5432
Connection to mydbinstance.xxxxxxxxx.us-west-2.rds.amazonaws.com 5432 port [tcp/postgresql] succeeded!
and when I navigate on the app I am able to see the results of queries. However, when I try to use a model that uses postgis, somehow my connections don't work correctly. Here's my Controller's code, which stores lat, lng pairs with bus stop information, and finds the ones close to a point given in parameters:
class TransitStopsController < ApplicationController
def create
end
def show
#transit_stop = TransitStop.find(params[:id])
#transit_routes = #transit_stop.transit_routes
end
def get_nearby_stops
radius_in_meters = params[:radius_in_meters].nil? ? 3219 : params[:radius_in_meters]
#nearby_stops = TransitStop.close_to(params[:lat], params[:lng], radius_in_meters)
end
end
My Model:
class TransitStop < ActiveRecord::Base
has_many :transit_stops_transit_routes, foreign_key: "onestop_id", class_name: "TransitStopsTransitRoute"
has_many :transit_routes, through: :transit_stops_transit_routes, foreign_key: "route_onestop_id", class_name: "TransitRoute"
validates_uniqueness_of :onestop_id
#Get transit stops close to a given lat, lng pair. Default distance = 2 miles
scope :close_to, -> (lat, lng, distance_in_meters = 3219) {
where(%{
ST_DWithin(
ST_GeographyFromText(
'SRID=4326;POINT(' || transit_stops.lng || ' ' || transit_stops.lat || ')'
),
ST_GeographyFromText('SRID=4326;POINT(%f %f)'),
%d
)
} % [lng, lat, distance_in_meters])
}
end
and my View (get_nearby_stops.jbuilder):
json.nearby_stops #nearby_stops do |transit_stop|
json.region_id transit_stop.region_id
json.lat transit_stop.lat
json.lng transit_stop.lng
json.onestop_id transit_stop.onestop_id
json.name transit_stop.name
json.osm_way_id transit_stop.osm_way_id
json.osm_way_id transit_stop.served_by_vehicle_types
json.timezone transit_stop.timezone
json.wheelchair_boarding transit_stop.wheelchair_boarding
json.created_or_updated_in_changeset_id transit_stop.created_or_updated_in_changeset_id
json.transit_routes transit_stop.transit_routes
end
Routes.rb has line added to access method:
get 'transit_stops/get_nearby_stops' => 'transit_stops#get_nearby_stops'
When I try to access this via: https://myherokuapp.herokuapp.com/transit_stops/get_nearby_stops.json?lat=-122.49766&lng=37.71677
All I get is a message:
Application Error
An error occurred in the application and your page could not be served. If you are the application owner, check your logs for details.
When I look at my heroku logs all I see is a timeout error:
app[web.1]: Processing by TransitStopsController#get_nearby_stops as JSON
app[web.1]: Parameters: {"lat"=>"-122.49766", "lng"=>"37.71677"}
heroku[router]: at=error code=H12 desc="Request timeout" method=GET path="/transit_stops/get_nearby_stops.json?lat=-122.49766&lng=37.71677" host=myherokuapp.herokuapp.com request_id=1e081fdf-d0ce-4000-a6b4-4e75c176b8a2 fwd="10.0.0.1" dyno=web.1 connect=0ms service=30001ms status=503 bytes=0
The AWS Error Logs show nothing.
The strange thing to me is that I am able to perform the same query by connecting to Heroku's rails console:
irb(main):001:0> TransitStop.close_to(-122.49766,37.71677,5000)
=> #<ActiveRecord::Relation [#<TransitStop region_id: 1, lat: #<BigDecimal:7fe69f6c95c0,'-0.122504106E3',18(18)>...
...
etc
So at this point I don't understand what's causing this controller to fail only when I access it through my view, but not through console? Should the database url be different if I use postgis methods?
Any help would be highly appreciated.
EDIT: I've tested the show method of my controller, and it works ok:
app<a class="jive-link-external" href="http://web.1">http://web.1</a>: Started GET "/transit_stops/s-9q8ys6puje-655johnmuirave.json" for 159.16.243.2 at 2016-11-12 19:55:16 +0000
app<a class="jive-link-external" href="http://web.1">http://web.1</a>: Processing by TransitStopsController#show as JSON
app<a class="jive-link-external" href="http://web.1">http://web.1</a>: Parameters: {"id"=>"s-9q8ys6puje-655johnmuirave"}
herokurouter: at=info method=GET path="/transit_stops/s-9q8ys6puje-655johnmuirave.json" host=myapp.herokuapp.com request_id=15814367-5235-484b-bff9-7727a2349dd0 fwd="10.0.0.1" dyno=web.1 connect=0ms service=329ms status=200 bytes=1385
app<a class="jive-link-external" href="http://web.1">http://web.1</a>: Rendered transit_stops/show.json.jbuilder (107.3ms)
app<a class="jive-link-external" href="http://web.1">http://web.1</a>: Completed 200 OK in 217ms (Views: 6.7ms | ActiveRecord: 207.4ms)<br class="jive-newline" />
Which to me translates to perhaps there being some problem in the database to perform the query I'm doing? The query itself should be fast, as when I test it in console I always get a response almost immediately, but perhaps something about the configuration of the database needs to be changed?

Just for other people to see, my problem was that after the query, my view was also producing several additional queries, because the field
transit_stop.transit_routes
is a relationship to a different table. Thus, for every resulting stop the database was performing many other queries for every result I got. Since my query was returning several hundred results, the final view performed several hundred additional queries which caused a lot of overhead to my db.
To detect this I updated log_statement = all to my db parameter group, so that I could see all activity coming into the database. I've updated my query to make it more efficient by reducing the number of results to only the n nearest ones, with a maximum of 10, as I don't really have any use on getting so many results.

Related

Post request from external website to Rails App is not routed through

I am trying to send data from an external website to a Rails app but the post request is not routed through correctly.
The Rails app has the route
post '/submit_text/' => 'activities#submitText', as: :submitText
The code of the corresponding controller action is
before_filter :submitText
protect_from_forgery :except => :submitText
def submitText
puts "in submitText"
puts params[:text]
puts "end of submitText "
end
I am trying to send data from an external website to the Rails app like this
<form action="https://todo-list-study.herokuapp.com/submit_text/" method= "post">
<textarea name="response[text]" rows="25" cols="75" id="answer_text">
</textarea>
<input type="submit" name="Submit" value="test" onclick="recordAnswer()">
</form>
When I submit data from the external website, the Rails app receives it but it does not pass it on to the specified controller action. Here is what happens according to the Heroku log file:
heroku[router]: at=info method=POST path="/submit_text/" host=todo-list-study.herokuapp.com request_id=fee72511-ad1e-41c3-ae4c-d4b3395e6afd fwd="24.7.71.184" dyno=web.1 connect=1ms service=19ms status=500 bytes=1754 protocol=https
Unfortunately, that is all that happens. Given that the put statement at the beginning of the method is not executed I conclude that it is not being called. This happens even though both the Rails app and the external website run on the HTTPS protocol.
What can I do to fix this?
The router is finding an action for that call, otherwise it would have responded with a 404 instead of a 500, which indicates that there's an internal error.
Assuming that you're not trying to send back a response with content back to the client, try adding a call to render so that your controller sends back a response instead of trying to find a view template to render, which is where I'm guessing the issue is.
For example, try updating your code to:
def submitText
puts "in submitText"
puts params[:text]
puts "end of submitText "
render nothing: true
end

Getting rails error when using Spaceship::Tunes

In a rails app I am running:
54 def itunes_all_apps
55 begin
56 Spaceship::Tunes.login(params[:itunes_username], params[:itunes_password])
57 apps = Spaceship::Tunes::Application.all
58 render json: apps.to_json, status: 200
59 rescue => e
60 render json: {error: e}.to_json, status: 500
61 end
62 end
It returns a status 500 error with no other information every time.
However, if I change this around slightly, for example getting teams (note, from Spaceship, not Spaceship::Tunes) this works fine:
def itunes_all_apps
begin
spaceship = Spaceship.login(params[:itunes_username], params[:itunes_password])
teams = spaceship.teams
render json: teams.to_json, status: 200
rescue => e
render json: {error: e}.to_json, status: 500
end
end
I'm not using any fast file or or config or anything. Just passing in a username and password via an api call and trying to get a response back. I'm new to rails so it may be my implementation of the Spaceship examples provided.
Using spaceship 0.36.1 gem (the latest)
I've pored through the docs to no avail. Grasping for any leads on what I'm doing wrong.
http://www.rubydoc.info/gems/spaceship/Spaceship/Tunes
https://github.com/fastlane/fastlane/blob/master/spaceship/docs/iTunesConnect.md
Someone suggested I run these two commands in irb, which I did, and they worked perfect!
Spaceship::Tunes.login('myAppleId', 'myPassword')
Spaceship::Tunes::Application.all
So it's not an iTunes account problem or credentials problem (because it works in irb), routes problem (because I ran both rails methods above with same route), or params problem (because I ran both rails methods above with same param names).
I really appreciate any suggestions. Thanks.
Edit:
Commenting out begin, rescue, and rending the error, the stack trace is as follows:
2016-10-24T17:47:34.974650+00:00 app[web.1]: Started POST "/api/v1/users/13/itunes_all_apps" for 162.237.102.13 at 2016-10-24 17:47:34 +0000
2016-10-24T17:47:34.977478+00:00 app[web.1]: Processing by Api::V1::UsersController#itunes_all_apps as JSON
2016-10-24T17:47:34.977521+00:00 app[web.1]: Parameters: {"itunes_username"=>"myCorrectUsername", "itunes_password"=>"[FILTERED]", "team_id"=>"myCorrectTeamId", "id"=>"13", "user"=>{}}
2016-10-24T17:47:35.629629+00:00 heroku[router]: at=info method=POST path="/api/v1/users/13/itunes_all_apps" host=myHerokuApp.herokuapp.com request_id=002d906d-354e-4633-8b54-71aa5181e3a7 fwd="161.237.102.13" dyno=web.1 connect=2ms service=657ms status=500 bytes=259
2016-10-24T17:47:35.619597+00:00 app[web.1]: Completed 500 Internal Server Error in 642ms (ActiveRecord: 0.0ms)
2016-10-24T17:47:35.620430+00:00 app[web.1]:
2016-10-24T17:47:35.620432+00:00 app[web.1]: IOError (not opened for reading):
2016-10-24T17:47:35.620434+00:00 app[web.1]:
2016-10-24T17:47:35.620433+00:00 app[web.1]: app/controllers/api/v1/users_controller.rb:58:in `itunes_all_apps'
It seems that Spaceship::Fastlane::Application does not implement as_json method and the default as_json touches some IO object, which cannot be represented as json.
My suggestion would be to create JSON serializer. You could use active_model-serializer, but if you do not want to create a dependency just for one object, then you can create your own serializer.
class SpaceshipApplicationSerializer
attr_reader :spaceship_applications
def initialize(spaceship_applications)
#spaceship_applications = spaceship_applications
end
def as_json(options = {})
spaceship_applications.each_with_object([]) do |spaceship_application, memo|
memo << object_as_json(spaceship_application)
end
end
def object_as_json(object)
attributes.each_with_object({}) do |attribute, memo|
memo[attribute] = object.send(attribute)
end
end
def attributes
[
:apple_id,
:name,
:vendor_id,
:bundle_id,
:last_modified,
:issues_count,
:app_icon_preview_url
]
end
end
# In your controller
def itunes_all_apps
begin
Spaceship::Tunes.login(params[:itunes_username], params[:itunes_password])
apps = Spaceship::Tunes::Application.all
render json: SpaceshipApplicationSerializer.new(apps).to_json, status: 200
rescue => e
render json: {error: e}.to_json, status: 500
end
end
EDIT:
Yes, the classes return an array, but the actual objects in array don't play nicely with json. It's hard to say if the problem is with the library - on one hand Spaceship::Tunes::Application not returning a proper json representation is a missing feature, but if the to_json raises an exception (a method the class responds to) - then I would say that is a bug.
Creating your own serializer to build json representation the way you want it - is a common pattern.

Modify Rails controller to work with Postgres/Heroku

I'm working my way through the railstutorial whilst working on my own mini project. Whilst it has been suggested that the development database you use should be the same as the one in production, the guide uses sqlite for development
and I've been doing the same.
I've deployed some changes recently, that work locally, to my app hosted on Heroku however, when trying to access a specific page, I receive the following error:
If you are the application owner check the logs for more information.
How can I access the logs that are mentioned?
I'm guessing a possible cause is due to the code in my controller that returns data from the db, and works in sqlite but is possibly invalid for postgres. Can someone please suggestion improvements for the controller.
I've attached my code below.
accounts_controller.rb:
# GET /accounts/1/history
def history
#account = Account.find(params[:id])
#accountHistory = Account.select("accounts.*, balances.*").joins("JOIN balances").where('balances.account_id = :accountId', {accountId: #account.id}).where('accounts.id = :accountId', {accountId: #account.id}).order('date desc')
end
history.html.erb
<tbody>
<% #accountHistory.each do |a| %>
<tr>
<td><%= date_format(a.date) %></td>
<td class='account-balance'><%= number_to_currency(a.balance, unit: "£") %></td>
</tr>
<% end %>
</tbody>
UPDATE:
Looking at the Heroku logs, it looks like there's a syntax error for Postgres. Can anyone suggest how to improve it?
heroku logs:
2015-12-22T16:54:39.361012+00:00 app[web.1]: Started GET "/accounts/3/history" for 2.220.200.172 at 2015-12-22 16:54:39 +0000
2015-12-22T16:54:39.370975+00:00 app[web.1]: Account Load (0.9ms) SELECT accounts.*, balances.* FROM "accounts" JOIN balances WHERE (balances.account_id = 3) AND (accounts.id = 3) ORDER BY date desc
2015-12-22T16:54:39.371012+00:00 app[web.1]: LINE 1: ...ounts.*, balances.* FROM "accounts" JOIN balances WHERE (bal...
2015-12-22T16:54:39.371010+00:00 app[web.1]: PG::SyntaxError: ERROR: syntax error at or near "WHERE"
2015-12-22T16:54:39.371013+00:00 app[web.1]: ^
2015-12-22T16:54:39.371015+00:00 app[web.1]: : SELECT accounts.*, balances.* FROM "accounts" JOIN balances WHERE (balances.account_id = 3) AND (accounts.id = 3) ORDER BY date desc
2015-12-22T16:54:39.371797+00:00 app[web.1]: Rendered accounts/history.html.erb within layouts/application (2.3ms)
2015-12-22T16:54:39.371929+00:00 app[web.1]: Completed 500 Internal Server Error in 6ms (ActiveRecord: 1.6ms)
2015-12-22T16:54:39.374155+00:00 app[web.1]:
2015-12-22T16:54:39.374158+00:00 app[web.1]: ActionView::Template::Error (PG::SyntaxError: ERROR: syntax error at or near "WHERE"
Looks like the Heroku error is related to the joins statement. It needs the on, which you can do a couple ways. To do this in an active relation, just change the joins statement from
.joins("JOIN balances")
To
.joins(:balances)
Note - this part may not be needed anymore
.where('balances.account_id = :accountId', {accountId: #account.id})
Looking at your code a little further, there may be something else you are really after. If accountHistory is a list of balance records, this would work for you....
#account = Account.find(params[:id])
#accountHistory = #account.balances
Or, to potentially do in one query...
#account = Account.includes(:balances).find(params[:id])
The balances collection is referenced on account, I suspect
class Account < ActiveRecord::Base
has_many :balances
end
And, with the foreign key on Balance
class Balance < ActiveRecord::Base
belongs_to :account
# Add a scope if you like to reuse code
scope :order_by_date, -> { order(:date => :desc) }
end
You can then reference balances easily. This is where Rails helps you out a lot to make things very readable.
#account.balances.order_by_date
You can assign this to #accountHistory if you want, or just refer to balances from the collection off account in the view which might look like:
<tbody>
<% #account.balances.order(:date => :desc).each do |b| %>
<tr>
<td><%= date_format(b.date) %></td>
<td class='account-balance'><%= number_to_currency(b.balance, unit: "£") %></td>
</tr>
<% end %>
</tbody>
Did you run heroku run rake db:migrate -a <YOUR HEROKU APP NAME> after you deployed to heroku?
If you did, you can check the logs they are referring to with:
heroku logs --tail -a <YOUR HEROKU APP NAME>
Replace the <YOUR HEROKU APP NAME> with the name on your heroku configs. If you don't know how to find that, go to the heroku.com dashboard and find it under settings.

Can't verify(check) paypal account

I need to verify PayPal account, when user sign_up.
I have function(source - http://curry.byteally.com/finding-verification-status-of-a-paypal-account-ruby-on-rails-paypal-adaptive-accounts-getverifiedstatus/)
I entered my credentials and changed.
I put it i my static_pages_controller(for now).
def verify_paypal
...
//change:
if res.status == 200
#xml = XmlSimple.xml_in(res.content)
#check if the status node exists in the xml
if #xml['accountType']!=nil
account_type = #xml['accountType'][0]
if account_type.to_s() == "Business"
render :text => "Business account!"
elseif account_type.to_s() == "Premier"
render :text => "Premier Account!"
elseif account_type.to_s() == "Personal"
render :text => "Personal account!"
else
render :text => "Account type not null but not a valid PayPal account type."
end
end
Added line in my routes.rb
post "static_pages/verify_paypal"
In my views:
<%= link_to "verify", static_pages_verify_paypal_path, :method => :post %>
But it constantly gives me text:
"Gee! sorry! something went seriously wrong"
what mean, that my user isn't registered in PayPal(but it is!).
EDTED
From Heroku logs:
←[33m2012-07-15T17:22:56+00:00 app[web.1]:←[0m Started POST "/static_pages/verify_paypal" for 46.119.153.97 at 2012-07-15 17:22:56 +0000
←[33m2012-07-15T17:22:56+00:00 app[web.1]:←[0m Processing by StaticPagesController#verify_paypal as HTML
←[33m2012-07-15T17:22:56+00:00 app[web.1]:←[0m Parameters: {"authenticity_token"=>"xnW29ekJqp7qBNrvIZJjPSh05AMdiHWNQMvLZhevCig="}
←[36m2012-07-15T17:22:57+00:00 heroku[router]:←[0m POST sharp-cloud-3895.herokuapp.com/static_pages/verify_paypal dyno=web.1 queue=0 wait=0ms service=1058ms status=200 bytes=42
←[33m2012-07-15T17:22:57+00:00 app[web.1]:←[0m Rendered text template (0.0ms)
←[33m2012-07-15T17:22:57+00:00 app[web.1]:←[0m Completed 200 OK in 1046ms (Views: 6.7ms | ActiveRecord: 2.7ms)
First question to this line:
"emailAddress" => params[:paypal]
Can I change it into
current_user.email
Second question - Where is problem and what I'm doing wrong ?
The API call structure is sound.
However, when you say you entered your credentials, did you make sure that you are using the right credentials for the right environment?
Live credentials, and live accounts do not exist within the sandbox and viceversa. You can't check a live account's status against the checkbox because it simply does not exists in the sandbox "universe".
That would be the first thing to look at. If you feel your environments are correct, can you post the contents of res.content to see what came back from the HTTP call?
Check out the adaptiveaccounts-sdk-ruby gem

Rails Location based search not working on Heroku

Recently I deployed my application on Heroku. I'm using Geokit to search events, based on user's location.
#events = Event.all(:origin => [#location.lat, #location.lng], :within => 5, :conditions => ["end_date >= ?", Date.today], :select => "id, created_at, user_id, location, description, permalink, title", :order => "created_at DESC")
The above statement is working fine in my local system with mysql database.
But I'm getting error while executing same stmt on Heroku. Please check the below error I'm facing on Heroku.
ActiveRecord::StatementInvalid (PGError: ERROR: function radians(character varying) does not exist
2011-03-20T00:52:23-07:00 app[web.1]: LINE 2: ...,COS(0.303256183987648)*COS(1.36963671754269)*COS(RADIANS(fr...
2011-03-20T00:52:23-07:00 app[web.1]: ^
2011-03-20T00:52:23-07:00 app[web.1]: HINT: No function matches the given name and argument types. You might need to add explicit type casts.
Any help would be greatly appreciated.
Thanks,
Kalyan.
As a heads-up, Heroku uses Postgres as the only SQL database backend: http://devcenter.heroku.com/articles/database
Therefore, your problem is related to these two Q&A:
Why does Postgresql fail with Geokit like this?
Rails: Converting from MySQL to PostGres breaks Geokit Distance Calculations?
In your case, you should add a database migration and change "lat" and "lng" in your location model from "string" (or "text") to "float", and then Geokit should work fine with Postgres and Heroku respectively.

Resources