In RailsAdmin I am trying to manage my polymorphic Region
with two classes, one namespaced and one not.
class Region < ApplicationRecord
belongs_to :contentable, polymorphic: true
end
class Event::Exhibition < ApplicationRecord
has_many :regions, as: :contentable
end
class Post < ApplicationRecord
has_many :regions, as: :contentable
end
Everything works bar the ajax fetch of instances of namespaced models.
When I try and select an Event::Exhibition
, for example, I see this in my browser's console.
Error: Syntax error, unrecognized expression: #event::exhibition-js-options rails_admin.js:1502:8
error http://localhost:3000/assets/rails_admin/rails_admin.js:1502
When I select Post
all of my posts are returned as expected.
Is this a bug or should I be able to work around this with different settings? The only config I have for this is to tell Rails Admin to use the field.
edit do
field :contentable
end
Digging into the HTML and JavaScript a bit more (thanks @Guillermo) I noticed the generated dropdown looks like this.
<option value=""></option>
<option value="Event::ArtFair">Art fair</option>
<option value="Event::Exhibition">Exhibition</option>
<option selected="selected" value="Post">News article</option>
When either option with a value Event::
is selected, Sizzle complains, throwing a syntax error.
In my code inspector, if I escape the colons, making the values Event\:\:ArtFair
and Event\:\:Exhibition
things work as expected.
I see, those are not valid js identifiers. I think you can scape the values if you defined the content of the select by adding the _enum instance method.
First you need to get a list of possible contentables for the model.
I'm shooting from the hip here but it should be something like:
def self.contentable_models
ActiveRecord::Base.descendants.select do |model|
model.reflect_on_all_associations(:has_many).any? do |has_many_association|
has_many_association.options[:as] == :contentable
end
end
end
def contentable_enum
self.class.contentable_models.map |model|
[
model.name.humanize,
model.class.name.gsub(':','\:')
]
end
end
I'm not sure about the performance of the contentable_models
if you have many models it will iterate on all of them to find the contentable you might want to memoize that value.
You might need to define the contentable field as an enum or even the contentable_type field. Not sure