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')
+1
Please don't +1 issues.
is sorting on custom scopes is implemented in ranscack. I'm facing same issue with sorting using custom scopes
mmm, that's another feature of metasearch I'm using extensively making it hard to migrate to ransack...
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??
yeah - good question. Will this be in ransack?
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
I think this feature was added with PR #390. Please correct me if wrong. Am closing this for now.
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.
Anyone ever get custom sorts working?
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: https://github.com/activerecord-hackery/ransack/pull/390#issuecomment-48338916
@tanelj I am using ransackable_scopes, but how can I get asc and desc sorting to work on the scope?
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')
@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.
@tanelj I think your example just works by default since ransack can search nested attributes normally.
@JoshuaNovak919 - yes, my project is using older version v1.6.6.
@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
@alehmann +1
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!
@jonatack it seems that https://github.com/activerecord-hackery/ransack/pull/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.
@drborges @jonatack did you solve it to work with ransortable_attributes?
Hey @laserlemon this would be a great contribution to the Wiki.
@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
@drborges thanks. Did the same :)
@drborges Did you use a sort_link in the view? If so, how does it look? Thanks!
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.
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?
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?
Full support is implemented in https://github.com/activerecord-hackery/ransack/pull/973
Most helpful comment
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!