Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Override default scope in active_admin form.has_many

Given a model Post that has_many attachments, and an attachment has a hidden flag. Throughout the app I want to easily say post.attachments and only get the visible ones, so i setup a default scope in the Attachment model (using squeel):

default_scope -> { where { (hidden != true) | (hidden == nil) } } 

But the admin page needs to be able to see all attachments for a post, not just the visible ones (so you can toggle the hidden checkbox). The default way of doing this (in admin/posts.rb) uses the default_scope and only lets me edit the visible ones:

f.has_many :attachments do |a|
  ...
end

I know I could just not use default_scope and instead name it :visible, and then everywhere (except the admin page) say post.attachments.visible but I prefer not having the do that.

How can I unscope the children attachments on the admin page?

like image 614
linojon Avatar asked Feb 18 '23 02:02

linojon


1 Answers

Here's the solution I worked out:

In app/admin/posts.rb

f.has_many :attachments, for: [:attachments, f.object.attachments_including_hidden] do |a|
  ...
end

And in app/models/posts.rb

def attachments_including_hidden
  Attachment.unscoped.where( attachable_id: id )
end

(where Attachment model belongs_to: :attachable, polymorphic: true )

What's going on? ActiveAdmin uses Formtastic, which uses Rails Form Builder. The form.has_many method is an ActiveAdmin method, which calls Formtastic's form.inputs, which in turn calls Rails' fields_for. The :for option will get passed all the way down the fields_for, which can take a collection (as its 2nd arg) so I deliver this collection to it explicitly.

like image 117
linojon Avatar answered Mar 06 '23 20:03

linojon