alekseyl / rails_select_on_includes Goto Github PK
View Code? Open in Web Editor NEWLicense: MIT License
License: MIT License
Hi, I have to use outer join, group_concat and group by in my query, and I think that this patch does not work with that currently.
My query is something like:
post = Post.includes(:comments).references(:tags)
.select("posts.*, group_concat(distinct tags.name) as tags")
.where( SOME_CONDITION )
.group_by('posts.id')
I tried to use this gem, but I still get undefined method for "post.tags"
Could you please check this case if it's a valid issue? Thanks!
I use rails_select_on_includes gem on Rails 6 and raise NoMethodError (undefined method 'testval' for nil:NilClass)
when I did these commands:
irb(main):001:0> Post.create(title: 'title', body: 'body')
irb(main):002:0> post = Post.includes(:comments).select("posts.*, 1 as testval").where(id: [1,2]).first
(1.1ms) SELECT sqlite_version(*)
Post Load (0.2ms) SELECT posts.*, 1 as testval FROM "posts" WHERE "posts"."id" IN (?, ?) ORDER BY "posts"."id" ASC LIMIT ? [["id", 1], ["id", 2], ["LIMIT", 1]]
Comment Load (0.1ms) SELECT "comments".* FROM "comments" WHERE "comments"."post_id" = ? [["post_id", 1]]
=> #<Post id: 1, title: "title", body: "body", created_at: "2019-09-03 08:52:17", updated_at: "2019-09-03 08:52:17">
irb(main):003:0> post.comments.first.testval
Traceback (most recent call last):
1: from (irb):2
NoMethodError (undefined method `testval' for nil:NilClass)
Do you support Rails6?
If you want to try to check, I created sample app:
https://github.com/ikepon/sample_app_for_rails6
And try these commands:
git clone [email protected]:ikepon/sample_app_for_rails6.git
cd sample_app_for_rails6
bundle
bin/rails db:create db:migrate
yarn install --check-files
bin/rails c
and do these commands on rails console:
Post.create(title: 'title', body: 'body')
post = Post.includes(:comments).select("posts.*, 1 as testval").where(id: [1,2]).first
post.comments.first.testval
Just getting around to upgrading to Rails5 (and eventually, rails6) and upgraded to Rails 5.2.42 and rails_select_on_includes 5.2.1 (which appears to be the latest).
We used this amazing gem under Rails4 for over 40% of our model querying (we have a lot of postgresql DB functions) and it always worked great.
With the current rails/gem version, when I add a virtual attribute for a non-joined/eager-loaded query, the virtual attributes are created as normal. As soon as I add a eager_load to the join, the virtual attributes are not available on the primary model (i.e everything acts like before select_on_includes was present).
Is it possible some post rails 5.2.1 change broke this?
At the moment, we cannot go to Rails 6 as a number of the gems we depend on have not yet been updated for it.
When running gem againts Rails 6.1.1, I get the following error and stack trace:
ArgumentError at XXX
wrong number of arguments (given 5, expected 6)
construct
activerecord (6.1.1) lib/active_record/associations/join_dependency.rb, line 238
block (2 levels) in instantiate
rails_select_on_includes (6.0.1) lib/rails_select_on_includes.rb, line 104
block in each
activerecord (6.1.1) lib/active_record/result.rb, line 62
each
activerecord (6.1.1) lib/active_record/result.rb, line 62
each
activerecord (6.1.1) lib/active_record/result.rb, line 62
block in instantiate
rails_select_on_includes (6.0.1) lib/rails_select_on_includes.rb, line 96
instrument
activesupport (6.1.1) lib/active_support/notifications/instrumenter.rb, line 24
instantiate
rails_select_on_includes (6.0.1) lib/rails_select_on_includes.rb, line 95
block (2 levels) in exec_queries
rails_select_on_includes (6.0.1) lib/rails_select_on_includes.rb, line 130
apply_join_dependency
activerecord (6.1.1) lib/active_record/relation/finder_methods.rb, line 421
block in exec_queries
rails_select_on_includes (6.0.1) lib/rails_select_on_includes.rb, line 120
skip_query_cache_if_necessary
activerecord (6.1.1) lib/active_record/relation.rb, line 868
exec_queries
rails_select_on_includes (6.0.1) lib/rails_select_on_includes.rb, line 117
load
activerecord (6.1.1) lib/active_record/relation.rb, line 638
records
activerecord (6.1.1) lib/active_record/relation.rb, line 249
to_ary
activerecord (6.1.1) lib/active_record/relation.rb, line 244
The line is:
def construct(ar_parent, parent, row, seen, model_cache, strict_loading_value)
return if ar_parent.nil?
I'm talking about
As of now expressions like
@stuff = Mymodel.join(my_arel.join_sources)
.select('some.stuff,
other.stuff')
are broken if there is no space after some.stuff,
.
Not sure if it is related to this gem or it's rails fault. I'm getting different results when I use eager_load
String, Fixnum and Booleans are ok:
Post.eager_load(:comments).select("posts.*, 1 as testval").first.testval.class
# Fixnum
Post.eager_load(:comments).select("posts.*, 'test' as testval").first.testval.class
# String
Post.eager_load(:comments).select("posts.*, true as testval").first.testval.class
# TrueClass
But on other types are converted to String:
Post.select("posts.*, .1 as testval").first.testval.class
# BigDecimal
Post.eager_load(:comments).select("posts.*, .1 as testval").first.testval.class
# String
Post.select("posts.*, ARRAY['Ruby'] as testval").first.testval.class
# Array
Post.eager_load(:comments).select("posts.*, ARRAY['Ruby'] as testval").first.testval.class
# String
Post.select("posts.*, '2017-02-07 12:00:00'::timestamp as testval").first.testval.class
# Time
Post.eager_load(:comments).select("posts.*, '2017-02-07 12:00:00'::timestamp as testval").first.testval.class
# String
Any thoughts on what is causing this?
It would be useful for us to be able to provide subqueries alias as virtual attributes :
Like in :
select(
'"devices".*',
activations.where(activations[:type].eq('Activation'))
.where(activations[:device_id].eq(Device.arel_table[:id]))
.project(Arel.star.count)
.as('activations_count')
)
The required change to make it work is to handle Arel::Nodes::TableAlias here :
def update_aliases_to_select_values( select_values )
return if select_values.blank?
select_values.each do |sv|
# if sv is symbol that we assume that its a base table column and it will be aliased and added as usual
# all we need is some specials joins+select from related tables
case sv
when String
sv.split( ", " ).each do |sub_sv|
if sub_sv[/.+ as .+/i]
add_virtual_attribute(sub_sv.rpartition(/ as /i).last.strip)
elsif sub_sv[/.+\.[^\*]+/]
add_virtual_attribute(sub_sv[/\..+/][1..-1].strip)
end
end
when Arel::Nodes::As
add_virtual_attribute(sv.right)
when Arel::Nodes::TableAlias # Added
add_virtual_attribute(sv.right) # Added
when Arel::Nodes::Function
add_virtual_attribute(sv.alias) if sv.alias.present?
end
end
end
# OK
post = Post.includes(:comments).select('"posts".*, "comments"."something" as something, 1 as testval').where( SOME_CONDITION ).first
post.something # something
post.testval # 1
# quotes, or omitting the "as"
post = Post.includes(:comments).select('"posts".*, "comments"."something", 1 testval').where( SOME_CONDITION ).first
post.something # Undefined method!
post.testval # Undefined method!
post.attributes.keys # [..., "\"something\""] # quoted???
By the SQL standard, keywords such as AS
are case-insensitive. However, rails_select_on_includes
seems to be case sensitive:
> User.includes(:comments).order("comments.updated_at").select("1 as testval").first.testval
=> 1
> User.includes(:comments).order("comments.updated_at").select("1 AS testval").first.testval
NoMethodError: undefined method `testval' for #<User:0x0055b293b6bb60>
Any plans to provide Rails 5 support for this gem? It solved the problem on Rails 4, but when trying to switch into Rails 5.1.0, it gives following error:
An ActiveRecord::StatementInvalid occurred in modelname#search:
PG::IndeterminateDatatype: ERROR: could not determine data type of parameter $4
Any help would be appreciated.
Rails 5.1.4 worked just fine. I'm currently trying to track down the changes. It seems like 5.1.5 is calling instance.arel
where 5.1.4 didn't.
subj
If the select
contains multiple instances of the keyword AS
, mapping of attributes fails.
> User.includes(:comments).where(id: 1).order("comments.updated_at").select("(SELECT COUNT(*) FROM replies AS r WHERE r.user_id = users.id) AS reply_count").first.attributes
=> {"id"=>1, "email"=>"[email protected]", "r WHERE r.user_id = users.id) as reply_count"=>nil}
Subqueries without AS
work fine.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.