【问题标题】:Moving Models into a gem - Rails 4.1将模型移动到 gem - Rails 4.1
【发布时间】:2015-02-10 22:34:28
【问题描述】:

我有一个名为 Xaaron 的引擎。和一个名为 core_models 的 Gem。作为一个实验,我试图将 Xaaron 的用户模型移动到 gem 中。最终,我想将引擎中的所有模型移到 gem 中。

这是我做的,在lib/core_models/models/user.rb下的gem中我做了:

require_relative 'concerns/user_concerns'
require 'bcrypt'

module CoreModels
  module Models
    class User < ActiveRecord::Base

      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

这是以前在 Xaaron 中的模型。

在 Xaaron 引擎中,app/models/xaaron/user.rb 下我做了:

require 'core_models/models/user'

module Xaaron
  class User < CoreModels::Models::User
  end
end

如您所见,我只是在扩展模型。

现在我假设这会起作用,显然它不起作用,因为与用户模型交互的任何东西都在抛出,测试明智:

 Failure/Error: create_login_admin_user
 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 

现在 Xaaron 的表与 xaaron_table_names 的名称隔开,因此在本例中为 xaaron_users

我认为即使我扩展了另一个模型,它仍然会知道如何查看xaaron_users 表。显然不是。

我可以做些什么来纠正这个问题,以便我的模型仍然在 gem 中,但可以通过 xaaron 或任何其他在表中命名空间或不命名空间的应用程序访问?

【问题讨论】:

    标签: ruby-on-rails-3 model namespaces gem rails-engines


    【解决方案1】:

    这不会使用xaaron_users 表,因为CoreModels::Model::UserXaaron 命名空间之外,因此您的表名上不会有xaaron_ 前缀。

    解决办法是在模型内部手动指定表名:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-07-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多