ActiveRecord and illegal column names - ruby-on-rails

I want to access the Limesurvey database via ActiveRecord. Some tables have column names like '79924X192X1240'. When I want to access the model, I get the following error:
ActionView::Template::Error (/usr/local/rvm/gems/ruby-1.9.2-p318/gems/activerecord-3.1.10/lib/active_record/attribute_methods/time_zone_conversion.rb:44: syntax error, unexpected tINTEGER
def 79924X192X1240=(original_time)
^):
I guess, the error appears, because it's not allowed, that a method starts with a digit. But I can't alter the column name, because Limesurvey generates these columns.
This error appears only if the data type of a column (like 79924X192X1240) is datetime. Other data types like varchar don't make any problems.
How can I access these datetime columns, too?

You need to do raw sql queries for that. ActiveRecord is written for ruby which does not allow method names to start with numbers. Since each column on the table is equivalent to a method, then trying to access that information will throw a syntax error every time.
You need to use: ActiveRecord::Base.connection.execute

Related

Rails - Summing an encrypted field

I have an encrypted column :amount following using Lockbox that I need to sum in my controller.
Currently, I have -
transaction_controller.rb
#one_month_transactions_sum = transactions.where(transaction_date: 1.month.ago..Date.today).sum(:amount).abs()
This is giving me the error - PG::UndefinedColumn: ERROR: column "amount" does not exist LINE 1: SELECT SUM(amount) FROM "transactions" WHERE "transactions".... which makes sense because I am asking rails to use the PG SUM function on a column I changed to be a ciphertext.
How would I sum the transactions at the controller level with an encrypted column?
If you send data to database as opaque binary blobs, you (naturally) lose ability to manipulate those fields directly in the database. It appears that your only option is to fetch encrypted values into the app, decrypt and sum in ruby (slowly). I haven't tried this specific library, but I'd guess that something like this should work:
transactions.where(...).map(&:amount).sum

Is it possible to get column names from an relation even if result rows are zero?

In Rails, one uses ActiveRecord for querying the database. ActiveRecord's query results in an ActiveRecord::Relation object. Since we can execute ActiveRecord::Relation#select and specify arbitrary SQL select clause, sometimes the records returned by the database contains columns which does not exist in the database.
If this relation contains more than one row, then one can get the column names of the relation by using the_relation.first.attributes. When no records were returned by the query, however, this method is not possible.
Question
Is there any way to get the Query's resulting column names of an ActiveRecord::Relation even if no rows were returned?
The motivation
For example, when you're building an Daru::DataFrame instance or some other Relational Data, you'd want to obtain the attribute names even if there is no records in the result.
Yes you can get the column names
If the result is ActiveRecord::Relation then you can use something like this
the_relation.column_names

In Rails how to use a model's method for the active record `where`?

Normally we use Model.where(name: 'John') to find records. Let's say I have a method inside the model named status which does some calculations and output a string. How can I use that in the where? Now if I use Model.where(status: 'active') it says PG::UndefinedColumn: ERROR: column model.status does not exist
No, you can't. where is for SQL conditions, if you calculate your status in Ruby, you can't use it in where.
If what you ask is how to have status applied as a filter by the SQL server before retrieving the records, you can't.
One option indeed, is to retrieve all the records and then use select to get what you want. That is very inefficient.
One other option is to write a fragment of SQL logic and plug that straight into a where. That is not easy but very efficient.
One last solution is to have that status be computer for you by a before_save and stored in the table. You can then use a regular where to filter which records you want. The downside of this, is that you have a new extra column.

Specify an attribute or mention table name for last in Model.last(5)

In an active-record chaining association when using last(10), am getting an error:
ActiveRecord::StatementInvalid Exception: Mysql2::Error: Column 'id'
in order clause is ambiguous
To solve this we normally specify the table name i.e posts.id, but how can i put the same logic with last?
After going through the documentation of ActiveRecord Last, found it uses the primary key. Also can we specify a custom attribute?
Any help or thoughts appreciated.
Thanks
The error means you're ordering by a column called id and that you've at least two tables in your from and join clauses which contain a column with that name. You need to qualify it accordingly, e.g. yourtable.id.
Thanks MrYoshji for his suggestions, the last for the activerecord works alternately.
You can pass the limit or a specific column, but not both.
It accepts only attribute, if of type integer it uses limit, as per documentation
order("#{primary_key} DESC").limit(*args).reverse
for specifying an attribute other than "id" we can use this:
Model.last(:order => 'models.score')
As my requirements goes it shud be
order("models.id desc").limit(12)
Let me know if this can be made better.
Thanks

Can't insert row in table with computed column?

I've got a Rails 3 applicaiton running on SQL Server against a legacy database with some computed columns. When I try to save a new record, I get an error "The column "ContractPendingDays" cannot be modified because it is either a computed column or is the result of a UNION operator
I'm not updating this column, it just seems to be one of the columns activerecord tries to write to when adding a new record into the db.
Is there some way to stop this behavior? I even tried changing schema rb but that didn't help. (and suboptimal anyway since I'd have to do it every time I change the db.)
Is there some way to mark a column as not updatable so activerecord doesn't try to write to it?
Found answer here:
Prevent NULL for active record INSERT?
(Use attributes.delete in a before_create filter)

Resources