DEV Community

Derrick Amenuve
Derrick Amenuve

Posted on

Resolving ActiveStorage URL Generation Between Rails and Avo admin gem

I've been working on my project Modatongue and hit a roadblock with Active Storage. Images were displaying fine in lessons or my main rails application, but not in my Avo admin! 😭

TLDR;
Just change line 3 of your app/views/active_storage/_blobs.html.erb to use main_app.url_

Image description

Image description

My Battle with Active Storage (and How I Won!)
Like I mentioned earlier the Images were displaying fine in my lessons or inside the main rails app, but not in my Avo admin or when I logged into my admin interface! 😭

<figure class="attachment attachment--<%= blob.representable? ? "preview" : "file" %> attachment--<%= blob.filename.extension %>">
  <% if blob.representable? %>
    <%= image_tag blob.representation(resize_to_limit: local_assigns[:in_gallery] ? [ 800, 600 ] : [ 1024, 768 ]) %>
  <% end %>

  <figcaption class="attachment__caption">
    <% if caption = blob.try(:caption) %>
      <%= caption %>
    <% else %>
      <span class="attachment__name"><%= blob.filename %></span>
      <span class="attachment__size"><%= number_to_human_size blob.byte_size %></span>
    <% end %>
  </figcaption>
</figure>
Enter fullscreen mode Exit fullscreen mode

The above code for my blob partial(which is likely going to be your default when you install active storage). This works in Rails views, but not Avo which expects blob objects to respond to to_model. Avo admin cried undefined method 'to_model'. Ugh, why?! 🤯

After a lot of trial and error, I realized Avo uses different helpers. So I tried bypassing them directly with:

<%= image_tag main_app.url_for(blob) %>

so now my blob partial will look like:

<figure class="attachment attachment--<%= blob.representable? ? "preview" : "file" %> attachment--<%= blob.filename.extension %>">
  <% if blob.representable? %>
    <%= image_tag main_app.url_for(blob.representation(resize_to_limit: local_assigns[:in_gallery] ? [ 800, 600 ] : [ 1024, 768 ])) %>
  <% end %>

  <figcaption class="attachment__caption">
    <% if caption = blob.try(:caption) %>
      <%= caption %>
    <% else %>
      <span class="attachment__name"><%= blob.filename %></span>
      <span class="attachment__size"><%= number_to_human_size blob.byte_size %></span>
    <% end %>
  </figcaption>
</figure>
Enter fullscreen mode Exit fullscreen mode

The Solution
The key was to bypass both helpers and generate the URL directly from Rails.

This works because main_app references the root Rails application context:

<%= image_tag main_app.url_for(blob.representation(resize_to_limit: local_assigns[:in_gallery] ? [ 800, 600 ] : [ 1024, 768 ])) %>

Now url_for generates the URL correctly for any ActiveStorage attachment, working identically in both Rails and Avo views.
By leveraging the core Rails URL generation, a single rendering approach can work consistently across any frameworks layered on top of Rails. This keeps view code DRY and avoids compatibility issues.

Eureka! It worked 🎉
Big props to the chatbots who helped clue me in - ChatGPT, Poe and especially Bard who provided the final hint. What a rollercoaster ride but so satisfying to crack it myself! 🙌

I hope this helps you and feel free to say hi on Twitter! Now back to building Modatongue.

Top comments (2)

Collapse
 
benherbst profile image
Ben Herbst

I really like your writing style, especially your emojies. Your article is great 😀

Collapse
 
godsloveady profile image
Derrick Amenuve

@benherbst, thank you so much for your kind words! 😊 I'm happy to hear that you enjoyed my writing style and the article. It means a lot to me! 🙌
Do you use Rails with Avo Admin?