Missing column name during ActiveAdmin query - ruby-on-rails

Rails 3.1, Ruby 1.9.2, using a SQL Server 2008 database through the activerecord-sqlserver-adapter gem. I'm working with a legacy database, so this was not voluntary.
I'm running into an odd problem with ActiveAdmin. I've not used ActiveAdmin before, and added it after watching a Railscast. Followed the standard installation instructions, and I'm able to log into the admin console.
When I add a model:
rails generate active_admin:resource Payment
The model (in plural) is now visible on the ActiveAdmin dashboard. However, when I click on the link, I get the following error:
TinyTds::Error: No column name was specified for column 2 of '__rnt'.: EXEC
sp_executesql N'SELECT TOP (1) [__rnt].* FROM ( SELECT ROW_NUMBER() OVER (ORDER
BY [Payments].[UPaymentID] ASC) AS [__rn], 1 FROM [Payments] ) AS [__rnt]
WHERE [__rnt].[__rn] > (0) ORDER BY [__rnt].[__rn] ASC'
Now, this query returns the same error if I run it directly on the SQL Server database - it doesn't like the unnamed column of "1".
Started digging to see what the issue was. The obvious places to look would be in the transitions between activeadmin and activerecord, and then activerecord and the SQL Server adapter. Here's the stack trace for the first intersection:
activerecord (3.1.0) lib/active_record/relation/finder_methods.rb:197:in `exists?'
activeadmin (0.4.2) lib/active_admin/views/pages/index.rb:41:in `items_in_collection?'
activeadmin (0.4.2) lib/active_admin/views/pages/index.rb:20:in `main_content'
It looks like items_in_collection? is calling exists? on a collection that has had order filters removed. At this point, we're handing off to ActiveRecord. If we look at the transition from ActiveRecord to the SQL Server adapter, it looks as if the SELECT statement has already been formed:
activerecord-sqlserver-adapter (3.1.6) lib/active_record/connection_adapters/sqlserver/database_statements.rb:348:in `do_exec_query'
activerecord-sqlserver-adapter (3.1.6) lib/active_record/connection_adapters/sqlserver/database_statements.rb:24:in `exec_query'
activerecord-sqlserver-adapter (3.1.6) lib/active_record/connection_adapters/sqlserver/database_statements.rb:297:in `select'
activerecord (3.1.0) lib/active_record/connection_adapters/abstract/database_statements.rb:18:in `select_all'
activerecord (3.1.0) lib/active_record/connection_adapters/abstract/query_cache.rb:61:in `block in select_all'
I'm totally confused as to why the SQL would be generated the way that it is. There are a couple of candidate problem areas:
I'm working on a legacy database with an odd schema. I'm having to set table names and primary key names within my models. I don't think this is the issue, since the query that is coming out seems to use the appropriate primary key and table names.
Problems with the activerecord-sqlserver-adapter gem. However, I pulled the source code, and it sure doesn't look like there is anything there that would be assembling this query in that way.
Has anyone run into anything similar to this? It may be that I'll just need to debug my way through the whole stack to see what's going on. Figured it would be worth checking here first though.
Edit: I'm now fairly sure this is a bug in activerecord-sqlserver-adapter. Will post resolution here once I have it.
Edit2: Can reproduce the error without ActiveAdmin at all. This is related to the way that the sql server adapter deals with offset queries. Calling
MyModel.offset(1).exists?
produces the same error. I have an ugly patch to the adapter which passes all the unit tests, but I'm going to try to find a more elegant solution before making a pull request.

I'm not sure this is exactly the answer, but I patched my local code and your query works for me now.
First, the github issue:
https://github.com/rails/rails/issues/1623
and then the pull request for arkadiyk's fix:
https://github.com/arkadiyk/rails/commit/7e2ddddb303d17adc825ebb691097a93902fa539
The basic problem is finder_methods.rb, which has the existing code around line 187 or 188:
relation = relation.except(:select).select("1").limit(1)
MSSQL barfs on the unnamed column this generates, so the following code fixes it:
relation = relation.except(:select).select("1 as o").limit(1)
Hope that helps.

