Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RuboCop default_scope format #1895

Closed
sescobb27 opened this issue May 15, 2015 · 14 comments
Closed

RuboCop default_scope format #1895

sescobb27 opened this issue May 15, 2015 · 14 comments

Comments

@sescobb27
Copy link

Hi I'm working with MongoId but I'm having some issues with the recommended format. how can I
fixed, or is MongoId's problem?, thanks

class Plan
  include Mongoid::Document
  # When I run rubocop it says default_scope expects a block as its sole argument. BUT works
  # line 17
  default_scope -> { where(status: true).asc(:price) }
  # but if instead I use the recommended way an exception is raised:
  # default_scope: wrong number of arguments (0 for 1) (ArgumentError)
  default_scope { where(status: true).asc(:price) }
end

here is my stack trace

/home/kiro/.rvm/gems/ruby-2.2.2/gems/mongoid-4.0.2/lib/mongoid/scopable.rb:90:in `default_scope': wrong number of arguments (0 for 1) (ArgumentError)
    from /home/kiro/Documents/Rails/festinare_api/app/models/plan.rb:17:in `<class:Plan>'
    from /home/kiro/Documents/Rails/festinare_api/app/models/plan.rb:1:in `<top (required)>'
    from /home/kiro/.rvm/gems/ruby-2.2.2/gems/activesupport-4.2.0/lib/active_support/dependencies.rb:274:in `require'
    from /home/kiro/.rvm/gems/ruby-2.2.2/gems/activesupport-4.2.0/lib/active_support/dependencies.rb:274:in `block in require'
    from /home/kiro/.rvm/gems/ruby-2.2.2/gems/activesupport-4.2.0/lib/active_support/dependencies.rb:240:in `load_dependency'
    from /home/kiro/.rvm/gems/ruby-2.2.2/gems/activesupport-4.2.0/lib/active_support/dependencies.rb:274:in `require'
    from /home/kiro/.rvm/gems/ruby-2.2.2/gems/activesupport-4.2.0/lib/active_support/dependencies.rb:360:in `require_or_load'
    from /home/kiro/.rvm/gems/ruby-2.2.2/gems/activesupport-4.2.0/lib/active_support/dependencies.rb:494:in `load_missing_constant'
    from /home/kiro/.rvm/gems/ruby-2.2.2/gems/activesupport-4.2.0/lib/active_support/dependencies.rb:184:in `const_missing'
    from /home/kiro/Documents/Rails/festinare_api/db/seeds.rb:71:in `<top (required)>'
    from /home/kiro/.rvm/gems/ruby-2.2.2/gems/activesupport-4.2.0/lib/active_support/dependencies.rb:268:in `load'
    from /home/kiro/.rvm/gems/ruby-2.2.2/gems/activesupport-4.2.0/lib/active_support/dependencies.rb:268:in `block in load'
    from /home/kiro/.rvm/gems/ruby-2.2.2/gems/activesupport-4.2.0/lib/active_support/dependencies.rb:240:in `load_dependency'
    from /home/kiro/.rvm/gems/ruby-2.2.2/gems/activesupport-4.2.0/lib/active_support/dependencies.rb:268:in `load'
    from /home/kiro/.rvm/gems/ruby-2.2.2/gems/railties-4.2.0/lib/rails/engine.rb:547:in `load_seed'
    from /home/kiro/Documents/Rails/festinare_api/spec/rails_helper.rb:30:in `block in <top (required)>'
    from /home/kiro/.rvm/gems/ruby-2.2.2/gems/rspec-core-3.2.3/lib/rspec/core.rb:101:in `configure'
    from /home/kiro/Documents/Rails/festinare_api/spec/rails_helper.rb:24:in `<top (required)>'
    from /home/kiro/Documents/Rails/festinare_api/spec/controllers/api/v1/clients_controller_spec.rb:1:in `require'
    from /home/kiro/Documents/Rails/festinare_api/spec/controllers/api/v1/clients_controller_spec.rb:1:in `<top (required)>'
    from /home/kiro/.rvm/gems/ruby-2.2.2/gems/rspec-core-3.2.3/lib/rspec/core/configuration.rb:1226:in `load'
    from /home/kiro/.rvm/gems/ruby-2.2.2/gems/rspec-core-3.2.3/lib/rspec/core/configuration.rb:1226:in `block in load_spec_files'
    from /home/kiro/.rvm/gems/ruby-2.2.2/gems/rspec-core-3.2.3/lib/rspec/core/configuration.rb:1224:in `each'
    from /home/kiro/.rvm/gems/ruby-2.2.2/gems/rspec-core-3.2.3/lib/rspec/core/configuration.rb:1224:in `load_spec_files'
    from /home/kiro/.rvm/gems/ruby-2.2.2/gems/rspec-core-3.2.3/lib/rspec/core/runner.rb:97:in `setup'
    from /home/kiro/.rvm/gems/ruby-2.2.2/gems/rspec-core-3.2.3/lib/rspec/core/runner.rb:85:in `run'
    from /home/kiro/.rvm/gems/ruby-2.2.2/gems/rspec-core-3.2.3/lib/rspec/core/runner.rb:67:in `rescue in run'
    from /home/kiro/.rvm/gems/ruby-2.2.2/gems/rspec-core-3.2.3/lib/rspec/core/runner.rb:63:in `run'
    from /home/kiro/.rvm/gems/ruby-2.2.2/gems/rspec-core-3.2.3/lib/rspec/core/runner.rb:38:in `invoke'
    from /home/kiro/.rvm/gems/ruby-2.2.2/gems/rspec-core-3.2.3/exe/rspec:4:in `<top (required)>'
    from /home/kiro/.rvm/gems/ruby-2.2.2/bin/rspec:23:in `load'
    from /home/kiro/.rvm/gems/ruby-2.2.2/bin/rspec:23:in `<main>'
    from /home/kiro/.rvm/gems/ruby-2.2.2/bin/ruby_executable_hooks:15:in `eval'
    from /home/kiro/.rvm/gems/ruby-2.2.2/bin/ruby_executable_hooks:15:in `<main>'
@bbatsov
Copy link
Collaborator

bbatsov commented May 16, 2015

To be honest I didn't factor Mongoid at all in this check. All the Rails cops that are model-related assume you're using ActiveRecord.

@DMA57361
Copy link

DMA57361 commented Aug 5, 2015

I'm using ActiveRecord and was coming here to ask if the cop is working correctly, I'll add this here instead of opening a new issue.

While working through our TODO's I've activated this cop on a app with several default_scopes in an app and it resulted in several offences - telling me default_scope requires a block instead of a lambda. As far as I can tell these scopes have been working for some time problem free, and switching between lambda and block seems to make no obvious difference.

According to the docs (http://api.rubyonrails.org/classes/ActiveRecord/Scoping/Default/ClassMethods.html#method-i-default_scope):

(You can also pass any object which responds to call to the default_scope macro, and it will be called when building the default scope.)

So I wonder if this is a cop that's targeting an older version of Rails?
Or if there's another reason we should prefer block over lambda that I'm missing?

@alexdowad
Copy link
Contributor

@DMA57361 I think it's just a bit more concise to use a block. RC is a style checker. Naturally, code which fails its style checks may still "work".

@DMA57361
Copy link

@alexdowad I think it's less that a style warning is working code that's a problem (it clearly isn't), but more that the cop states "default_scope expects a block as its sole argument", which is inaccurate - especially in the case originally raised, where that does not even work.

If I have a scope that needs to be evaluated at call-time instead of load-time (some comparison to Time.now, for example) a lambda is required to get the expected behaviour. I assume the same is true of default_scope (although, frankly, I haven't checked right now), if this is the case then pushing people to change away from lambda's might cause unexpected behavioural changes.

@bbatsov
Copy link
Collaborator

bbatsov commented Dec 26, 2015

Guess this was the case when I wrote the cop. It might not be relevant anymore. I don't do much Rails programming these days.

@alexdowad
Copy link
Contributor

@DMA57361 Thanks for further explanation. Can you suggest how this cop should be adjusted? Or do you think it should simply be removed?

@DMA57361
Copy link

I can only comment in terms of ActiveRecord, when used in Rails 4.1 and 4.2 (2 most recent big releases)

I'd make Rubocop suggest the use of lambdas as the recommended usage for both default_scope and scope. The first is the opposite of the current Rails/DefaultScope, and I think Rails/ScopeArgs does the latter already.

(I've roughly said this already, but to keep it together:) This is to avoid unexpected behaviour of the block versions being evaluated at load-time instead of call-time. For example, a scope of where('timestamp > ?', Time.now) - if used in a block this ends up getting locked to the same timestamp for every query until the server/worker is restarted (or class is reloaded in dev - making this easy to miss!), while when used with a lambda Time.now is the time the scope gets constructed into a query.

@bbatsov
Copy link
Collaborator

bbatsov commented Dec 27, 2015

Maybe those cops should simply be dropped. In general I regret introducing the Rails cops, as they are pretty unreliable and susceptible to changes in Rails. Ideally they should be spun into a separate gem, but I'd be fine with simply deleting them...

@scottmatthewman
Copy link
Contributor

I'd be sad if the Rails cops were dropped altogether, as we use them in our
team to help keep everyone to the same style, or at least talking about
style from a consistent viewpoint. However, I can see the benefit of
transferring them to a separate gem, e.g. "rubocop-rails", in the style of
rubocop-rspec.

Hiving them off to a separate gem might make it easier to keep up to date
with changes to Rails as well.
On Sun, 27 Dec 2015 at 00:04, Bozhidar Batsov [email protected]
wrote:

Maybe those cops should simply be dropped. In general I regret introducing
the Rails cops, as they are pretty unreliable and susceptible to changes in
Rails. Ideally they should be spun into a separate gem, but I'd be fine
with simply deleting them...


Reply to this email directly or view it on GitHub
#1895 (comment).

@alexdowad
Copy link
Contributor

The Rails cops are definitely going into another gem. However, the question still remains of what to do with Rails/DefaultScope.

It's been a long time since I developed Rails code. So I had to refresh my memory on how default_scope works.

There are 3 forms:

default_scope where(a: 1)
default_scope { where(a: 1) }
default_scope -> { where(a: 1) }

I don't see any reason to enforce the use of any one of these forms. Rails programmers on a team can pick whichever style seems more appropriate at each call site. (As @DMA57361 pointed out, whether or not they want to re-evaluate the arguments every time will affect their choice.)

I recommend that this cop can be dropped, but the other Rails cops be retained until we are ready to split them off.

@bbatsov
Copy link
Collaborator

bbatsov commented Dec 31, 2015

I'm fine with killing it.

@bbatsov
Copy link
Collaborator

bbatsov commented Dec 31, 2015

P.S. For me the usage of default_scope has always been a bad idea.

@alexdowad
Copy link
Contributor

Pushing a fix.

@bbatsov
Copy link
Collaborator

bbatsov commented Dec 31, 2015

Btw, it seems this cop was introduced because of a change from Rails 3 to Rails 4 http://stackoverflow.com/questions/18506038/rails-4-default-scope

Unfortunately my memory is a bit fuzzy.

alexdowad added a commit to alexdowad/rubocop that referenced this issue Jan 1, 2016
Active Record's `default_scope` method can be used in 3 ways:

    default_scope where(a: 1)
    default_scope { where(a: 1) }
    default_scope -> { where(a: 1) }

The `DefaultScope` cop enforced the use of the 2nd form. This is unnecessary,
and causes problems, since in some situations only the 3rd form will do.
(To be specific, in cases where the arguments must be re-evaluated every time
records are retrieved using the default scope, only the 3rd form will work.)

Therefore, remove this cop.
@bbatsov bbatsov closed this as completed in b96397a Jan 3, 2016
nickcharlton added a commit to thoughtbot/guides that referenced this issue Feb 13, 2016
jferris added a commit to thoughtbot/guides that referenced this issue Apr 18, 2016
The DefaultScope cop was removed:

rubocop/rubocop#1895

The TrailingComma cop was split into two:

rubocop/rubocop@a0719f9
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants