https://avo.cool logo
I think I'm hitting an edge case (again
# general
m
I think I'm hitting an edge case (again), this time around polymorphic relations. I've got this model, and I want to display the
recipients
in a list:
Copy code
rb
class Mailing < ApplicationRecord
  belongs_to :mailable, polymorphic: true

  delegate :recipients, to: :mailable
end
and an example of a `mailable`:
Copy code
rb
class Event < ApplicationRecord
  has_many :recipients
  has_many :mailings, as: :mailable
end
The
delegate
is necessary, because you can't specify a
has_many through:
on a polymorphic association:
Copy code
rb
  has_many :recipients, through: :mailable

  # => Cannot have a has_many :through association 'Mailing#recipients' which goes through the polymorphic association 'Mailing#mailable'. (ActiveRecord::HasManyThroughAssociationPolymorphicThroughError)
I tried to solve this with an
Array
field, but failed because it needs an
ArrayResource
to back it. Is there any other way to achieve this?
l
Hi @millions-exabyte-27721 👋 The array field needs the array resources to function, you can easly create one recipt array resource
m
yep I got that, but I already have a
recipient
resource, i.e. the
User
resource. but that doesn't work because it needs an Array resource:
Copy code
rb
    field :recipients, as: :array, use_resource: "User"
this (obviously) leads to
Copy code
undefined method `fetch_records' for #<Avo::Resources::User:0x000000012edddc70>
which isn't surprising because the array field isn't designed to work with resources other than
Array
ones 🤔
l
You must create an array resource, since we're not namespacing the resources types you need to use another name
m
yuck
I mean, the
array
field is just a crutch anyway, it's just a
has_many
, just on another resource 🤔
l
True, the used resource is what diferentiates it from a has many
m
ugh, working with polymorphic assiciations is always such a brainfuck
l
What about:
Copy code
has_many :recipients, -> (mailing) { mailing.recipients }
m
if I add a dummy
has_many
it actually works:
Copy code
rb
  # this is a dummy association to appease Avo
  has_many :recipients, class_name: "User"
  delegate :recipients, to: :mailable
Copy code
rb
    field :recipients, as: :has_many, use_resource: "User", name: "Recipients"
l
Copy code
ruby
class Mailing < ApplicationRecord
  belongs_to :mailable, polymorphic: true

  has_many :recipients, -> (mailing) { mailing.recipients }
end
I dont have the context setted up but probbaly this works ☝️
m
final question though,
has_many
fields cannot be set to
readonly
, right?
actually I just tried this a second before, and it threw up at the
count
query it issued. but nevermind
l
actually i think it misses a step:
has_many :recipients, -> (mailing) { mailing.mailable.recipients }
mailing.mailable
What would you expect from this setting?
m
right! that was what I tried
Copy code
ActiveRecord::StatementInvalid (PG::UndefinedColumn: ERROR:  column users.mailing_id does not exist
don't worry though
l
readonly marks fields to not be included or updated on form submit
m
the
delegate
more or less is just overriding the getter, which is good in my case because I don't even want that list to be editable, I just want to display it for reference
I'd just love to not display the action bar at all
needs a custom view, probably?
l
No, actions are controller by policy
by authorization
m
ah!
l
are you using authorization yet?
When you start using authorization, by default, the has many table will not be visible at all You need to go into mailing policy and add
def view_recipients? = true
then same for each action that you want to enable
def edit_recipients? = true
etc...
I use true on my example but you can rely on the user
m
yep
so, opting into authorization is a one-for-all switch, right? It means I have to add policies for every resource?
l
Yes, that's intentional, it avoids letting actions authorized without explicitly authorize those
m
good. I just think I'll punt on it in this PR and do it later
now that I know how to do it. thanks!
l
Cool!
m
again, maybe something to write a guide for 😄
l
You mean the authorization?
m
well, the whole polymorphic shenanigans
it's edge-casey, but needs some good recipes, I think
l
Got it, makes sense. I'll add an issue for that so we don't lose track of it. Meanwhile, if you're up for contributing a guide about this issue, we'd love to merge it.