Has Many
By default, the HasMany
field is visible only on the Show
view. You will see a new panel with the model's associated records below the regular fields panel.
field :projects, as: :has_many
Options
-> searchable
Turns the attach field/modal from a select
input to a searchable experience
class Avo::Resources::CourseLink < Avo::BaseResource
def fields
field :links,
as: :has_many,
searchable: true
end
end
WARNING
Avo uses the search feature behind the scenes, so make sure the target resource has the search_query
option configured.
# app/avo/resources/course_link.rb
class Avo::Resources::CourseLink < Avo::BaseResource
self.search = {
query: -> {
query.ransack(id_eq: params[:q], link_cont: params[:q], m: "or").result(distinct: false)
}
}
end
Default
false
Possible values
true
, false
-> attach_scope
Default
nil
Possible values
field :user,
as: :belongs_to,
attach_scope: -> { query.non_admins }
Pass in a block where you attach scopes to the query
object and parent
object, which is the actual record where you want to assign the association. The block is executed in the ExecutionContext
.
WARNING
The attach_scope
will not filter the records in the listing from has_many
or has_and_belongs_to_many
associations. Use scope
or a Pundit policy Scope
for that.
field :members,
as: :has_many,
attach_scope: -> { query.where.not(team_id: parent.id) }
In this example, in the attach_scope
, we ensure that when attaching members to a team, only those who are not already members will appear in the list of options.
-> scope
Default
nil
Possible values
field :user,
as: :belongs_to,
scope: -> { query.approved }
Pass in a block where you attach scopes to the query
object. The block gets executed in the ExecutionContext
.
With version 2.5.0, you'll also have access to the parent
record so that you can use that to scope your associated models even better.
Starting with version 3.12, access to resource
and parent_resource
was additionally provided.
-> description
-> use_resource
Default
nil
. When nothing is selected, Avo infers the resource type from the reflected association.
Possible values
Avo::Resources::Post
, Avo::Resources::PhotoComment
, or any Avo resource class.
The value can be the actual class or a string representation of that class.
# the class
Avo::Resources::Post
# the stirng representation of the class
"Avo::Resources::Post"
-> discreet_pagination
Default
false
Possible values
true
, false
-> hide_search_input
Default
false
. When nothing is selected and the search_query
of association's resource is configured, Avo displays the search input.
Possible values
true
, false
.
-> link_to_child_resource
Sets which resource should be used in an STI scenario.
See more on this in the STI section.
Default
false
. When it's false
it will use the same resource.
Possible values
true
, false
.
Search query scope
Since v2.13If the resource used for the has_many
association has the search
block configured with a query
, Avo will use that to scope out the search query to that association.
For example, if you have a Team
model that has_many
User
s, now you'll be able to search through that team's users instead of all of them.
You can target that search using params[:via_association]
. When the value of params[:via_association]
is has_many
, the search has been mad inside a has_many association.
For example, if you want to show the records in a different order, you can do this:
self.search = {
query: -> {
if params[:via_association] == 'has_many'
query.ransack(id_eq: params[:q], m: "or").result(distinct: false).order(name: :asc)
else
query.ransack(id_eq: params[:q], m: "or").result(distinct: false)
end
}
}
-> linkable
This feature doesn't go deeper than this. It just helps you see the association table easier in a separate page.
Has Many Through
The HasMany
association also supports the :through
option.
field :members,
as: :has_many,
through: :memberships
-> attach_fields
If you have extra fields defined in the through table and would like to display them when attaching use the attach_fields
option.
field :patrons,
as: :has_many,
through: :patronships,
attach_fields: -> {
field :review, as: :text
}
WARNING
If the through model uses polymorphism, the type must be included as a hidden field:
field :patrons,
as: :has_many,
through: :patronships,
attach_fields: -> {
field :review, as: :text
field :patronship_type, as: :hidden, default: "TheType"
}
Show on edit screens
By default, has_and_belongs_to_many
is only visible on the Show
page. If you want to enable it on the Edit
page, too, you need to add the show_on: :edit
option.
WARNING
Adding associations on the New
screen is not currently supported. The association needs some information from the parent record that hasn't been created yet (because the user is on the New
screen).
You may use the redirect helpers to have the following flow:
- User is on the
New
view. They can't see the association panels yet. - User creates the record.
- They get redirected to the
Show
/Edit
view, where they can see the association panels. - User attaches associations.
Add scopes to associations
Watch the demo videoWhen displaying has_many
associations, you might want to scope out some associated records. For example, a user might have multiple comments, but on the user's Show
page, you don't want to display all the comments, but only the approved ones.
# app/models/comment.rb
class Comment < ApplicationRecord
belongs_to :user, optional: true
scope :approved, -> { where(approved: true) }
end
# app/models/user.rb
class User < ApplicationRecord
has_many :comments
end
# app/avo/resources/user.rb
class Avo::Resources::User < Avo::BaseResource
def fields
field :comments, as: :has_many, scope: -> { query.approved }
end
end
The comments
query on the user Index
page will have the approved
scope attached.
With version 2.5.0, you'll also have access to the parent
record so that you can use that to scope your associated models even better.
Starting with version 3.12, access to resource
and parent_resource
was additionally provided.
All the has_many
associations have the attach_scope
option available too.
Show/hide buttons
You will want to control the visibility of the attach/detach/create/destroy/actions buttons visible throughout your app. You can use the policy methods to do that.
Find out more on the authorization page.
-> Reloadable
The reloadable option adds a reload icon next to the association title so users can easily reload just that turbo-frame instead of doing a full page reload.
Usage
To enable the reloadable feature, you have two options:
- Direct Boolean Value:
Provide a boolean value directly to the reloadable option. This sets a default behavior where the reloadable feature is either enabled or disabled based on this boolean value.
field :reviews, as: :has_many, reloadable: true
- Dynamic Conditions with a Block:
For more dynamic behavior, you can provide a block to the reloadable option. Within this block, you can specify conditions under which the reloadable should be displayed.
field :reviews, as: :has_many,
reloadable: -> {
current_user.is_admin?
}
In the above example, the reloadable will be visible if the current_user is an admin.
ExecutionContext
The reloadable block executes within the ExecutionContext
, granting access to all default methods and attributes.
-> association
The for_attribute
option allows to specify the association used for a certain field. This option make possible to define same association with different scopes and different name several times on the same resource.
Usage
field :reviews,
as: :has_many
field :special_reviews,
as: :has_many,
for_attribute: :reviews,
scope: -> { query.special_reviews }