Rails instance variables working locally but not on heroku - ruby-on-rails-3

So i have some instance variables being set in my rails 3.1 controller that are simply failing to exist when i try to call them in my views on heroku (they work fine locally).
With a similar other model with a similar data structure and the same instance variables, it works fine - which makes it all the weirder. Also some instance vars are getting through ok - so i'm struggling to find out what is causing this problem.
Here's a quick example
class PointsController < ApplicationController
def show
#point = Point.find(params[:id])
#area = #point.area
#zoom = 15
#ff = 0
#ff = params[:ff].to_i if params[:ff] and params[:ff].to_i
end
end
In my view, if i put: <%= #point.name %> or <%= #ff %> - they work both on local and heroku environments and the values are returned BUT if i put in:
<%= #zoom %> and <%= #area %> these work locally, but return nothing in the heroku environment. it's just totally random.
Any ideas?
Thanks!

Related

Translating SQL Query to ActiveRecord and Rendering as a Table

I am trying to translate a raw SQL query in my model to use ActiveRecord Query Interface. I think that I translated the query correctly, but I cannot transform it to an array in order to render it.
Here is my model:
class Pgdb < ActiveRecord::Base
self.abstract_class = true
self.table_name = 'test'
if Rails.env.development?
establish_connection :pg_development
end
def self.getInfo(name)
get = Pgdb.where(city: "New York")
get_a = get.to_a
get_a
end
end
The raw SQL query, which I was able to render, was:
get = connection.query("SELECT * FROM test WHERE city = "New York")
As the above code indicates, I am accessing an external PostgreSQL database and have tried to convert the ActiveRecord object to an array using #to_a but this isn't working. When I try to render it in my view:
<% #info.each do |row| %>
<tr>
<% row.each do |element| %>
<td><%= element %></td>
<% end %>
</tr>
<% end %>
I get an error: undefined method 'each' for #<Pgdb:0x007fd37af79040>. I have tried using to_a on the object in different places in the code but nothing has worked.
Controller
def index
end
def new
#thing = Thing.new
end
def create
#info = Pgdb.getInfo(#thing.something)
render :index
end
You are receiving the error undefined method 'each' for an instance of Pgdb because your code is trying to iterate over the instance's data attributes in this line:
<% row.each do |element| %>
ActiveRecord instances are not collections of attributes that you can iterate over. Instead, they are objects that respond to messages named for their attributes. In other words, you can do this:
p = Pgdb.first
p.city # because the underlying table has a `city` attribute
but you can't do this:
p.each { |attribute| puts attribute }
However, ActiveRecord provides the attributes accessor for just this very thing. The attributes method returns a hash that you can iterate over with the each method. Therefore, you can do this:
p.attributes.each { |key, value| puts "#{key}: #{value}" }
In your view, you can substitute the inner loop with:
<% row.attributes.each do |key, value| %>
<td><%= "#{key}: #{value}" %></td>
<% end %>
And this should render the attributes for your instance of Pgdb.
By the way, it is not necessary to cast the result of where into an Array in Pgdb::getInfo. The where query returns an ActiveRecord::Relation object that responds to each, as well as other Enumerable messages like map and select, similarly to an array. In your code, you are successfully iterating over the result set in
<% #info.each do |row| %>
This will work whether you use to_a or not in getInfo. There are good reasons not to cast your result set to an array. For one, ActiveRecord::Relation objects have other capabilities, like scoping, which you may often need to use.
Hope that helps. Happy coding!
The correct way to connect rails to an external database is using the config/database.yml file:
# SQLite version 3.x
# gem install sqlite3
#
# Ensure the SQLite 3 gem is defined in your Gemfile
# gem 'sqlite3'
#
defaults: &defaults
adapter: postgresql
encoding: utf8
template: template0
# used for test & development
local:
host: localhost
username: j_random_user # change this!
password: p4ssword # change this!
development:
<<: *defaults
<<: *local
database: my_app_development
# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
<<: *defaults
<<: *local
database: my_app_test
production:
<<: *defaults
host: "my_app_something.rds.amazonaws.com" # change this!
username: my_amazon_db_user # change this!
password: my_amazon_user # change this!
reconnect: true
port: 3306
You may want to use a local postgres database for development and mirror the production database with pgbackups.
But your main issue is that your are doing pretty much everything wrong when it comes to creating a rails application. That looks like a PHP example where some clueless soul is reinventing an database manager for the 1000th time.
So here is a fast Rails MVC & ActiveRecord crash course:
Models reflect the objects in your domain. Lets say we have a pet store app.
We of course need a Pet model:
$ rails g model Pet name:string
$ rake db:migrate
This creates a pets table in the database and a Pet class. Note that the table name is plural and the model name is singular.
# app/models/pet.rb
class Pet < ActiveRecord::Base
end
We can then access the pets by:
Pet.all
Pet.find(1) # find pet where id is 1
# ... etc
And we can create pets by:
pet = Pet.create(name: "Spot")
All of this is covered in most basic rails tutorials.
Connecting without a model.
ActiveRecord::Base.establish_connection
con = ActiveRecord::Base.connection
res = con.execute('SELECT * FROM foo')
Although using ActiveRecord does not really make sense if you are not actually using a model per table and following the MVC conventions somewhat. It's possible, but it gives you no real benefits at all.
Likewise doing Rails without MVC is doable but what's the point?
Using a legacy database
let's say you have a legacy database written by someone who though using Apps Hungarian for database columns (shrug) was cool:
persons:
intPersonID: Integer, Autoincrement, Primary Key
And you want to map this to a Rails model
class User < ActiveRecord::Base
self.table_name 'persons'
self.primary_key 'intPersonID'
end
Or in your case:
class Test < ActiveRecord::Base
self.table_name 'test' # since it's not "tests"
end
Test.where(city: "New York")

Rails ERB -- get the generated HTML content to a variable I can access in a controller

I am doing an online contract agreement which is generated dynamically based on the current state of our contract language (stored in an ERB partial).
When the user clicks "I Agree" we save the variable data, but I also want to store the contents of the rendered partial (html fragment) in the database.
I tried using ActionView::Helpers::CaptureHelper.capture -- wrapping the whole partial in a block and rendering at the end, like
<% #saved_output = capture do %>
...
The rest of the erb with instance variable <%= #my_class.name %> and so on
...
<% end %>
<%= #saved_output %>
<% logger.debug "Rendered output is: #{#saved_output}" %>
And this produced the same result and also sent the correct text to the log. But it appears to go out of scope -- even if I declare #saved_output = nil prior to render it's nil when I end the block.
I tried using content_for as well ... which makes some sense to me, but ... huh, just not getting it. Any helpful pointers appreciated.
Have you tried render_to_string in your controller when you're creating the record? That may allow you to just go ahead and "snapshot" the page.

Rails - uncached controller action messing with serialized attribute

I have a controller action that calls a model method which generates a serialized list of data pulled from another model database. I need this to be uncached because the SQL queries should be random data pulls.
Here's a general idea of my code (Note that User has_one Foo, Bar is an arbitrary model of data, :data_list is of type text, and the database is SQLite):
# app/models/foo.rb
class Foo < ActiveRecord::Base
serialize :data_list
def generate_data
list = []
for i in 1..4
data = Bar.find(:first, :order => "Random()")
list << data
end
self.data_list = list
end
end
# app/controllers/users_controller.rb
class UsersController < ApplicationController
def generate_action
...
uncached do
#user.foo.generate_data
end
#user.foo.save
end
end
# app/views/user/show.html.erb
...
<% #user.foo.data_list.each do |data| %>
<%= data %><br />
<% end %>
Whenever uncached do ... end is removed, everything works fine and the show view prints out each set of Bar objects in #user.foo.data_list. Unfortunately, because of Rails' SQL caching, it ends up look like this:
RandomDataPoint8
RandomDataPoint8
RandomDataPoint8
RandomDataPoint8
When I need to look like this:
RandomDataPoint7
RandomDataPoint13
RandomDataPoint2
RandomDataPoint21
It should be noted that running user.foo.generate_data from Rails command line works perfectly with the randomization. It is only when being called from the controller that caching starts to occur.
My research suggested I use uncached in the controller to remove caching, however it seems to destroy my data serialization and I receive the error:
undefined method 'each' for #<String:0x007ff49008dc70>
In fact, it does this even if I retroactively add in uncached (having successfully generated a data_plan without uncached prior) and save the controller, but don't call generate_action.
EDIT
I believe this problem is actually related to the fact that I was storing an object in the hash. Switching to the object id fixed this problem. Another SO question of mine regarding this can be found here:
Rails - Accessing serialized data from console
The following has been preserved just because the syntax may still help people, but I don't believe it was the actual cause of the problem.
I solved this by moving uncached to the model. For reference, the source I was using to originally solve this problem was this link: http://railspikes.com/2008/8/18/disabling-activerecord-query-caching-when-needed
What I overlooked is that he puts uncached in the model, not the controller. Also, the syntax needed to be a little different:
# app/models/foo.rb
self.class.uncached do
...
end
instead of
uncached do
...
end
The source for the syntax correction is this SO response: https://stackoverflow.com/a/967690/337903

How do I make a settings configuration page for the rails-settings gem?

I just discovered the rails-settings gem and now I need to make an admin page that lets me edit the setting values. How would I make a settings controller with an edit view that can change these dynamic app wide settings?
I haven't used this gem but it seems like it should be fairly straight forward. Since it uses a database backed model, you would simply create a controller as normal:
rails g controller Settings
From here you would define your index action to gather all your individual settings for display in the view:
def index
#settings = Settings.all
end
Then in the view you can setup a loop to display them:
<% #settings.each do |setting| %>
<%= setting.var %> = <%= setting.value %>
<% end %>
As far as editing ... this might be a bit tricky since by default rails would expect you to submit only one setting at a time to edit. You could do it this way but unless you implement the edit with ajax it might be tedious and non-intuitive.
Another way would be to set up your update method to accept all the individual settings at once, loop through and update each one with new values. It might look something like this:
// The /settings route would need to be setup manually since it is without an id (the default)
<%= form_tag("/settings", :method => "put") do %>
<% #settings.each do |setting| %>
<%= label_tag(setting.var, setting.var) %>
<%= text_field_tag(setting.var, :value => setting.value) %>
<% end %>
<%= submit_tag("Save Changes") %>
<% end %>
This should output all of the settings (given they have been assigned to the #settings variable) with the var name as the label and the current value as the text field value. Assuming that the routing is setup, when you submit this form the action that receives it should all the new settings in the params variable. Then you can do something like this in the action:
def update
params.each_pair do |setting, value|
eval("Settings.#{setting} = #{value}")
end
redirect_to settings_path, :notice => 'Settings updated' # Redirect to the settings index
end
This may not be the best way depending on how often you edit the settings and how many settings you have...but this is a possible solution.
I was looking for some suggestions for this and found another answer to this that is very simple and elegant, for anyone looking for this later. It just sets up dynamic accessors in your model, allowing your form to have settings fields just like your normal attributes. An example can be found in the original answer:
How to create a form for the rails-settings plugin

Memberships engine not working properly

I've installed RefineryCMS and a couple of its engines (like Blog). Everything was working fine until I installed Memberships engine.
After struggling a couple of days, I could make it "work". By "work" I mean that I could create a user, but since I have it installed, each time I access the home page I get the following error:
undefined method `refinery_user?'
Extracted source (around line #1):
1: <% if refinery_user? %>
2: <% unless admin? # all required JS included by backend. %>
3: <% content_for :stylesheets, stylesheet_link_tag('refinery/site_bar') unless !!local_assigns[:exclude_css] %>
4: <%= yield(:stylesheets) unless local_assigns[:head] or local_assigns[:exclude_css] %>
I've "ctrl+click" on that method and it does exist!! It has the following code:
def refinery_user?
user_signed_in? && current_user.has_role?(:refinery)
end
The weird thing is that I've put a breakpoint on that line but the app didn't stop there...
Does anybody know what's going on?
Make sure your /config/initializers/devise.rb file exists and that it includes the following (probably at the bottom):
config.router_name = :refinery