Skip to content

Commit

Permalink
Merge pull request #6 from blocknotes/scopes
Browse files Browse the repository at this point in the history
Scopes
  • Loading branch information
blocknotes authored May 19, 2021
2 parents fab5d02 + 94eace2 commit 69faf0c
Show file tree
Hide file tree
Showing 14 changed files with 91 additions and 25 deletions.
6 changes: 6 additions & 0 deletions .github/workflows/specs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,9 @@ jobs:
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
- name: Run tests
run: bundle exec rake
- name: Archive screenshots for failed tests
uses: actions/upload-artifact@v2
if: failure()
with:
name: test-failed-screenshots
path: spec/dummy/tmp/screenshots
25 changes: 25 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ prepend AdministrateRansack::Searchable
- For associations (_has many_/_belongs to_) the label used can be customized adding an `admin_label` method to the target model which returns a string while the collection can by filtered with `admin_scope`. Example:

```rb
# Sample post model
class Post < ApplicationRecord
scope :admin_scope, -> { where(published: true) }

Expand All @@ -38,6 +39,30 @@ class Post < ApplicationRecord
end
```

- To use scopes in filters it's needed to update also the `ransackable_scopes` in the model, example:

```rb
# Sample post model
class Post < ApplicationRecord
scope :recents, ->(dt = 1.month.ago) { where('dt > ?', dt).order(dt: :desc) }
scope :by_category, ->(category) { where(category: category) }

class << self
def ransackable_scopes(_auth_object = nil)
%i[by_category recents]
end
end
end
```

```erb
<!-- Sample index view -->
<%= render(
'administrate_ransack/filters',
attribute_types: { recents: Administrate::Field::DateTime, by_category: Administrate::Field::String }
) %>
```

## Notes

- Administrate Search logic works independently from Ransack searches, I suggest to disable it eventually (ex. overriding `show_search_bar?` in the controller or removing the bar from the view)
Expand Down
23 changes: 12 additions & 11 deletions app/views/administrate_ransack/_filters.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -30,29 +30,30 @@
<% next if field == :id %>

