2015-02-11 33 views
3

我有一个模型,它是另一个模型的子类,这个特定的模型不使用我指定的表,而是默认返回到试图找到该表的父类。Rails没有使用指定模型的表

父类是宝石,子类是在名字空间被隔离的引擎中。

父(创业板):

require_relative 'concerns/user_concerns' 
require 'bcrypt' 

module CoreModels 
    module Models 
    class User < ActiveRecord::Base 
     self.abstract_class = true 

     extend FriendlyId 
     friendly_id :first_name, use: [:slugged, :finders, :history] 

     before_save :encrypt_password 

     has_many :group_memberships, :dependent => :delete_all 
     has_many :groups, :through => :group_memberships, :dependent => :delete_all 
     has_many :roles, :through => :group_memberships, :dependent => :delete_all 

     has_many :api_keys 

     validates :first_name, presence: true 
     validates :user_name, uniqueness: true, presence: true, length: {minimum: 5} 
     validates :email, presence: true, confirmation: true, uniqueness: true 
     validates_format_of :email, :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i 
     validates :password, presence: true, confirmation: true, length: { minimum: 10 }, if: :new_record? 

     include CoreModels::Models::Concerns::UserConcerns 

     before_create{ generate_token(:auth_token) } 

     def self.authenticate_user(user_name, password) 
     user = Xaaron::User.find_by_user_name(user_name) 
     if(user && (user.password == BCrypt::Engine.hash_secret(password, user.salt))) 
      user 
     else 
      nil 
     end 
     end 

     def encrypt_password 
     if password.present? 
      self.salt = BCrypt::Engine.generate_salt 
      self.password = BCrypt::Engine.hash_secret(password, salt) 
     end 
     end 

     def send_password_reset 
     generate_token(:password_reset_token) 
     self.password_reset_timestamp = Time.zone.now 
     save! 
     UserMailer.password_reset(self).deliver 
     end 

     protected 
     def generate_token(column) 
     begin 
      self[column] = SecureRandom.urlsafe_base64 
     end while User.exists?(column => self[column]) 
     end 
    end 
    end 
end 

儿童(发动机):

require 'core_models/models/user' 

module Xaaron 
    class User < CoreModels::Models::User 
    self.table_name = 'xaaron_users' 
    end 
end 

当我运行我的测试中,他们的135失败,一遍又一遍给我同样的错误再次:

Failure/Error: setup_group_role_permissions_relations_for_administrator 
    ActiveRecord::StatementInvalid: 
     PG::UndefinedTable: ERROR: relation "users" does not exist 
     LINE 5:    WHERE a.attrelid = '"users"'::regclass 
               ^
     :    SELECT a.attname, format_type(a.atttypid, a.atttypmod), 
          pg_get_expr(d.adbin, d.adrelid), a.attnotnull, a.atttypid, a.atttypmod 
         FROM pg_attribute a LEFT JOIN pg_attrdef d 
         ON a.attrelid = d.adrelid AND a.attnum = d.adnum 
         WHERE a.attrelid = '"users"'::regclass 
         AND a.attnum > 0 AND NOT a.attisdropped 
         ORDER BY a.attnum 

该特定方法是:

def setup_group_role_permissions_relations_for_administrator 
    @user = FactoryGirl.create(:user) 
    @role = FactoryGirl.create(:admin_role) 
    @group = FactoryGirl.create(:administrator_group) 
    @permission = FactoryGirl.create(:can_read) 

    @role.add_permission = @permission.permission_name 
    @group.add_role = @role.role_name 

    @user.add_group_membership(@group, @role) 
end 

所以你可以看到它不听我说我使用表x。相反,它试图使用不我所有的引擎exist./表表是名与xaaron_

更新

的核心问题间隔,经过一番调查FactoryGirl,如果我们看的第一件事这种情况发生在:setup_group_role_permissions_relations_for_administrator我做@user = FactoryGirl.create(:user),当我用撬找出WA对那里发生的 - 这就是问题,所以让我们来看看这家工厂:

FactoryGirl.define do 
    sequence :user_email do |n| 
    "user#{n}@example.com" 
    end 

    # Allows for multiple user names 
    sequence :user_name do |n| 
    "user#{n}" 
    end 

    sequence :permission_name do |n| 
    "can_read#{n}" 
    end 

    sequence :role_name do |n| 
    "Member#{n}" 
    end 


    factory :user, :class => Xaaron::User do 
    first_name 'Adam' 
    last_name 'Something' 
    user_name {generate :user_name} 
    email {generate :user_email} 
    password 'somePasswordThat_Is$ecure10!' 
    end 

    factory :admin, :class => Xaaron::User do 
    first_name "Sample Admin" 
    email "[email protected]" 
    user_name "Admin_User_Name" 
    password "admin_Password10985" 
    end 
end 

也有一些是错误的方式工厂女孩正在创建用户,因为我可以启动一个导轨控制台并执行Xaaron::User.all,它知道要在xaaron_users而不是users

因此,self.table_name=""工作,但由于某种原因,与工厂的女孩不工作。 2

我在提交了一份可能的bug报告

更新:Their Github Repo

+0

这与任何事情无关。 – TheWebs 2015-02-11 23:14:28

+0

这与手头的问题无关,请不要粘住convo或离开。或者提供一些更好的反馈。 – TheWebs 2015-02-12 01:31:17

回答

1

一般来说,活动记录的目的是使用单表继承(用于所有子类的记录相同的表),而不是多个表继承(子类的不同表)。

这就是说,不是使用self.table_name =设置子类中的表名,而是可以覆盖table_name方法,例如

def table_name 
    'xaaron_users' 
end 

然后看看你的情况是否有效。这是mentioned as an alternative in the docs

+0

尽管我所做的事情被认为是单表继承,但我真正想要做的事情是将模型移动,并将引擎(在本例中为Xaaron)和引擎的关系移至gem--在本例中为core_models。就这样说,正如你从更新的问题中看到的那样,真正的问题是FactoryGirl。 – TheWebs 2015-02-11 23:20:42