I'm stuck with the query that checks whether two arrays have one or more elements in common.
Since the query is the part of a much bigger query, I need to use Arel to accomplish this. But the && operator, known as the overlap operator, is not implemented in Arel gem.
There's a postgres_ext gem that implements the above mentioned operator and provides a .overlap method so that one could construct the query similar to the one I did: DiscountCondition.arel_table[:target_plan_period_ids].overlap(target_period_ids). This produces an SQL where clause that works fine for me: "\"discount_conditions\".\"target_plan_period_ids\" && '{2}'".
But. The thing is some tests in our application failed with the following error: NoMethodError: undefined method 'array' for #<ActiveRecord::ConnectionAdapters::SQLite3Column:0x007f23c4995ba8> (turns out the gem is incompatible with some adapters).
A simple ActiveRecord query that works is DiscountCondition.where('target_plan_period_ids && ARRAY[?]', target_period_ids) that produces the following SQL query "SELECT \"discount_conditions\".\"discount_id\" FROM \"discount_conditions\" WHERE (target_plan_period_ids && ARRAY[2])".
So, I wanted to know if anyone faced that issue and succeeded to workaround this.
Just in case someone ever faces the same issue, I ended up monkey patching the aforementioned functionality of a postgres_ext gem into the project.
Related
I have been chasing an issue down for a while now, and still cannot figure out what's happening. I am unable to edit documents made from my gem through normal persistence methods, like update or even just editing attributes and calling save.
For example, calling:
Scram::Policy.where(id: a.id).first.update!(priority: 12345)
Will not work at all (there are no errors, but the document has not updated). But the following will work fine:
Scram::Policy.collection.find( { "_id" => a.id } ).update_one( { "$set" => {"priority" => 12345}})
I am not sure what I'm doing wrong. Calling update and save on any other model works fine. The document in question is from my gem: https://github.com/skreem/scram/blob/master/lib/scram/app/models/policy.rb
I cannot edit its embedded documents either (targets). I have tried removing the store_in macro, and specifying exactly what class to use using inverse_of and class_name in a fake app to reimplement these classes: https://github.com/skreem/scram-implementation/blob/master/lib/scram/lib/scram/app/models/policy.rb
I've tried reimplementing the entire gem into a clean fake rails application: https://github.com/skreem/scram-implementation
Running these in rails console demonstrates how updating does not work:
https://gist.github.com/skreem/c70f9ddcc269e78015dd31c92917fafa
Is this an issue with mongoid concerning embedded documents, or is there some small intricacy I am missing in my code?
EDIT:
The issue continues if you run irb from the root of my gem (scram) and then run the following:
require "scram.rb"
Mongoid.load!('./spec/config/mongoid.yml', :test)
Scram::Policy.first.update!(priority: 32) #=> doesn't update the document at all
Scram::Policy.where(id: "58af256f366a3536f0d54a61").update(priority: 322) #=> works just fine
Oddly enough, the following doesn't work:
Scram::Policy.where(id: "58af256f366a3536f0d54a61").first.update(priority: 322)
It seems like first isn't retrieving what I want. Doing an equality comparison shows that the first document is equal to the first returned by the where query.
Well. As it turns out, you cannot call a field collection_name or else mongoid will ensure bad things happen to you. Just renaming the field solved all my issues. Here's the code within mongoid that was responsible for the collision: https://github.com/mongodb/mongoid/blob/master/lib/mongoid/persistence_context.rb#L82
Here's the commit within my gem that fixed my issue: https://github.com/skreem/scram/commit/25995e955c235b24ac86d389dca59996fc60d822
Edit:
Make sure to update your Mongoid version if you have dealt with this issue and did not get any warnings! After creating an issue on the mongoid issue tracker, PersistenceContext was added to a list of prohibited methods. Now, attempting to use collection_name or collection as a field will cause mongoid to spit out a couple of warnings.
Fix commit: https://github.com/mongodb/mongoid/commit/6831518193321d2cb1642512432a19ec91f4b56d
I have a statement in my code:
RentalItem.last.maintenance_orders.where("status_id IS NOT 2").present?
Works fine in development mode, but not in PostGreSQL in production. Trouble is, that syntax was the only way of making the code work because in my statement, if a child maintenance_order had a status_id of nil, then I want it to be found by the .present? command. Other syntaxes were ignoring nil. See this question here: Rails ActiveRecord find children where attribute is NOT a given value
Any ideas on how to change this syntax?
Try:
RentalItem.last.maintenance_orders.where("status_id <> 2 or status_id is null").present?
I just switched rails console to use pry.
I'm also using ruby 2.1.2p95, rails 4.1.5, neo4j (3.0.0.alpha.11), neo4j-community (2.1.3), neo4j-core (3.0.0.alpha.19)
While executing the command show-models it failed, returning the following error:
[3] pry(main)> show-models
ArgumentError: wrong number of arguments (1 for 2..3)
from /home/pdipietro/.rvm/gems/ruby-2.1.2/bundler/gems/neo4j-2e41203410cc/lib/neo4j/active_node/has_n.rb:79:in `has_one'
has anyone an idea on how to circunvent it?
Thank you
Paolo
Look in your models, one of them has a bad has_one call. Every has_one requires at minimum two parameters: a direction and an association name. That indicates you have one that's probably using the old syntax, just doing has_one :association. See documentation at https://github.com/neo4jrb/neo4j/wiki/Neo4j-v3-Declared-Relationships.
EDIT: Unfortunately, I just tested and it doesn't look like show-models doesn't recognize these models. You can add an issue at https://github.com/neo4jrb/neo4j and we can work on adding support. The error you're reporting still has nothing to do with pry, though.
Also, 3.0.0.alpha.11 is quite old at this point, the gem has been released and is now up to 3.0.1. You should really update.
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.
Prior to Rails 3, creating a plugin to extend find was relatively easy: basically override the find method itself in ActiveRecord::Base, calling super if needed.
Now that Arel is being used in Rails 3, (specifically I'm using Rails 3.1), how would I go about doing something similar? The problem is that many of the old find methods are deprecated in favor of scopes like where, order, limit, etc. At what point(s) in the Rails source should I try to override the default behavior?
I'm sure it's going to be a bit more convoluted than this, but the closest thing I can find that seems like it might be appropriate is the construct_finder_arel method in ActiveRecord::Base.
After digging through Rails source, regardless of Arel being used, find_by_sql method is called on whatever model is performing the find. This can be extended via alias_method_chain as follows:
find_by_sql_with_customization(*args)
results = find_by_sql_without_customization
# do something with results here
results
end
alias_method_chain :find_by_sql, :customization