<% label = attribute_labels.include?(field) ? attribute_labels[field] : field %>
<% model = @ransack_results.klass %>
<% input_type = type.is_a?(Administrate::Field::Deferred) ? type.deferred_class.to_s : type.to_s %>
<div class="filter <%= input_type.parameterize %>">
<% case input_type %>
<% when 'Administrate::Field::BelongsTo' %>
<% association = @ransack_results.klass.reflections[field.to_s] %>
<%= render 'administrate_ransack/components/field_belongs_to', form: f, field: field, label: label, association: association %>
<% association = model.reflections[field.to_s] %>
<%= render 'administrate_ransack/components/field_belongs_to', form: f, model: model, field: field, label: label, association: association %>
<% when 'Administrate::Field::Boolean' %>
<%= render 'administrate_ransack/components/field_boolean', form: f, field: field, label: label %>
<%= render 'administrate_ransack/components/field_boolean', form: f, model: model, field: field, label: label %>
<% when 'Administrate::Field::Date' %>
<%= render 'administrate_ransack/components/field_date', form: f, field: field, label: label %>
<%= render 'administrate_ransack/components/field_date', form: f, model: model, field: field, label: label %>
<% when 'Administrate::Field::DateTime' %>
<%= render 'administrate_ransack/components/field_datetime', form: f, field: field, label: label %>
<%= render 'administrate_ransack/components/field_datetime', form: f, model: model, field: field, label: label %>
<% when 'Administrate::Field::Email', 'Administrate::Field::String', 'Administrate::Field::Text' %>
<%= render 'administrate_ransack/components/field_string', form: f, field: field, label: label %>
<%= render 'administrate_ransack/components/field_string', form: f, model: model, field: field, label: label %>
<% when 'Administrate::Field::Number' %>
<%= render 'administrate_ransack/components/field_number', form: f, field: field, label: label %>
<%= render 'administrate_ransack/components/field_number', form: f, model: model, field: field, label: label %>
<% when 'Administrate::Field::HasMany' %>
<% association = @ransack_results.klass.reflections[field.to_s] %>
<%= render 'administrate_ransack/components/field_has_many', form: f, field: field, label: label, association: association %>
<% association = model.reflections[field.to_s] %>
<%= render 'administrate_ransack/components/field_has_many', form: f, model: model, field: field, label: label, association: association %>
<% when 'Administrate::Field::Select' %>
<%= render 'administrate_ransack/components/field_select', form: f, field: field, label: label, type: type %>
<%= render 'administrate_ransack/components/field_select', form: f, model: model, field: field, label: label, type: type %>
<% else %>
<%= render 'administrate_ransack/components/field_other', form: f, field: field, label: label, type: type %>
<%= render 'administrate_ransack/components/field_other', form: f, model: model, field: field, label: label, type: type %>
<% end %>
</div>
<% end %>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<% if association %>
<% field_key = model.ransackable_scopes.include?(field) ? field : "#{field}_id_eq" %>
<% desc = association.klass.method_defined?(:admin_label) ? :admin_label : :to_s %>
<% collection = association.klass.send(association.klass.respond_to?(:admin_scope) ? :admin_scope : :all) %>
<%= form.label(label) %>
<%= form.collection_select "#{field}_id_eq", collection, :id, desc, include_blank: true %>
<%= form.collection_select(field_key, collection, :id, desc, include_blank: true) %>
<% end %>
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
<% field_key = model.ransackable_scopes.include?(field) ? field : "#{field}_eq" %>
<% values = [[t('administrate_ransack.filters.no'), false], [t('administrate_ransack.filters.yes'), true]] %>
<%= form.label(label) %>
<%= form.select "#{field}_eq", values, include_blank: true %>
<%= form.select(field_key, values, include_blank: true) %>
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
<%= form.label(label) %>
<%= form.date_field "#{field}_gteq" %>
<%= form.date_field "#{field}_lteq" %>
<% if model.ransackable_scopes.include?(field) %>
<%= form.date_field(field) %>
<% else %>
<%= form.date_field("#{field}_gteq") %>
<%= form.date_field("#{field}_lteq") %>
<% end %>
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
<%= form.label(label) %>
<%= form.datetime_field "#{field}_gteq" %>
<%= form.datetime_field "#{field}_lteq" %>
<% if model.ransackable_scopes.include?(field) %>
<%= form.datetime_field(field) %>
<% else %>
<%= form.datetime_field("#{field}_gteq") %>
<%= form.datetime_field("#{field}_lteq") %>
<% end %>
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
<% if association %>
<% field_key = model.ransackable_scopes.include?(field) ? field : "#{field}_id_in" %>
<% desc = association.klass.method_defined?(:admin_label) ? :admin_label : :to_s %>
<% collection = association.klass.send(association.klass.respond_to?(:admin_scope) ? :admin_scope : :all) %>
<%= form.label(label) %>
<%= form.collection_check_boxes "#{field}_id_in", collection, :id, desc do |b| %>
<%= form.collection_check_boxes(field_key, collection, :id, desc) do |b| %>
<%= b.label do %>
<%= b.check_box %>
<span><%= b.object.send(desc) %></span>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
<% field_key = model.ransackable_scopes.include?(field) ? field : "#{field}_eq" %>
<%= form.label(label) %>
<%= form.number_field "#{field}_eq" %>
<%= form.number_field(field_key) %>
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
<% field_key = model.ransackable_scopes.include?(field) ? field : "#{field}_eq" %>
<%= form.label(label) %>
<%= form.select "#{field}_eq", type.options[:collection] || [], include_blank: true %>
<%= form.select(field_key, type.options[:collection] || [], include_blank: true) %>
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
<% field_key = model.ransackable_scopes.include?(field) ? field : "#{field}_cont" %>
<%= form.label(label) %>
<%= form.search_field("#{field}_cont") %>
<%= form.search_field(field_key) %>
6 changes: 3 additions & 3 deletions spec/dummy/app/models/post.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ class Post < ApplicationRecord

validates :title, allow_blank: false, presence: true

scope :published, -> { where(published: true) }
scope :recents, ->(dt = 1.month.ago) { where('created_at > ?', dt).order(created_at: :desc) }
scope :recents, ->(dt = 1.month.ago) { where('dt > ?', dt).order(dt: :desc) }
scope :by_category, ->(category) { where(category: category) }

def to_s
title
Expand All @@ -30,7 +30,7 @@ def upper_title

class << self
def ransackable_scopes(_auth_object = nil)
%i[published recents]
%i[by_category recents]
end
end
end
3 changes: 2 additions & 1 deletion spec/dummy/app/views/admin/posts/index.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@
position: Administrate::Field::Number,
dt: Administrate::Field::Date,
created_at: Administrate::Field::DateTime,
# recents: Administrate::Field::String,
recents: Administrate::Field::DateTime,
by_category: Administrate::Field::String,
tags: Administrate::Field::HasMany
} %>

Expand Down
19 changes: 19 additions & 0 deletions spec/system/scope_filter_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# frozen_string_literal: true

RSpec.describe 'Scope filter', type: :system do
let(:posts) { Post.where(category: 'news') }

it 'filters the posts by category (using the scope)' do
visit '/admin/posts'

fill_in('q[by_category]', with: 'news')
find('input[type="submit"]').click

expect(page).to have_current_path %r{/admin/posts\?.+q%5Bby_category%5D=news.*}
expect(posts.count).to be_positive
expect(page).to have_css('.js-table-row', count: posts.count)
posts.each do |post|
expect(page).to have_css('.js-table-row a.action-show', text: post.title)
end
end
end

0 comments on commit 69faf0c

Please sign in to comment.