我使用gem来管理gmail api集成的某些属性,并且我对它的工作方式非常满意。
我想添加一些本地方法来处理该gem中使用的Gmail :: Message类。
即。我想做这样的事情。
models/GmailMessage.rb
class GmailMessage < Gmail::Message
def initialize(gmail)
#create a Gmail::Message instance as a GmailMessage instance
self = gmail
end
def something_clever
#do something clever utilising the Gmail::Message methods
end
end
我不想坚持下去。但显然我无法以这种方式定义自我。
为了澄清,我想采用Gmail :: Message的实例并创建一个GmailMessage实例,该实例是该其他消息的直接副本。
然后我可以运行@ gmail.subject和@ gmail.html之类的方法,还可以运行@ gmail.something_clever ...并在必要时保存本地属性。
我完全疯了吗?
答案 0 :(得分:2)
您可以使用mixin
的概念,其中您在另一个类中包含Module
,以通过其他功能对其进行增强。
以下是如何做到这一点。为了创建一个完整的工作示例,我创建了类似于代码库中的模块。
# Assumed to be present in 3rd party gem, dummy implementation used for demonstration
module Gmail
class Message
def initialize
@some_var = "there"
end
def subject
"Hi"
end
end
end
# Your code
module GmailMessage
# You can code this method assuming as if it is an instance method
# of Gmail::Message. Once we include this module in that class, it
# will be able to call instance methods and access instance variables.
def something_clever
puts "Subject is #{subject} and @some_var = #{@some_var}"
end
end
# Enhance 3rd party class with your code by including your module
Gmail::Message.include(GmailMessage)
# Below gmail object will actually be obtained by reading the user inbox
# Lets create it explicitly for demonstration purposes.
gmail = Gmail::Message.new
# Method can access methods and instance variables of gmail object
p gmail.something_clever
#=> Subject is Hi and @some_var = there
# You can call the methods of original class as well on same object
p gmail.subject
#=> "Hi"
答案 1 :(得分:1)
以下应该工作:
class GmailMessage < Gmail::Message
def initialize(extra)
super
# some additional stuff
@extra = extra
end
def something_clever
#do something clever utilising the Gmail::Message methods
end
end
GmailMessage.new # => will call first the initializer of Gmail::Message class..
答案 2 :(得分:1)
我不确定为什么你不能只有一个简单的包装类...
class GmailMessage
def initialize(message)
@message = message
end
def something_clever
# do something clever here
end
def method_missing(m, *args, &block)
if @message.class.instance_methods.include?(m)
@message.send(m, *args, &block)
else
super
end
end
end
然后你可以......
@my_message = GmailMessage.new(@original_message)
@my_message将正确响应@original_message支持的所有方法,您可以将自己的方法添加到类中。
编辑 - 感谢@ jeeper在评论中的观察
答案 3 :(得分:1)
根据其他海报所说的内容,您可以在ruby中使用内置类SimpleDelegator来包装现有消息:
require 'delegate'
class MyMessage < SimpleDelegator
def my_clever_method
some_method_on_the_original_message + "woohoo"
end
end
class OriginalMessage
def some_method_on_the_original_message
"hey"
end
def another_original_method
"zoink"
end
end
original = OriginalMessage.new
wrapper = MyMessage.new(original)
puts wrapper.my_clever_method
# => "heywoohoo"
puts wrapper.another_original_method
# => "zoink"
如您所见,包装器自动将方法调用转发给包装对象。
答案 4 :(得分:-1)
这不是最漂亮的,但它有效......
class GmailMessage < Gmail::Message
def initialize(message)
message.instance_variables.each do |variable|
self.instance_variable_set(
variable,
message.instance_variable_get(variable)
)
end
end
def something_clever
# do something clever here
end
end
感谢所有帮助人员。