There seem to be two alternatives to fixing this: fix it in rails, or fix it in activerecord-sqlserver-adapter.
The link that Raels has provided is probably the right way to fix this, however, the pull request has not been accepted into rails. I'm concerned about using a patched version of rails, as this will force me to either stick with my patched version, or continue to patch as rails evolves.
Al alternative is to fix this in activerecord-sqlserver-adapter. I've submitted a pull request here:
https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/171
It's possible that the maintainer of active-sqlserver-adapter will come up with a more elegant fix. If he does, I'll update this answer.

Related

Rails 5.2.2.1 ActiveRecord::RecordInvalid: Validation failed

I updated my company's application from Rails 5.2.1 to Rails 5.2.2.1. Upon running our test suite post-update, I am encountering issues with validating uniqueness within the scope of a model, specifically, when appending a model to the ActiveRecord relation of another model. For example, in our application, if I were to do #person.cars << #car, we would run a uniqueness validation (validates :car_id, uniqueness: { scope: :group_id }. Even in a scenario where #person.cars was originally empty, our post-update branch is throwing validation errors on this uniqueness check. These test cases work on our master branch (pre-update), but not on our update branch (post-update). There have been no other changes made to the application besides updating Rails from 5.2.1 to 5.2.2.1. I am wondering if anyone knows of any existing bugs or issues in relation to Rails 5.2.2.1 uniqueness validations that may be causing this. I have looked through the changelogs of both Rails and ActiveRecord, as well as a few other dependencies that were updated, but I have been unable to find anything.
Looks like this is an issue with a change made in Rail's ActiveRecord::Associations which used to remove duplicates in version 5.2.1, when appending to an ActiveRecord association. This never threw a RecordInvalid exception, as the duplicate would be removed before hand. In 5.2.2.1, it looks like that has been removed, and any duplicates appending to an association will no longer be preemptively deleted (most likely to mimic Ruby += functionality). I had to change all your uses of += to a relation to |= to ensure duplicates were no longer being appended on.
Sorry for no being able to post any code or stack traces. The stack trace was very application specific and wouldn't have been helpful at all, and the code is proprietary. Appreciate the help!

What is the source of "unknown OID" errors in Rails?

