You can sometimes remove a lot of duplication by generating methods dynamic. In this episode I will show you how to create a plugin which does exactly that.
通过动态的生成方法可以减少大量的代码重复。这一节讲述如何创建一个rails插件来实现。
---
上一节讲过的用虚拟属性来实现文本框输入时间格式。我们将这个功能做成一个插件的形式:
首先用命令ruby script/generate plugin stringify_time
在vendor/plugin下生成一个stringify_time的插件。
下面修改其内容:
# models/task.rb
stringify_time :due_at
def validate
errors.add(:due_at, "is invalid") if due_at_invalid?
end
# stringify_time.rb
module StringifyTime
def stringify_time(*names)
names.each do |name|
define_method "#{name}_string" do
read_attribute(name).to_s(:db) unless read_attribute(name).nil?
end
define_method "#{name}_string=" do |time_str|
begin
write_attribute(name, Time.parse(time_str))
rescue ArgumentError
instance_variable_set("@#{name}_invalid", true)
end
end
define_method "#{name}_invalid?" do
instance_variable_get("@#{name}_invalid")
end
end
end
end
# init.rb
class ActiveRecord::Base
extend StringifyTime
end
stringify_time :due_at
def validate
errors.add(:due_at, "is invalid") if due_at_invalid?
end
# stringify_time.rb
module StringifyTime
def stringify_time(*names)
names.each do |name|
define_method "#{name}_string" do
read_attribute(name).to_s(:db) unless read_attribute(name).nil?
end
define_method "#{name}_string=" do |time_str|
begin
write_attribute(name, Time.parse(time_str))
rescue ArgumentError
instance_variable_set("@#{name}_invalid", true)
end
end
define_method "#{name}_invalid?" do
instance_variable_get("@#{name}_invalid")
end
end
end
end
# init.rb
class ActiveRecord::Base
extend StringifyTime
end
本文转自 fsjoy1983 51CTO博客,原文链接:http://blog.51cto.com/fsjoy/132165,如需转载请自行联系原作者