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

Is there support for sorting not by columns but custom scopes? #100

Closed
pavolzbell opened this issue May 22, 2012 · 29 comments
Closed

Is there support for sorting not by columns but custom scopes? #100

pavolzbell opened this issue May 22, 2012 · 29 comments

Comments

@pavolzbell
Copy link

Is there support for sorting not by columns but custom scopes like it was in meta search? Is such feature planned to be implemented in the future?

I mean something like this (works in meta search), in model:

scope :sort_by_custom_name_asc, order('custom_name ASC')
scope :sort_by_custom_name_desc, order('custom_name DESC')

And then in view:

sort_link @search, :custom_name

I am asking because I would like to sort results by more than one column, I mean I have records not containing unique values in some columns and then I must sort these records by other columns to maintain consistency in the view, for example:

scope :sort_by_custom_name_asc, order('col_1 ASC, col_2 DESC, col_3 ASC')
@ghost
Copy link

ghost commented Oct 26, 2012

+1

@radar
Copy link
Contributor

radar commented Oct 26, 2012

Please don't +1 issues.

@aditya-mandal
Copy link

is sorting on custom scopes is implemented in ranscack. I'm facing same issue with sorting using custom scopes

@gamov
Copy link

gamov commented May 20, 2013

mmm, that's another feature of metasearch I'm using extensively making it hard to migrate to ransack...

@aditya-mandal
Copy link

ok.. so is it possible to use both metasearch and ransack gems simultaneously, or i will have to move to metasearch instead?
i.e for sorting scopes can i use meta_search and ranscak for remaining??

@mensfeld
Copy link

yeah - good question. Will this be in ransack?

@intelcommercedev
Copy link

You can use my simple hack to support custom search scopes like meta_search. I really spent 10min to do it, so it's dirty.

https://gist.github.com/intelcommercedev/5176f6b53b4b74a64132

@jonatack
Copy link
Contributor

I think this feature was added with PR #390. Please correct me if wrong. Am closing this for now.

@medius
Copy link

medius commented Feb 21, 2015

How does sorting on a custom attribute work with this change? Can you please give an example, especially when the attribute is from a nested joined table?

scope :sort_by_custom_name_asc, joins(:something).order('something.custom_name ASC')
scope :sort_by_custom_name_desc, joins(:something).order('something.custom_name DESC')

What should be the name of the scope? Should ransortable_attributes include custom_name?

I'm not able to make it work and looks like this PR mostly address the search part and not sorting.

@JoshuaNovak919
Copy link

Anyone ever get custom sorts working?

@tanelj
Copy link

tanelj commented Oct 29, 2015

Hi!

One way to solve it with ransackable_scopes:

class People < ActiveRecord::Base
  scope :sorted, -> { order(:name) }
  scope :person_age_gteq, lambda { |age| where('((YEAR(CURDATE()) - YEAR(people.birth_date)) - (RIGHT(CURDATE(),5) < RIGHT(people.birth_date,5))) >= ?', age) }

  class << self
    def ransackable_scopes(auth_object = nil)
      %w(sorted person_age_gteq)
    end
  end
end

See also: #390 (comment)

@JoshuaNovak919
Copy link

@tanelj I am using ransackable_scopes, but how can I get asc and desc sorting to work on the scope?

@tanelj
Copy link

tanelj commented Oct 29, 2015

Sorry about misreading.

For custom sorting you should use ransortable_attributes

class Person < ActiveRecord::Base
  belongs_to :company

  scope :sorted, -> { order(:name) }
  scope :person_age_gteq, lambda { |age| where('((YEAR(CURDATE()) - YEAR(people.birth_date)) - (RIGHT(CURDATE(),5) < RIGHT(people.birth_date,5))) >= ?', age) }
  scope :sort_by_company_name_asc, -> { order('companies.status').joins('LEFT OUTER JOIN companies ON people.company_id = companies.id') }
  scope :sort_by_company_name_desc, -> { order('companies.status DESC')joins('LEFT OUTER JOIN companies ON people.company_id = companies.id') }

  class << self
    def ransackable_scopes(auth_object = nil)
      %w(sorted person_age_gteq)
    end

    def ransortable_attributes(auth_object = nil)
      ransackable_attributes(auth_object) + %w(
        sort_by_company_name_asc sort_by_company_name_desc
      )
  end