When replicating an app to production, my POSTGIS table columns started misbehaving, with Rails informing me there was an "unknown OID 26865" and that the fields would be treated as String.
Instead of current_pos yielding e. g.
#<RGeo::Geographic::SphericalPointImpl:0x22fabdc "POINT (13.39318248760133 52.52908798020595)"> I would get 0101000020E6100000FFDD958664C92A403619DEE6B2434A40. It looked like the activerecord-postgis-adapter was not installed, or installed badly, but I eliminated that possibility by testing for the existence of data type RGeo::Feature::Point and by test-assigning
current_pos = "POINT (13.39318248760133 52.52908798020595)"
to the field - which proceeded without error but then yielded another incomprehensible hex string like the above.
Also, strangely enough, POSTGIS was working correctly within the database, e.g. giving correct results for a ST_DISTANCE query. A very limited problem thus, where writing, writing-parsing (from Point to hex format), manipulating by SQL and reading all worked, only the parsing upon read didn't.
When I tried to use migrations to ensure the database column would have the correct type, the migrations failed, giving
undefined method `st_point' for #<ActiveRecord::ConnectionAdapters::PostgreSQL::TableDefinition:0x00000005cb80b8>
I spent several hours trying all kinds of solutions, even re-installing the server from scratch, double-checking version numbers of everything, installing a slightly newer version of Ruby and a slightly older version of POSTGIS (to match my other environment), exporting the database and starting with a clean one, and so on. After I had done migrations and arrived at the "undefined method st_point" error, I was finally able to find the solution via Google, way down in a Github issue, and it's really simple:
In config/database.yml, swap out postgres:// for postgis:// in the database url. If you're using Heroku, this may require some ugly manipulation:
production:
url: <%= ENV.fetch('DATABASE_URL', '').sub(/^postgres/, "postgis") %>
So silly...
Do not forget to add activerecord-postgis-adapter to your Gemfile so #Sprachprofi's solution can run.

How do I override ActiveModel type processing in Rails (JRuby)

I'm trying to create a rails model around an oracle table that has a column "SESSION_XML" using Oracle's XMLTYPE. Whenever I attempt to use the model to get data from the db, the connection adapter responds with:
SELECT "ZC_SESSION_DATA".* FROM "ZC_SESSION_DATA" WHERE ROWNUM <= 1
ActiveRecord::StatementInvalid: Java::JavaLang::NoClassDefFoundError: oracle/xdb/XMLType:SELECT "ZC_SESSION_DATA".* FROM "ZC_SESSION_DATA" WHERE ROWNUM <= 1
from oracle.jdbc.oracore.OracleTypeADT.applyTDSpatches(OracleTypeADT.java:1081)
It seems clear to me that Java (I'm using Rails on top of JRuby) is complaining that it doesn't have a type with which to parse the XMLTYPE column, so my question is this: How can I force rails to interpret the XMLTYPE as a flat string.
I'm fine with needing to parse the XML myself, but how do I get the adapter to stop trying to parse it?
This is an Oracle problem, not really an ActiveRecord problem:
https://community.oracle.com/thread/485754?start=0&tstart=0
TL;DR there's a jar that isn't being loaded that defines XMLType.

Using mongomapper to execute server runCommand geoNear

I would very much like to use the mongo geoNear command as discussed here.
Here is the command I entered in my rails console with the accompanying error message.
MongoMapper.database.command({ 'geoNear' => "trips", 'near' => [45,45]})
Mongo::OperationFailure: Database command 'geoNear' failed:
(errmsg: 'more than 1 geo indexes :('; ok: '0.0').
I can not make sense of the error message, it is supposedly impossible to have more than 1 geo index and I am certain that I have only created one.
Based on this stackoverflow question I believe I am wording the query correctly. Does anyone understand that error message? How would I go about destroying and recreating my indexes?
I am using rails 3.1 with mongodb v2.0 and the mongo ruby gem v1.5.1.
I really asked this too soon, maybe I should delete it? Somehow there were in fact too many geo indexes, because deleting the index and recreating it fixed the problem.
MongoMapper.database.collection('trips').drop_indexes
Trip.ensure_index [[:route, '2d']]

mysql2 driver seems to write invalid queries

I'm developing an application layer on top of a rails app developed by someone else.
His application uses a module called request_logger to write to a table, which worked fine under ruby1.8/rails2/mysql gem, but in my ruby1.9/rails3/mysql2 environment, activerecord falls over, suggesting that the generated query is invalid.
It obviously is, all mysql relation names are wrapped in double quotes instead of backticks.
The call to activerecord itself just sets a bunch of attributes with
log.attributes = {
:user_id => user_id,
:controller => controller,
...etc
}
and then calls
log.save
So I'm leaning towards it not being dodgy invocation. Any suggestions?
mysql2 works fine for a lot of people, but it unashamedly sacrifices conformance to the MySQL C API for performance in the common tasks. Perhaps, if request_logger is low-level enough, it's expecting calls to exist which don't.
It's trivial to switch back to using mysql - give it a try, and if it works, stick with it. Remember to change both your Gemfile and your config/database.yml settings.
It turned out to be what seems to be a change in behaviour between rails 2 and 3 (we have the same setup working fine in rails 2)
We use database.yml to specify an (empty) "master" database and then feed in our clients with shards+octopus.
The master db is sqlite for simplicity, and it seems that activerecord was feeding off requests formatted for sqlite to the mysql2 shards, regardless of their adaptor type.

Resources