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

Fix count method to work with select statement. #372

Merged
merged 2 commits into from
Jun 19, 2014
Merged

Fix count method to work with select statement. #372

merged 2 commits into from
Jun 19, 2014

Conversation

edariedl
Copy link
Contributor

count method raises ActiveRecord::StatementInvalid if select method is used in Rails 4.1. This commit fixes will paginate and if work if select method is used.

@cyrusstoller
Copy link

+1

3 similar comments
@simonmorley
Copy link

👍

@quek
Copy link

quek commented Apr 18, 2014

👍

@tkuisma
Copy link

tkuisma commented Apr 22, 2014

+1

@frenkel
Copy link

frenkel commented Apr 23, 2014

Works great, thanks!

@ledermann
Copy link

👍

nazgum added a commit to nazgum/will_paginate that referenced this pull request Apr 29, 2014
@O-I
Copy link

O-I commented Apr 29, 2014

Awesome!

@mhenrixon
Copy link

👍

@cyrusstoller
Copy link

I'm guessing test coverage is the reason this hasn't been merged.

@edariedl
Copy link
Contributor Author

edariedl commented May 6, 2014

Yes, it is possible, I had an issue with installing mysql gem, so I cannot run the tests. But it doesn't matter. It looks, that this error was already fixed in ActiveRecord so the fix of will_paginate should not be needed anymore after Rails 4.1.1 release.

From ActiveRecord changelog:

Fixed error for aggregate methods (empty?, any?, count) with select which created invalid SQL.

Fixes #13648.

Simon Woker

@O-I
Copy link

O-I commented May 6, 2014

Can anyone confirm that updating to Rails 4.1.1 fixes this issue? I still get the ActiveRecord::StatementInvalid error after updating.

@edariedl
Copy link
Contributor Author

edariedl commented May 6, 2014

According to blog Rails 4.1.1 is only security fix and includes only code related to security issues. It does not fixes this issue.

@O-I
Copy link

O-I commented May 6, 2014

OK. Thanks for the clarification.

