Modify Rails controller to work with Postgres/Heroku - ruby-on-rails

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.

Related

Problems using controller on postgres DB on AWS RDS from Heroku app

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.

Impossible to delete a flash

I made a mistake before migrating a plugin, and have written
flash[:notice] = :label_presta_added
instead of
flash[:notice] = l(:label_presta_added)
I corrected my mistake but it seems that my Redmine Plugin has trashed my Redmine. Even though I delete my plugin a migrate once again, I still get this error:
Started GET "/" for 127.0.0.1 at 2016-06-01 22:21:37 +0200
Processing by WelcomeController#index as HTML
Current user: admin (id=1)
Rendered welcome/index.html.erb within layouts/base (28.1ms)
Completed 500 Internal Server Error in 366ms (ActiveRecord: 116.0ms)
ActionView::Template::Error (undefined method `html_safe' for :label_presta_added:Symbol
Did you mean? html_safe?):
97: <div id="sidebar">
98: <%= yield :sidebar %>
99: <%= view_layouts_base_sidebar_hook_response %>
100: </div>
101:
102: <div id="content">
103: <%= render_flash_messages %>
app/helpers/application_helper.rb:312:in `block in render_flash_messages'
app/helpers/application_helper.rb:311:in `render_flash_messages'
app/views/layouts/base.html.erb:100:in `_app_views_layouts_base_html_erb__4104276684161420982_39604440'
lib/redmine/sudo_mode.rb:63:in `sudo_mode'
Can somebody give me a hand here?
Thanks in advance!
This is stored in your session, so usually changing the session secret key will invalidate all sessions and discard any old session data.
You can also try and rescue to clear it out as a one-time deal.
Have you restarted the server? Or you can use flash[:notice] = nil to remove it.
It looks like it throws a html_safe error. Can you see if the method which is rendering the flash is using html_safe? It looks like its coming from there.
Not sure exactly, may be shooting in the dark.
But read these and try may be:
actionview::template::error(undefined method 'html_safe' for nil:NilClass)
http://www.redmine.org/issues/8477

How to write complex code inside the XLS file on ruby on rails

index.xls.erb
<% #gd = GoodsDelivery.find_all_by_store_location_id(stores.id) %>
<% gd_qty = 0.00 %>
<% for goods_delivery in #gd %>
<% gdl_qty = goods_delivery.goods_delivery_line_items.where(:product_id => prods.id).where(:customer_bill_id => nil).sum(:quantity) %>
<% gd_qty = gd_qty + gdl_qty %><% end %>
<td><%= gd_qty %></td>
I have a code something like this in index.xls.erb file due to some issues i cannot move it into the controller, But in local server it is running properly where as Heroku is my cloud there it is giving error as follows
Error Messege :
Rack::Timeout::RequestTimeoutError: Request ran for longer than 29.989883911185302 seconds.: SELECT SUM("goods_receipt_line_items"."goods_receipt_quantity") AS sum_id FROM "goods_receipt_line_items" WHERE "goods_receipt_line_items"."goods_receipt_id" = 311 AND "goods_receipt_line_items"."product_id" = 133
/app/vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.11/lib/active_record/connection_adapters/postgresql_adapter.rb:1153:in `async_exec' /app/vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.11/lib/active_record/connection_adapters/postgresql_adapter.rb:1153:in `exec_no_cache' /app/vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.11/lib/active_record/connection_adapters/postgresql_adapter
Request timeout error - looking like it's because of your slow database. Try to run your app local and connected to remote database - I think, you'll receive timeout too.

ActionView::Template::Error: Undefined Method on live server only

This Ruby on Rails problem is a bit vexing, as the code works fine locally but not when I push it onto my live server.
I've added a few int columns into a table using a migration and have a few checkboxes to determine whether items of a certain status are displayed on a certain page, eg:
status\page myitems featureditems saleitems
status1 X x x
status2 x x
This works fine locally in a development environment, but when I push the code to my live server the "add new feature" page fails to load with the following error:
Started GET "/admin/statuses/new" for 86.159.115.236 at 2012-08-19 13:39:12 -0400
Processing by Admin::StatusesController#new as HTML
Rendered shared/_validationerror.html.erb (0.0ms)
Rendered admin/statuses/_form.html.erb (2.1ms)
Rendered admin/statuses/new.html.erb within layouts/application (2.2ms)
Completed 500 Internal Server Error in 4ms
ActionView::Template::Error (undefined method `show_my_items' for #<Status:0xb6c1690>):
20: </tr>
21:
22: <tr>
23: <td align="center"><%= f.check_box :show_my_items %></td>
24: <td align="center"><%= f.check_box :show_latest_items %></td>
25: <td align="center"><%= f.check_box :show_featured_items %></td>
26: <td align="center"><%= f.check_box :show_search_results %></td>
app/views/admin/statuses/_form.html.erb:23:in `block in
_app_views_admin_statuses__form_html_erb__566719799_79558060'
app/views/admin/statuses/_form.html.erb:1:in
`_app_views_admin_statuses__form_html_erb__566719799_79558060'
app/views/admin/statuses/new.html.erb:7:in
`_app_views_admin_statuses_new_html_erb__880262090_94647510'
app/controllers/admin/statuses_controller.rb:31:in `new'
In this case 'show_my_items' is one of the fields attached to a status, (represented by page1).
Additionally, on live I can edit a status using the checkbox (but it's int datatype...), but on live, though I can view the edit page and submit without an error, it doesn't actually update the field.
So the columns exist in the database, the code is the same code as I have on live, but the error only happens on the live server. Same version of Rails on both (3.1.0.rc8), ruby versions slightly different (local: 1.9.2p320, live: 1.9.3p194).
No idea what's going on...
Just to be sure, did you run the migration on your server in production mode?
$ RAILS_ENV=production rake db:migrate
Well the problem seems to be that Passenger did not start correctly. Either it takes longer than I thought or something else went wrong, but having restarted passenger again it worked fine.

PostgreSQL and Heroku, find and group

I'm trying to get an app to run on Heroku properly. (Heroku uses the postgreSQL database, yeh?)
In development, I'm using sqlite, and this is my code in a controller =>
#productsort = Products.find(:all,
:select => 'count(*) count, color',
:group => 'color',
:order => 'count DESC',
:conditions => 'size = "Small"')
As you can see, I'm trying to group products by their colors, and order them by greatest amount to least.
Also, the products must be "Small". (the conditions)
In SQL, it works fine.
But not in PostgreSQL (heroku).
This is from running "heroku log"
2011-06-20T18:20:33+00:00 app[web.1]: ActiveRecord::StatementInvalid (PGError: ERROR: column "Small" does not exist
2011-06-20T18:20:33+00:00 app[web.1]: LINE 1: ...ducts".* FROM "products" WHERE (size = "Smal...
Hm... I've searched around and I couldn't find anything similar to what I have.
All help would be appreicated. Thank you
You need to be using single quotes around your strings in the conditions (double quotes may work with sqlite, but they definitely don't with PostgreSQL).
So replace your conditions with this:
:conditions => "size = 'Small'"
It will still work in SQLite too.

Resources