class RuboCop::Cop::Rails::WhereExists
This cop enforces consistent style when using `exists?`.
Two styles are supported for this cop. When EnforcedStyle is 'exists' then the cop enforces `exists?(…)` over `where(…).exists?`.
When EnforcedStyle is 'where' then the cop enforces `where(…).exists?` over `exists?(…)`.
This cop is unsafe for auto-correction because the behavior may change on the following case:
- source,ruby
Author.includes(:articles).where(articles: {id: id}).exists? #=> Perform `eager_load` behavior (`LEFT JOIN` query) and get result.
Author.includes(:articles).exists?(articles: {id: id}) #=> Perform `preload` behavior and `ActiveRecord::StatementInvalid` error occurs.
@example EnforcedStyle: exists (default)
# bad User.where(name: 'john').exists? User.where(['name = ?', 'john']).exists? User.where('name = ?', 'john').exists? user.posts.where(published: true).exists? # good User.exists?(name: 'john') User.where('length(name) > 10').exists? user.posts.exists?(published: true)
@example EnforcedStyle: where
# bad User.exists?(name: 'john') User.exists?(['name = ?', 'john']) User.exists?('name = ?', 'john') user.posts.exists?(published: true) # good User.where(name: 'john').exists? User.where(['name = ?', 'john']).exists? User.where('name = ?', 'john').exists? user.posts.where(published: true).exists? User.where('length(name) > 10').exists?
Constants
- MSG
- RESTRICT_ON_SEND
Public Instance Methods
on_send(node)
click to toggle source
# File lib/rubocop/cop/rails/where_exists.rb, line 65 def on_send(node) find_offenses(node) do |args| return unless convertable_args?(args) range = correction_range(node) good_method = build_good_method(args) message = format(MSG, good_method: good_method, bad_method: range.source) add_offense(range, message: message) do |corrector| corrector.replace(range, good_method) end end end
Private Instance Methods
build_good_method(args)
click to toggle source
# File lib/rubocop/cop/rails/where_exists.rb, line 111 def build_good_method(args) if exists_style? build_good_method_exists(args) elsif where_style? build_good_method_where(args) end end
build_good_method_exists(args)
click to toggle source
# File lib/rubocop/cop/rails/where_exists.rb, line 119 def build_good_method_exists(args) if args.size > 1 "exists?([#{args.map(&:source).join(', ')}])" else "exists?(#{args[0].source})" end end
build_good_method_where(args)
click to toggle source
# File lib/rubocop/cop/rails/where_exists.rb, line 127 def build_good_method_where(args) if args.size > 1 "where(#{args.map(&:source).join(', ')}).exists?" else "where(#{args[0].source}).exists?" end end
convertable_args?(args)
click to toggle source
# File lib/rubocop/cop/rails/where_exists.rb, line 97 def convertable_args?(args) return false if args.empty? args.size > 1 || args[0].hash_type? || args[0].array_type? end
correction_range(node)
click to toggle source
# File lib/rubocop/cop/rails/where_exists.rb, line 103 def correction_range(node) if exists_style? node.receiver.loc.selector.join(node.loc.selector) elsif where_style? node.loc.selector.with(end_pos: node.loc.expression.end_pos) end end
exists_style?()
click to toggle source
# File lib/rubocop/cop/rails/where_exists.rb, line 85 def exists_style? style == :exists end
find_offenses(node, &block)
click to toggle source
# File lib/rubocop/cop/rails/where_exists.rb, line 89 def find_offenses(node, &block) if exists_style? where_exists_call?(node, &block) elsif where_style? exists_with_args?(node, &block) end end
where_style?()
click to toggle source
# File lib/rubocop/cop/rails/where_exists.rb, line 81 def where_style? style == :where end