2xmc pushed a commit to 2xmc/will_paginate that referenced this pull request May 13, 2014
fix_count_with_select_statement (mislav#372) (edariedl)
@aperkins81
Copy link

FYI, bug still exists using 4.1.2.rc1 (rails, active_, action_)

@nathany
Copy link
Contributor

nathany commented May 30, 2014

#303 is a cleaner fix for the count method.

There is still an issue with calls to count within will_paginate itself, which need to be count(:all) in Rails 4.1.

@edariedl
Copy link
Contributor Author

Yes, maybe it is a little cleaner, I just took params from rails count() method but it still does not support select statement. And I really don' know if it is cleaner to write everywhere count(:all) or if count itself should handle this. I really have no idea :).

@nathany
Copy link
Contributor

nathany commented May 30, 2014

Yah, I don't know either. :-) Also getting other fun test failures when trying to run specs agains Rails 4.1.1. 😦

@edariedl
Copy link
Contributor Author

Yes I have some issue with installing mysql gem, maybe its because I don't have installed MySQL database. So I even cannot run specs :).

@edariedl
Copy link
Contributor Author

But it's still weird Rails 4.1.1 should be only security fix.

@nathany
Copy link
Contributor

nathany commented May 30, 2014

The Gemfile was locked at 4.0.0rc2, so this is 4.1 in general that the specs aren't running on. Lots of stuff with the fixture. Trying to get it working atm.

@edariedl
Copy link
Contributor Author

Yes, it makes sense, also error fixed in this pull request was created by Rails 4.1.0.

@nathany nathany mentioned this pull request May 30, 2014
@nathany
Copy link
Contributor

nathany commented May 30, 2014

Maybe this commit rails/rails@afd4d82 in Rails 4.1.2 will fix things. rails/rails#13648. I'll try the rc in a minute.

@nathany
Copy link
Contributor

nathany commented May 30, 2014

nope.

@edariedl
Copy link
Contributor Author

I thought, according to change log, it will fix it, but after looking into source code. They just fixed size and any? methods. count will be still broken.

@nathany
Copy link
Contributor

nathany commented May 30, 2014

Maybe total_entries should use size instead of count. I'm not sure. Waiting for @mislav.

@edariedl
Copy link
Contributor Author

IMHO you cannot use size, if you look into method definition:

def size
  loaded? ? @records.length : count(:all)
end

If you have loaded records from database, which is most of the time, if you have pagination on the bottom of the page. It will count only your loaded records, not all of them.

And this is also the reason for redefinition of count method in will_paginate:

def count
  if limit_value
    excluded = [:order, :limit, :offset, :reorder]
    excluded << :includes unless eager_loading?
    rel = self.except(*excluded)
    # TODO: hack. decide whether to keep
    rel = rel.apply_finder_options(@wp_count_options) if defined? @wp_count_options
    rel.count
  else
    super
  end
end

On the third line excluded = [:order, :limit, :offset, :reorder] it defines all methods used by will_paginate and removes it before original count is called. If you use only size, you get back only per_page value almost every time.

@mislav
Copy link
Owner

mislav commented Jun 18, 2014

@edariedl Sorry for the late reply. See my comment in #348 (comment)

This fix looks simple enough, but I will need a test case for two reasons:

  1. A failing test would confirm that this bug exists
  2. The test should pass with this fix on our CI (Rails versions 3.0 – 4.2. alpha)

Otherwise I can't risk breaking will_paginate for older Rails versions.

@mislav mislav added the todo label Jun 18, 2014
@nathany
Copy link
Contributor

nathany commented Jun 18, 2014

Afaik, this is resolved with 0c6d08e

@temochka
Copy link

@nathany no, I don’t think so. It’s basically a problem in ActiveRecord, but it isn’t manageable when using will_paginate (since calls to #count are implicit). Example (ActiveRecord 4.1 & will_paginate 3.0.5):

User.select(:login, :created_at).count
# Mysql2::Error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ' created_at) FROM `users`' at line 1: SELECT COUNT(login, created_at) FROM `users`

# In my code I can call
User.select(:login, :created_at).except(:select).count

# or
User.select(:login, :created_at).count(:login)

# When using will_paginate, I can’t
User.select(:login, :created_at).limit(5).page(2).total_pages
# Mysql2::Error: You have an error in your SQL syntax; check the manual that corresponds ... (same as above)

I checked both 3.0.5 and 0c6d08e.

@nathany
Copy link
Contributor

nathany commented Jun 18, 2014

@temochka Oh. We should probably start with a failing spec like #389. Now that the specs are running/passing with Rails 4.1 (on master), that should be fairly trivial.

@edariedl
Copy link
Contributor Author

@mislav It's ok and I agree that test should be here from the beginning. I add the test and according to CI, everything looks fine for all required versions of rails.

@nathany
Copy link
Contributor

nathany commented Jun 18, 2014

@edariedl Have you merged master to your branch? See #387.

I added a very similar spec at #389, which may not be needed if you get this working. :-D

@edariedl
Copy link
Contributor Author

@nathany Yes, I merged master to the branch. Nice thing to see passing tests and they are broken. I went through all the tests on the Travis CI and everything looks fine, except some deprecations from used libraries.

def select_for_count(rel)
if rel.select_values.present?
select = rel.select_values.join(", ")
select if select !~ /[,*]/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this looks very much like the code removed in rails/rails#10710, which I suppose is as good a solution as any.

@nathany
Copy link
Contributor

nathany commented Jun 18, 2014

Thanks @edariedl. I'm looking forward to the next will_paginate release and Rails 4.1. Whoot!

mislav added a commit that referenced this pull request Jun 19, 2014
Fix count method to work with select statement.
@mislav mislav merged commit 813722f into mislav:master Jun 19, 2014
@mislav
Copy link
Owner

mislav commented Jun 19, 2014

Gonna trust all of your's judgement and go ahead with this. Thanks for the help!

@nathany
Copy link
Contributor

nathany commented Jun 19, 2014

Tomorrow I can give master another try from our app to see if all is well before uploading a new gem. Thanks @mislav.

@nathany
Copy link
Contributor

nathany commented Jun 24, 2014

@mislav All is working well here. When are you planning a new gem release?

@nathany
Copy link
Contributor

nathany commented Jul 2, 2014

@mislav Is this fix included in the "3.0.6" gem release? I'm seeing errors when using total_entries since switching from master to 3.0.6.

@nathany nathany mentioned this pull request Jul 2, 2014
@mislav
Copy link
Owner

mislav commented Jul 4, 2014

@nathany Seems like I forgot to backport this to 3-0-stable, I'm sorry. Cutting a v3.0.7 as we speak

@nathany
Copy link
Contributor

nathany commented Jul 4, 2014

No worries. Thanks @mislav!

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

Successfully merging this pull request may close these issues.