end

And in views:

sort_link(@search, :company_name, 'Company name')

@JoshuaNovak919
Copy link

@tanelj Is there a particular version of Ransack required for this to work? I tried what you said and it doesn't seem to do anything.

@JoshuaNovak919
Copy link

@tanelj I think your example just works by default since ransack can search nested attributes normally.

@tanelj
Copy link

tanelj commented Oct 29, 2015

@JoshuaNovak919 - yes, my project is using older version v1.6.6.

@alehmann
Copy link

alehmann commented Nov 6, 2015

@JoshuaNovak919 Using the initializer written by @intelcommercedev I got the sorting by custom scopes working.

I just forked the GIST for wrapping it into the right modules / classes and adding usage instructions: https://gist.github.com/alehmann/02908a12866e4a193dde

@denniscastro
Copy link

@alehmann +1

@laserlemon
Copy link
Contributor

I ran into this same issue and solved it just a bit differently. It seems the Gist solution put forth by @intelcommercedev and @alehmann doesn't play nice with a combination of both column sorts and custom scope sorts. Here's my stab at it, which should work with both and preserve priority when multiple scopes are present.

https://gist.github.com/laserlemon/e5ce4e0d8bac63f4aa6835605ce3ec21

Hope it helps, and thank you for all your hard work on this!

@drborges
Copy link
Contributor

drborges commented Feb 8, 2017

@jonatack it seems that #390 adds support for ActiveRecord scopes only for ransackable_scopes list. Was it considered to support custom scopes on ransortable_attributes as well?

The solution provided by @laserlemon seems to work fine for my use case.

@mensfeld
Copy link

@drborges @jonatack did you solve it to work with ransortable_attributes?

@scarroll32
Copy link
Member

Hey @laserlemon this would be a great contribution to the Wiki.

@drborges
Copy link
Contributor

drborges commented Oct 9, 2017

@mensfeld yes, I was able to get it to work for what I needed, I had to create a few AR scopes to achieve the desired behavior, though. Something like:

scope :sort_by_approval_rate, ->(dir: "ASC") { order("(approved_amount / applied_amount) #{dir}") }
scope :sort_by_approval_rate_asc, -> { sort_by_approval_rate }
scope :sort_by_approval_rate_desc, -> { sort_by_approval_rate dir: "DESC" }

class << self
    # Add sorting scopes to Ransack for approval_rate computed column
    #
    def ransortable_attributes(auth_object = nil)
      super(auth_object) + [
        :sort_by_approval_rate_asc,
        :sort_by_approval_rate_desc,
      ]
    end
end

@mensfeld
Copy link

mensfeld commented Oct 9, 2017

@drborges thanks. Did the same :)

@LucasKuhn
Copy link

@drborges Did you use a sort_link in the view? If so, how does it look? Thanks!

@drborges
Copy link
Contributor

I did not @LucasKuhn :/

The view has an in-house backed solution on top of Ransack. Though, if my memory does not fail me, in my case if I were to use sort_link it would look something like:

sort_link @search, :approval_rate

Where approval_rate is the custom/dynamic field created by the scopes in my example above. It's been awhile since I last worked with Ransack, but I hope that puts you in a good direction.

@RailsCod3rFuture
Copy link

I'm having an issue with my code. I'm simply trying to get the count of the records that match the wage range. What I have so far is written below. When I use your method in view, it doesn't show the number. Just a hyperlink.

scope :count_jobs_with_salaries_between_20k_29k, -> {where(hourly_wage_salary: 20000..29000).count}

 ransacker :salary_between_20k_and_29k do
    Arel.sql('jobs.hourly_wage_salary BETWEEN 20000 AND 29000')
  end

<li><%= sort_link(@q, :salary_between_20k_and_29k,'$20,000-$29,000', default_order: :desc) %> <%= sort_link(@q, :hourly_wage_salary) %> </li>

def self.ransortable_attributes(auth_object = nil)
   ransortable_attributes(auth_object) + %w(count_jobs_with_salaries_between_20k_29k)
 end

How do I get the consistency and count that I need for the records?

@RailsCod3rFuture
Copy link

I just received a seriously long deep stack error after using the ransortable_attributes method. Is there any other way to count the records for the ranges?

@benlangfeld
Copy link

Full support is implemented in #973

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

No branches or pull requests