You are browsing docs for Avo 2: go to Avo 3

Skip to content

Has And Belongs To Many

The HasAndBelongsToMany association works similarly to HasMany.

ruby
field :users, as: :has_and_belongs_to_many

Options

searchable

Turns the attach field/modal from a select input to a searchable experience

ruby
class CourseLink < Avo::BaseResource
  field :links,
    as: :has_many,
    searchable: true
end

WARNING

Avo uses the search feature behind the scenes, so make sure the target resource has the search_query option configured.

ruby
# app/avo/resources/course_link_resource.rb
class CourseLinkResource < Avo::BaseResource
  self.search_query = -> do
    scope.ransack(id_eq: params[:q], link_cont: params[:q], m: "or").result(distinct: false)
  end
end

Default

false

Possible values

true, false

attach_scope

Scope out the records the user sees on the Attach modal.

Default

nil

Possible values

ruby
field :user,
  as: :belongs_to,
  attach_scope: -> { query.non_admins }

Pass in a block where you attach scopes to the query object. The block is executed in the AssociationScopeHost, so follow the docs to see what variables you have access to.

scope

Scope out the records displayed in the table.

Default

nil

Possible values

ruby
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 AssociationScopeHost, so follow the docs to see what variables you have access to.

description

Changes the text displayed under the association name.

Default

nil

Possible values

Any string.

use_resource

Sets a different resource to be used when displaying (or redirecting to) the association table.

Default

nil. When nothing is selected, Avo infers the resource type from the reflected association.

Possible values

PostResource, PhotoCommentResource, or any Avo resource class.

discreet_pagination

Hides the pagination details when only there's only one page for that association.

Default

false

Possible values

true, false

hide_search_input

Hides the search input displayed on the association table.

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.

Search query scope

Since v2.13

If the resource used for the has_many association has the search_query block configured, Avo will use that to scope out the search query to that association.

For example, if you have a Team model that has_many Users, 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:

ruby
self.search_query = -> do
  if params[:via_association] == 'has_many'
    scope.ransack(id_eq: params[:q], m: "or").result(distinct: false).order(name: :asc)
  else
    scope.ransack(id_eq: params[:q], m: "or").result(distinct: false)
  end
end

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:

  1. User is on the New view. They can't see the association panels yet.
  2. User creates the record.
  3. They get redirected to the Show/Edit view, where they can see the association panels.
  4. User attaches associations.

Searchable has_and_belongs_to_many

Similar to belongs_to, the has_many associations support the searchable option.

Add scopes to associations

Watch the demo video

When 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.

ruby
# 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_resource.rb
class UserResource < Avo::BaseResource
  # Before v2.5.0
  field :comments, as: :has_many, scope: -> { approved }
end

# app/avo/resources/user_resource.rb
class UserResource < Avo::BaseResource
  # After v2.5.0
  field :comments, as: :has_many, scope: -> { query.approved }
end

The comments query on the user Index page will have the approved scope attached.

Association scope

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.

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.

Associations authorization