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

Errors when using accepts_nested_attributes_for #30

Open
PhilipAnd opened this issue May 24, 2020 · 1 comment
Open

Errors when using accepts_nested_attributes_for #30

PhilipAnd opened this issue May 24, 2020 · 1 comment

Comments

@PhilipAnd
Copy link

PhilipAnd commented May 24, 2020

I am trying to use Rails-multitenant, but I am running into an issue when creating accounts. I have accounts which can have users and websites underneath. This means that for the website and user I have set:

class Website < ApplicationRecord
    include RailsMultitenant::MultitenantModel
    
    belongs_to :account
    accepts_nested_attributes_for :account

    multitenant_on :account_id
end
class User < ApplicationRecord
  include RailsMultitenant::MultitenantModel
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable, 
         :confirmable, :lockable, :trackable

  belongs_to :account
  accepts_nested_attributes_for :account

  multitenant_on :account_id
end
class Account < ApplicationRecord   
    has_many :users, dependent: :destroy, inverse_of: :account
    has_many :websites, dependent: :destroy, inverse_of: :account

    accepts_nested_attributes_for :users, allow_destroy: true
    accepts_nested_attributes_for :websites, allow_destroy: true
end

When creating the account I set the user and website and saves it:

class AccountsController < ApplicationController
    #layout 'session'
  
    def new
      @account = Account.new
      @account.users.build
      @account.websites.build
    end
  
    def create
      @account = Account.new(register_account_params)
       
      if @account.save
        user = @account.users.last
        sign_in(user)
  
        redirect_to root_path, notice: 'Account was successfully created.'
      else
        render :new
      end
    end
  
    private
  
    def register_account_params
      params.require(:account).permit(:name, users_attributes: [:name, :email, :password, :password_confirmation], websites_attributes: [:url])
    end

  end

When signing up I get the errors:

  • Users account can't be blank
  • Websites account users account can't be blank
  • Websites account can't be blank

The errors don't appear when disabling the multitenant functionality. My assumption is that this due to me trying to save the user and website through the account. Is there any way to get around this limitation?

@jturkel
Copy link
Member

jturkel commented May 26, 2020

Hmm. This gem adds a default scope to RailsMultitenant::MultitenantModel models that looks something like this:

default_scope { where(account_id: RailsMultitenant[:account_id]) }

The default scope will ensure that you're only seeing model instances corresponding to the current account but it also handles filling in the account_id for any newly created multitenant models. It also adds a validation to the model that the account_id is set properly. This approach generally works well and provides the desired sandboxing but it can lead to some weird behavior when working with the top level tenant model (i.e. Account model in your case) which is hopefully not very common. I suspect the assignment of account_id done in this gem is conflicting with the assignment of account_id done by accepts_nested_attributes_for. You could try running the AccountsController#create method in a RailsMultitenant::GlobalContextRegistry.with_unscoped_queries block (assuming you don't need tenant scoping for this one method) but that may lead to accidental data leakage as your code evolves. A safer (but more verbose) approach would be to avoid the usage of accepts_nested_attributes_for on your top level tenant model (but it should be fine on other models).

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