我知道这个问题已被问过好几次了,但我想在这种情况下从来没有。
我尝试为我的模型创建一个“帮助器”(acts_as
),用于从status_id自动设置状态。
acts_as_statusable :status, [ :in_progress, closed ]
此帮助程序创建方法status
,status=(sym)
,in_progress?
,closed?
和命名范围in_progress
和closed
。
我的帮助工作,这是它放在lib/
class ActiveRecord::Base
def self.acts_as_statusable(*args)
field_name = args.first
field_name_id = :"#{field_name}_id"
statuses = args.second
# Define getter
define_method(field_name) do
return nil if self.send(field_name_id).nil?
return statuses[self.send(field_name_id)]
end
# Define setter
define_method(:"#{field_name}=") do |v|
return self.send(:"#{field_name_id}=", statuses.index(v))
end
# Define a status? for each status,
# and a named scope .status
statuses.each do |status|
define_method(:"#{status}?") do
return self.send(field_name) == status
end
scope status, -> { where(["#{table_name}.#{field_name_id} = ?", statuses.index(status)]) }
end
validates field_name_id, :inclusion => { :in => (0...statuses.length).to_a }
end
end
现在,问题
我需要为每个使用acts_as_statusable
的类创建一个Class方法,名为status_index(sym)
,从状态返回status_id。
问题是我找到的用于定义类模型的每个解决方案都使用Module
,extend
或intend
,但我无法插入statuses
变量acts_as_statusable
加入这个模块...
我该怎么做?我使用Rails 4。
答案 0 :(得分:4)
您可以使用class_eval
和class_variable_set
class_variable_set :"@@#{field_name}_options", statuses
class_eval <<-RUBY
def self.status_index(sym)
@@#{field_name}_options.index(sym)
end
RUBY
在你的情况下会给出一个
@@status_options
类变量
和a
status_index(sym)
返回给定状态的偏移量的方法
答案 1 :(得分:2)
xlembouras - 您的解决方案效果很好!我有两个模型:
class User < ActiveRecord::Base
acts_as_statusable :status, [ :little, :big ]
end
class Price < ActiveRecord::Base
acts_as_statusable :status, [ :in_progress, :closed ]
end
'rails c'执行:
> User.status_index(:little)
=> 0
User.status_index(:big)
=> 1
> Price.status_index(:closed)
=> 1
> Price.status_index(:in_progress)
=> 0
我修改了结构,并使用了 ForgetTheNorm 编写的代码。 Rails 4,ActiveSupport ::关注使用
lib / active_record_extension.rb:
module ActiveRecordExtension
extend ActiveSupport::Concern
end
ActiveRecord::Base.send(:include, ActiveRecordExtension)
config / initializers / extensions.rb:
require "active_record_extension"
<强>配置/初始化/ active_record_monkey_patch.rb 强>
class ActiveRecord::Base
def self.acts_as_statusable(*args)
...
# ForgetTheNorm's CODE..
...
# xlembouras CODE:
class_variable_set :"@@#{field_name}_options", statuses
class_eval <<-RUBY
def self.status_index(sym)
@@#{field_name}_options.index(sym)
end
RUBY
end
end