Scopes

WARNING
This section is a work in progress.
Sometimes you might need to segment your data beyond just a few filters. You might have an User
resource but you frequently need to see all the Active users or Admin users. You can use a filter for that or add a scope.
Generating scopes
bin/rails generate avo:scope admins
# app/avo/scopes/admins.rb
class Avo::Scopes::Admins < Avo::Advanced::Scopes::BaseScope
self.name = "Admins" # Name displayed on the scopes bar
self.description = "Admins only" # This is the tooltip value
self.scope = :admins # valid scope on the model you're using it
self.visible = -> { true } # control the visibility
end
# app/models/user.rb
class User < ApplicationRecord
scope :admins, -> { where role: :admin } # This is used in the scope file above
end
Registering scopes
Because scopes are re-utilizable, you must manually add that scope to a resource using the scope
method inside the scopes
method.
# app/avo/resources/user.rb
class Avo::Resources::User < Avo::BaseResource
def scopes
scope Avo::Scopes::Admins
end
end
-> default
The default
option lets you select a default scope that is applied when you navigate to the resources page.
This option can be configured using a static value or a proc, which is executed using the Avo::ExecutionContext. Check the Execution Context section for more information about what's available in the execution context.
# app/avo/resources/user.rb
class Avo::Resources::User < Avo::BaseResource
def scopes
scope Avo::Scopes::OddId
# EvenId scope is applied as default
scope Avo::Scopes::EvenId, default: true
end
end
# app/avo/resources/user.rb
class Avo::Resources::User < Avo::BaseResource
def scopes
scope Avo::Scopes::OddId
# EvenId scope is applied as default if the current user is an admin
scope Avo::Scopes::EvenId, default: -> { current_user.admin? }
end
end
-> remove_scope_all
If you don't want to have the All
default scope you can remove it by executing the remove_scope_all
method inside scopes
method.
# app/avo/resources/user.rb
class Avo::Resources::User < Avo::BaseResource
def scopes
remove_scope_all
scope Avo::Scopes::Admins
end
end
Options
Execution Context
All options can be configured using static values or procs. The procs are executed using the Avo::ExecutionContext, which provides access to all default methods and attributes available in Avo's execution context. Each option has access to:
query
resource
scope
scoped_query
(check below Performance Note)
Performance Note
Inside each proc, you can call scoped_query
, but use it with caution as it executes the scope. If the scope takes a while to execute, this could impact performance.
-> name
This value is going to be displayed on the scopes bar as the name of the scope.
The scoped_query
method can be used to compute and display the record count. Please see the recipe on how to enable it.
# app/avo/scopes/even_id.rb
class Avo::Scopes::EvenId < Avo::Advanced::Scopes::BaseScope
self.name = "Even"
end
# app/avo/scopes/even_id.rb
class Avo::Scopes::EvenId < Avo::Advanced::Scopes::BaseScope
# Please see the performance note above if you're using `scoped_query`
self.name = -> { "Even (#{scoped_query.count})" }
end
-> description
This value is going to be displayed when the user hovers over the scope.
# app/avo/scopes/even_id.rb
class Avo::Scopes::EvenId < Avo::Advanced::Scopes::BaseScope
self.description = "Only records that have an even ID."
end
# app/avo/scopes/even_id.rb
class Avo::Scopes::EvenId < Avo::Advanced::Scopes::BaseScope
self.description = -> {
"Only #{resource.name.downcase.pluralize} that have an even ID"
}
end
-> scope
The scope you return here is going to be applied to the query of records on that page.
You can use a symbol which will indicate the scope on that model or a proc which will have the query
available so you can apply any modifications you need.
# app/avo/scopes/even_id.rb
class Avo::Scopes::EvenId < Avo::Advanced::Scopes::BaseScope
# This will use the `even_id` scope from the model
self.scope = :even_id
end
# app/avo/scopes/even_id.rb
class Avo::Scopes::EvenId < Avo::Advanced::Scopes::BaseScope
self.scope = -> { query.where("#{resource.model_key}.id % 2 = ?", "0") }
end
-> visible
From this block you can show, hide, and authorize the scope on the resource.
Extra Access
The visible
option has additional access to parent_record
and parent_resource
variables, which are useful when working with nested resources or association contexts.
# app/avo/scopes/even_id.rb
class Avo::Scopes::EvenId < Avo::Advanced::Scopes::BaseScope
# Only show this scope to admins
self.visible = -> { current_user.admin? }
end
Full example
# app/avo/scopes/even_id.rb
class Avo::Scopes::EvenId < Avo::Advanced::Scopes::BaseScope
# Please see the performance note above if you're using `scoped_query`
self.name = -> { "Even (#{scoped_query.count})" }
# This will compute the description based on the resource name
self.description = -> {
"Only #{resource.name.downcase.pluralize} that have an even ID"
}
# This will scope the query to only even IDs
self.scope = -> { query.where("#{resource.model_key}.id % 2 = ?", "0") }
# Only show this scope to admins
self.visible = -> { current_user.admin? }
end