acts_as_tenant gem使用RSpec / FactoryGirl创建错误

时间:2015-07-16 01:33:26

标签: ruby-on-rails rspec factory-bot acts-as-tenant

我正在尝试使用acts_as_tenant gem来为多个组织设置SQL查询范围。然而,RSpec / FactoryGirl正在拉扯一些肮脏的技巧。

一些背景知识:在我的应用中,UserGrant都属于Organization。只有管​​理员用户才能创建/删除Grant s。

与gem的文档建议一样,我已将acts_as_tenant :organization插入到我的GrantUser模型中。我还set_current_tenant_through_filter并在before_action :set_organization中定义了application_controller.rbUserGrant的查询仅限于当前用户的Organization

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

一切似乎都很好。现在编写控制器测试:

# 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

管理员部分引发了一个奇怪的错误:

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

所以,即使我已经将组织的外键专门传递给FactoryGirl,它仍然存在识别Organization的问题。

当我注释掉acts_as_tenant特定代码时,错误就会消失。如何让测试变得绿色好?

1 个答案:

答案 0 :(得分:0)

这实际上与我上面发布的代码关系不大。罪魁祸首是我的User模型中的这一行:

attr_accessor :organization_id

我认为该行阻止了实际的organization_id数据库列与模型一起保存。我的UsersController代码可以澄清这一点:

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

因此organization_id确实设置为organization.id,但attr_accessor首先被评估,因此organization_id成为无用的虚拟属性。 db列organization_id保存为nil,即没有传递给它。这反过来导致acts_as_tenant投诉,因为我将current_tenant设置为当前用户的组织,并且当前用户未设置外键

我对自己和偶然发现的所有其他人的建议:检查您的数据库列名是否被虚拟属性遮蔽。