简体   繁体   中英

acts_as_tenant gem is creating errors using RSpec/FactoryGirl

I am attempting to use the acts_as_tenant gem to scope SQL queries for multiple organizations. RSpec/FactoryGirl are pulling some dirty tricks, however.

A bit of background: in my app, User and Grant both belong to an Organization . Only admin users can create/delete Grant s.

Like the gem's documentation advises, I have inserted acts_as_tenant :organization into my Grant and User models. I have also set_current_tenant_through_filter and defined a before_action :set_organization in my application_controller.rb . Queries for User and Grant are scoped to the current user's Organization only:

  def set_organization
    if current_user
      current_organization = Organization.find(current_user.organization_id)
      set_current_tenant(current_organization)      
    end
  end

All seems well and good. Now to write controller tests:

# grants_controller_spec.rb

describe GrantsController do
  let(:organization) { create(:organization) }
  let(:admin) { create(:user, admin: true, organization_id: organization.id) }
  ...
  before(:each) { log_in admin }
  ...
end

The admin part raises an odd error:

 Failure/Error: let(:admin) { create(:user, admin: true, organization_id: organization.id) }
     ActiveRecord::RecordInvalid:
       Validation failed: Organization can't be blank

So, even though I have specifically passed the organization's foreign key to FactoryGirl, it's still having issues identifying the Organization .

When I comment out the acts_as_tenant -specific code, the errors go away. How can I make the tests go green for good?

This actually has very little to do with the code I posted above. The culprit was this line, in my User model:

attr_accessor :organization_id

I believe that line prevented the actual organization_id database column from being saved with the model. My UsersController code can clarify this:

def create
    @user = User.new(user_params)
    organization = Organization.find_by(name: params[:user][:organization_name])
    if organization.authenticated?(params[:user][:organization_password])
      @user.organization_id = organization.id
      @user.save
      ...
end

So organization_id was indeed set to organization.id , but attr_accessor was evaluated first, so organization_id became a useless virtual attribute. And the db column organization_id was saved as nil , ie, nothing was passed to it. This in turn caused acts_as_tenant to complain since I'd set the current_tenant as the current user's organization, and the current user wasn't getting set up with a foreign key.

My advice to myself and to all others who stumble upon this: check whether your db column names are shadowed by your virtual attributes.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM