Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rails Admin doesn't handle STI to single table #3373

Closed
Naokimi opened this issue Aug 7, 2021 · 12 comments
Closed

Rails Admin doesn't handle STI to single table #3373

Naokimi opened this issue Aug 7, 2021 · 12 comments

Comments

@Naokimi
Copy link

Naokimi commented Aug 7, 2021

I have 2 different classes inheriting from User but saving in the same table:

class User < ApplicationRecord
  # devise stuff
end

class Participant < User
  has_many :participant_stamps
  has_many :stamps, through: :participant_stamps
end

class Vendor < User
  has_many :vendor_stamps
  has_many :stamps, through: :vendor_stamps
end

I'd like to add a VendorStamp using rails admin, but when I go to the tab, the relation is missing, which of course throws an error when trying to save
image

I also tried to explicitly tell it to look for a vendor (see below), but with no luck

RailsAdmin.config do |config|
  config.model 'VendorStamp' do
    list do
      field :stamp
      field :vendor
    end
  end
end
@mshibuya
Copy link
Member

mshibuya commented Aug 8, 2021

Could you provide all relevant information like the VendorStamp model?
Are the operation you're trying to do achievable using the Rails Console?

@Naokimi
Copy link
Author

Naokimi commented Aug 8, 2021

VendorStamp model:

class VendorStamp < ApplicationRecord
  belongs_to :stamp
  belongs_to :vendor

  validates :stamp_id, uniqueness: { scope: :vendor_id }
end

Stamp model:

class Stamp < ApplicationRecord
  has_many :vendor_stamps
  has_many :vendors, through: :vendor_stamps
  has_many :participant_stamps
  has_many :participants, through: :participant_stamps
end

Creating VendorStamp in Rails Console (and confirming that it was actually created):
image

@Naokimi
Copy link
Author

Naokimi commented Aug 8, 2021

to point it out again: Vendor and Participant both save their record in the users table, thanks to this migration:

class DeviseCreateUsers < ActiveRecord::Migration[6.1]
  def change
    create_table :users do |t|
      ## Database authenticatable
      t.string :email,              null: false, default: ""
      t.string :encrypted_password, null: false, default: ""
      t.string :type #this column is what allows to save different Models in one table

      ## Recoverable
      t.string   :reset_password_token
      t.datetime :reset_password_sent_at

      ## Rememberable
      t.datetime :remember_created_at

      t.timestamps null: false
    end

    add_index :users, :email,                unique: true
    add_index :users, :reset_password_token, unique: true
  end
end

@Naokimi
Copy link
Author

Naokimi commented Aug 8, 2021

if you want to generate the other models, here are the migrations:

class CreateStamps < ActiveRecord::Migration[6.1]
  def change
    create_table :stamps do |t|
      t.string :name
      t.string :img_url

      t.timestamps
    end
  end
end

class CreateParticipantStamps < ActiveRecord::Migration[6.1]
  def change
    create_table :participant_stamps do |t|
      t.references :stamp, null: false, foreign_key: true
      t.references :participant, null: false, foreign_key: { to_table: :users }

      t.timestamps
    end
  end
end

class CreateVendorStamps < ActiveRecord::Migration[6.1]
  def change
    create_table :vendor_stamps do |t|
      t.references :stamp, null: false, foreign_key: true
      t.references :vendor, null: false, foreign_key: { to_table: :users }

      t.timestamps
    end
  end
end

@mshibuya
Copy link
Member

mshibuya commented Aug 8, 2021

I can't reproduce by using exactly the same setup, the vendor field shows up normally.
image

Can you show me the whole content of your VendorStamp model and RailsAdmin config?

@Naokimi
Copy link
Author

Naokimi commented Aug 8, 2021

VendorStamp I copied whole content

this is my rails admin config:

require 'nested_form/engine'
require 'nested_form/builder_mixin'

RailsAdmin.config do |config|

  ### Popular gems integration

  ## == Devise ==
  config.authenticate_with do
    warden.authenticate! scope: :user
  end
  config.current_user_method(&:current_user)

  ## == CancanCan ==
  # config.authorize_with :cancancan

  ## == Pundit ==
  # config.authorize_with :pundit

  ## == PaperTrail ==
  # config.audit_with :paper_trail, 'User', 'PaperTrail::Version' # PaperTrail >= 3.0.0

  ### More at https://github.com/sferik/rails_admin/wiki/Base-configuration

  ## == Gravatar integration ==
  ## To disable Gravatar integration in Navigation Bar set to false
  # config.show_gravatar = true

  config.authorize_with do
    unless current_user.admin?
      flash[:alert] = 'Sorry, no admin access for you.'
      redirect_to main_app.root_path
    end
  end

  config.actions do
    dashboard                     # mandatory
    index                         # mandatory
    new
    export
    bulk_delete
    show
    edit
    delete
    show_in_app

    ## With an audit adapter, you can add:
    # history_index
    # history_show
  end
end

To check for admin permissions I set up these methods in my User model:

class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable

  def admin?
    instance_of?(Admin)
  end

  def participant?
    instance_of?(Participant)
  end

  def vendor?
    instance_of?(Vendor)
  end
end

@Naokimi
Copy link
Author

Naokimi commented Aug 8, 2021

Ruby -v 2.7.2
Rails -v 6.1.4

@mshibuya
Copy link
Member

mshibuya commented Aug 8, 2021

Hmm, I see nothing unusual.

This is the repo I've created trying to reproduce this issue, can you make that happen by using this?
https://github.com/mshibuya/issue-3373

@Naokimi Naokimi closed this as completed Aug 8, 2021
@Naokimi Naokimi reopened this Aug 8, 2021
@Naokimi
Copy link
Author

Naokimi commented Aug 8, 2021

I was able to run the repo you provided, but then I tried creating a new one more similar to the one I have and the error is the same.

You can find the repo here: https://github.com/Naokimi/rails-admin-issue-3373

The main differences are:

  • using PG instead of sqlite
  • inheritance models are under app/models/users/ folder
  • added to config/application.rb the line config.autoload_paths += %W(#{Rails.root}/app/models/users)

BUT

when I kept all the models inside app/models and removed the added line, it worked as expected

Is there a way how to make it work while at the same time keeping models in folders for better readability?

@mshibuya
Copy link
Member

mshibuya commented Aug 9, 2021

Thanks, I was able to track down the issue.

First, you need to use eager_load_paths instead of autoload_paths.

  config.eager_load_paths += %W(#{Rails.root}/app/models/users)

autoload_paths is just telling the Rails to load models if necessary, hence the Vendor model fails to be picked up by RailsAdmin.
https://stackoverflow.com/a/19852844

But that alone does not solve this issue, there was a glitch in RailsAdmin which ignores the application-specific eager_load_paths configuration. 238f18e addresses it.

In short, using eager_load_paths and using the RailsAdmin master branch will solve this.

@Naokimi
Copy link
Author

Naokimi commented Sep 3, 2021

Sorry for coming back to this after so long, but just wanted to say that it still doesn't work :(
image
I've updated the gem and added the eager_load_paths

you can find the code in https://github.com/Naokimi/rails-admin-issue-3373

@mshibuya
Copy link
Member

mshibuya commented Sep 3, 2021

The fix is not released yet, you need to use the master branch.

gem 'rails_admin', github: 'sferik/rails_admin'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants