将模型移动到 gem - Rails 4.1
Moving Models into a gem - Rails 4.1
我有一个引擎,叫做 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 的 table 与 xaaron_table_names
的名字 spaced 相同,所以在这种情况下它是 xaaron_users
我假设它仍然知道如何查看 xaaron_users
table 即使我扩展了另一个模型。显然不是。
我该怎么做才能纠正这个问题,以便我的模型仍在 gem 中,但可以通过 xaaron 或任何其他在 space 中命名或不命名 table 的应用程序访问小号?
这不会使用 xaaron_users
table 因为 CoreModels::Model::User
在 Xaaron
命名空间之外,因此不会有 xaaron_
前缀你的 table 名字。
解决方法是在模型中手动指定table名称:
module Xaaron
class User < CoreModels::Models::User
self.table_name = "xaaron_users"
end
end
我有一个引擎,叫做 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 的 table 与 xaaron_table_names
的名字 spaced 相同,所以在这种情况下它是 xaaron_users
我假设它仍然知道如何查看 xaaron_users
table 即使我扩展了另一个模型。显然不是。
我该怎么做才能纠正这个问题,以便我的模型仍在 gem 中,但可以通过 xaaron 或任何其他在 space 中命名或不命名 table 的应用程序访问小号?
这不会使用 xaaron_users
table 因为 CoreModels::Model::User
在 Xaaron
命名空间之外,因此不会有 xaaron_
前缀你的 table 名字。
解决方法是在模型中手动指定table名称:
module Xaaron
class User < CoreModels::Models::User
self.table_name = "xaaron_users"
end
end