Rails PostgreSQL array can't iterate - ruby-on-rails

I wrote a helper method for my controller to iterate through an attribute, being represented as an array using PostgreSQL.
def format_cf array
nums = ""
array.each { |c| nums += "#{c}, " }
unless nums.blank?
nums.chop!.chop!
end
nums
end
This way, I don't get the messy {} chars in my view. I'm implementing an empty value for this attribute as the string '{}', meaning that's what I set the default value to in my migration. This hasn't been a problem for my development environment, as it interprets that as an empty array. However, now in production, this helper method is throwing an error saying
ActionView::Template::Error (undefined method `each' for "{}":String)
Is my implementation wrong here, or can anyone think of some obscure setting I may have overlooked when comparing my development.rb and production.rb?
EDIT: 2013-04-11 9:00
I'm currently deploying using capistrano with unicorn and nginx

I'm going to guess you may have run into this bug as well, if you're using rails 4 https://github.com/rails/rails/issues/10432. Basically there's a bug in the Migrations system that turns :string, array: true into a normal :string directive. The joys of using edge stuff huh.

I gues you used taps to deploy tour database on heroku with
heroku db:push
Problem is that taps doesn't support Postgres array, and it ends up casting the column as a string. There are many workaround for that.
The one I used was to open a console on heroku
heroku run console
Then get a connection to the database
User.connection # or any of your models
And then execute raw sql with the connection#execute method in order to create a backup column, delete the current string column and recreate it as an array.
You'll probably find it more useful to use the import/export advised by heroku
And if you're not using heroku, then I' completely wrong, and I have no idea what your problem is :)

Related

Why is Rails runner not returning a result?

I am having problems with the Rails runner. When I try to use if, even by command line, it does nothing! it doesn't show error messages, nor results from actions.
For example, if I try
rails runner Credit.count
having defined the model Credit, and the method count as
Credit.first.update_attribute(:estado, "En proceso")
or even simpler tasks, the runner does nothing!
I've tried saying that the environment is development, but nothing works. Does anyone has any insights? Am I doing something wrong?
Edit: I am watching the database, that's the problem, there is no update. I changed the value of the column "estado" for the first element to something other than "En proceso", however, no matter how many times I use the runner, the db doesn't show any change at all.
rails runner: runner runs Ruby code in the context of Rails non-interactively
update_attribute : it only return true or false, if you want to output the result, you can use "puts" or "p".
For example,
$ rails r "User.first" #no output, even it will return a user object
$ rails r "puts User.first" # you can use "puts" get the output
#<User:0x007f8a2c76e608>
if you just written Credit.first.update_attribute(:estado, "En proceso") in console, you shouldn't have results, but you could see result in DB, for checking if update_attribute really update it you could write as update_attribute! also you could just write:
p Credit.first.update_attribute(:estado, "En proceso") which should print true or false to console
Turns out I am an idiot.
First, I had to change the name of the method, calling Credit.count calls the default count method, so I changed it to myMethod.
After that, I was able to use puts function and update the database easily :)

Rails 4: Using ActionView helpers in model works in development env but not in production

I use the following code in one of my models
def jasper_amount
ActionController::Base.helpers.number_to_currency(amount)
end
I know that it breaks MVC. However, in this case it is the best solution. I have to pass data to Jasper via the Ruby Java Bridge and formatting in Jasper would be much more complicated.
Calling object.jasper_amount from the rails console works fine and prints the expected results. This works fine in development and production.
Now, to pass the data to Jasper I first have to create an xml version of the object's attributes using object.to_xml(methods: [:jasper_amount]).to_s This works in development but not in production. In production the value for jasper_amount that is passed to Jasper is "0.00 €". However, if I remove number_to_currency from def jasper_amount (just returning unformatted amount) it works. What's even more confusing is the fact that calling jasper_amount from the rails console in productions works. I guess the culprit must be to_xml, but I have no idea why it works in development and not in production.
The problem was with Ruby Java Bridge (rjb) and BigDecimal. If you use BigDecimal with rjb, you have to include the "BigDecimal" gem in your Gemfile. Otherwise all your BigDecimals will be 0 (and that all over your app!)

Rails 3 - Foreign Keys - Strings vs Symbols

I am in the process of learning Rails and I've ran into an interesting problem tonight.
I was creating a migration that would require an index on the foreign key:
Whenever I would run 'bundle exec rake db:migrate', I would receive this console error:
It looks as if it was trying to create the index before it was creating the reference.
The reason I believe this is because when I change the "subject" reference to a symbol:
The migration then suddenly works as expected!
This may just be the fact that I'm a total newby, but are symbols actually processed faster by Ruby than strings are?
Just curious - thanks!
This isn't a "faster" problem, or a problem of speed. The migrations are executed one line at a time, in order. The way you had it specified before simply didn't create the column correctly, hence when it got to the line where you create the index, the names didn't match up.
My guess is, with the string version it created the column name exactly as you spelled it, "subject" as opposed to subject_id when you use a symbol. Either way, you definitely had a name mismatch between when the column was created, and when the index was being built.
Always use symbols for this in your migrations, and you should be fine. Always check your schema.rb file, or browse the database using a GUI tool, after a migration to make sure the columns got created the way you expect, and with the data types you think they are, and you should be good.

Not able to use methods generated by ActiveRecord in resque

In my current database setup I have a user and a server table. I am able to do things like current_user.server from the rails console, but I am not able to do this from inside a resque worker. I am however, able to call current_user.name because of this code in my resque worker:
current_user = User.find(current_id)
I was able to do this by passing in the current_user's id to the worker. I thought I could use the same process for the user's server table; it's a has_one user->server relationship.
So I tried this:
current_server = Server.where(:user_id => current_user.id)
current_server[:cloudserver] = 123 #Just an example number
current_server.save
The first line worked fine, it returned the right server row. However, when I also include the second line I get an error:
TypeError can't convert Symbol into Integer
I know I created the cloudserver column as an integer type, and I made sure I loaded the rails environment in the resque workers. I can set the correct number by using the rails console:
current_user.server[:cloudserver] = 123
current_user.save
Since I can set it outside of the resque worker, I'm pretty sure it's a resque problem.
Oh, and I'm also running rails 3.1rc4 if that helps.
Thanks all!

Rails and Heroku PGError: column does not exist

This page I have been developing for my app has been working fine locally (using sqllite3) but when I push it to Heroku, which uses PostgreSQL I get this error:
NeighborhoodsController# (ActionView::Template::Error) "PGError: ERROR: column \"isupforconsideration\" does not exist\nLINE 1: ... \"photos\" WHERE (neighborhood = 52 AND isUpForCon...\n
From this line of code:
#photos = Photo.where(["neighborhood = ? AND isUpForConsideration = ?", #neighborhood.id, 1])
isUpForConsideration is defiantly part of the Photo column. All my migrations are up to date, and when I pull the db back locally isUpForConsideration is still there, and the app still works locally.
I've also tried:
#photos = #neighborhood.photos(:conditions => {:isUpForConsideration => 1})
and
#photos = #neighborhood.photos.where(["isUpForConsideration = 1"])
Which gives me this error:
NeighborhoodsController# (ActionView::Template::Error) "PGError: ERROR: column \"isupforconsideration\" does not exist\nLINE 1: ...tos\" WHERE (\"photos\".neighborhood = 52) AND (isUpForCon...\n
Any idea what I could be doing wrong?
Your problem is that table and column names are case sensitive in PostgreSQL. This is normally hidden by automatically converting these to all-lowercase when making queries (hence why you see the error message reporting "isupforconsideration"), but if you managed to dodge that conversion on creation (by double quoting the name, like Rails does for you when you create a table), you'll see this weirdness. You need to enclose "isUpForConsideration" in double quotes when using it in a WHERE clause to fix this.
e.g.
#photos = #neighborhood.photos.where(["\"isUpForConsideration\" = 1"])
Another way to to get this error by modifying a migration and pushing changes up to Heroku without rebuilding the table.
Caveat: You'll lose data and perhaps references, so what I'm about to explain is a bad idea unless you're certain that no references will be lost. Rails provides ways to modify tables with migrations -- create new migrations to modify tables, don't modify the migrations themselves after they're created, generally.
Having said that, you can run heroku run rake db:rollback until that table you changed pops off, and then run heroku run rake db:migrate to put it back with your changes.
In addition, you can use the taps gem to back up and restore data. Pull down the database tables, munge them the way you need and then push the tables back up with taps. I do this quite often during the prototyping phase. I'd never do that with a live app though.

Resources