Rails 自定义 class Gem
Rails customize class Gem
我在我的 rails 应用程序中重新打开了一个 gem class,一切似乎都正常,一切运行良好,但几分钟后,我的应用程序似乎忘记了所有修改:
config/initializers/rapidfire_custom.rb
::Rapidfire::Survey.class_eval do
belongs_to :campaign, class_name: '::Campaign', inverse_of: :survey
before_create :default_active
before_validation :default_status, :default_name
STATUS = ['DRAFT', 'PUBLISHED']
validates_inclusion_of :status, in: STATUS
validates :name, presence: true
scope :from_company, -> (id) { where(company_id: id) }
scope :template, -> { where(campaign_id: nil) }
scope :published, -> { where(status: 'PUBLISHED') }
def default_active
self.active ||= true
end
def default_status
self.status ||= 'DRAFT'
end
def self.all_status
STATUS
end
def default_name
if self.campaign
self.name = 'Survey'
end
end
end
错误:
undefined method `template' for #<Rapidfire::Survey::ActiveRecord_AssociationRelation:0x007fc762215ad0>
它只发生在开发中,我正在使用 puma:
config/puma.rb
workers Integer(ENV['WEB_CONCURRENCY'] || 2)
threads_count = Integer(ENV['MAX_THREADS'] || 5)
threads threads_count, threads_count
preload_app!
rackup DefaultRackup
port ENV['PORT'] || 3000
environment ENV['RACK_ENV'] || 'development'
if ENV['RACK_ENV'].nil? || ENV['RACK_ENV'] == 'development'
ssl_bind 'my_website.dev', '3000', { key: 'ssl/device.key', cert: 'ssl/device.crt' }
end
on_worker_boot do
ActiveRecord::Base.establish_connection
$redis.client.reconnect
end
我不知道发生了什么,知道吗?
谢谢
我猜想当 ActiveRecord 实例化 Rapidfire::Survey
记录时,它会从 gem 加载 class - 这会使您在 class eval 中所做的更改无效初始值设定项。
不属于您的 Monkey-patching 对象只有在您需要覆盖库方法并且没有更好的方法时才应该真正完成。
您还需要考虑 class eval 发生的时间和地点 - 当 rails 应用程序正在加载时初始化器是 运行 而模型 classes 是延迟加载时ActiveRecord 需要它们。所以使用初始化器来配置模型并不是一个好主意。
在这里使用继承是正确的做法 - 您正在创建自己的域对象。
我在我的 rails 应用程序中重新打开了一个 gem class,一切似乎都正常,一切运行良好,但几分钟后,我的应用程序似乎忘记了所有修改:
config/initializers/rapidfire_custom.rb
::Rapidfire::Survey.class_eval do
belongs_to :campaign, class_name: '::Campaign', inverse_of: :survey
before_create :default_active
before_validation :default_status, :default_name
STATUS = ['DRAFT', 'PUBLISHED']
validates_inclusion_of :status, in: STATUS
validates :name, presence: true
scope :from_company, -> (id) { where(company_id: id) }
scope :template, -> { where(campaign_id: nil) }
scope :published, -> { where(status: 'PUBLISHED') }
def default_active
self.active ||= true
end
def default_status
self.status ||= 'DRAFT'
end
def self.all_status
STATUS
end
def default_name
if self.campaign
self.name = 'Survey'
end
end
end
错误:
undefined method `template' for #<Rapidfire::Survey::ActiveRecord_AssociationRelation:0x007fc762215ad0>
它只发生在开发中,我正在使用 puma:
config/puma.rb
workers Integer(ENV['WEB_CONCURRENCY'] || 2)
threads_count = Integer(ENV['MAX_THREADS'] || 5)
threads threads_count, threads_count
preload_app!
rackup DefaultRackup
port ENV['PORT'] || 3000
environment ENV['RACK_ENV'] || 'development'
if ENV['RACK_ENV'].nil? || ENV['RACK_ENV'] == 'development'
ssl_bind 'my_website.dev', '3000', { key: 'ssl/device.key', cert: 'ssl/device.crt' }
end
on_worker_boot do
ActiveRecord::Base.establish_connection
$redis.client.reconnect
end
我不知道发生了什么,知道吗?
谢谢
我猜想当 ActiveRecord 实例化 Rapidfire::Survey
记录时,它会从 gem 加载 class - 这会使您在 class eval 中所做的更改无效初始值设定项。
不属于您的 Monkey-patching 对象只有在您需要覆盖库方法并且没有更好的方法时才应该真正完成。
您还需要考虑 class eval 发生的时间和地点 - 当 rails 应用程序正在加载时初始化器是 运行 而模型 classes 是延迟加载时ActiveRecord 需要它们。所以使用初始化器来配置模型并不是一个好主意。
在这里使用继承是正确的做法 - 您正在创建自己的域对象。