rails_admin: Active Storage: `method_missing': undefined method `has_one_attached'

Hello guys, I’m facing a issue while using active storage with rails_admin.

What’s happening is that I’ve model called Product which should have a image. I’ve installed active storage by running the following commands:

rails active_storage:install
db:migrate

After that, I’ve added a new attibute on my Model as:

has_one_attached :image

However, rails does not recognize it as a method:

class:Product’ /Users/username/.rvm/gems/ruby-2.5.1/gems/activerecord-5.2.0/lib/active_record/dynamic_matchers.rb:22:in method_missing': undefined method has_one_attached’ for Product (call ‘Product.connection’ to establish a connection):Class (NoMethodError)

I’ve created a application from the scratch without rails_admin and it worked fine.

Note: I’m using rails 5.2.0 and ruby 2.5.1

Any ideas?

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 7
  • Comments: 22

Commits related to this issue

Most upvoted comments

I think I’ve had the same issue. I was trying to configure model inside rails_admin initializer using config.model Product do ... end. Instead it should’ve been config.model 'Product' do ... end. The model name must be quoted.

At least up to 5.2.4.3, ActiveStorage seems to initialize and inject its methods into ActiveRecord after Rails config/initializers are loaded. If any initializer uses any model calling ActiveStorage macros, as has_one_attached or has_many_attached, those methods are missing by then.

For example, if you have a User model using has_one_attached :image , and you use User as your Devise model, Device initializer will refer User, and when User is loaded the method has_one_attached will be missing.

I added this code, taken from active_storage/engine, at the end of config/application.rb, and it worked for me.

# config/application.rb
require "active_storage/attached"
ActiveSupport.on_load(:active_record) do
  extend ActiveStorage::Attached::Macros
end

Initalizers are run before your application code runs. Models are interpreted only when needed (on a firs request perhaps). But if you reference a model in the initializer using a constant ie. config.model Product do ... end, the model has to be interpreted before the rest of your initializer code and other initalizers. Configuring your models using string config.model 'Product' do ... end works well with rails_admin.

It seems that ActiveStorage has its own initalizer which waits ActiveRecord to load before it inserts its macros. Perhaps rails_admin.rb initalizer is executed before active_storage.attached initalizer ?

declaring this on model solved the problem for me

` class User < ApplicationRecord has_one_attached :avatar

rails_admin do
  field :avatar, :active_storage
end

end `

reference https://github.com/sferik/rails_admin/issues/2990#issuecomment-378220331

thanks a lot @dmilisic, your solution to use a string instead of a constant helped me a lot!!

I ignored this thread because I thought it would not solve my issue. Turns out I’m completely wrong. Thank you so much! @dmilisic

@dmilisic thank you for the support! We have managed to solve the problem. The Subscription model was calling a constant defined in the User model and then make the User be load before has_one_attached creation (I think!?). From the previously stacktrace:

...
from /usr/local/bundle/gems/activesupport-6.0.0/lib/active_support/dependencies.rb:214:in `const_missing'
from /app/app/models/subscription.rb:121:in `<class:Subscription>'
...

So we just copy the constant to the Subscription class and then it worked.