【发布时间】:2018-08-20 18:30:15
【问题描述】:
我有一个普通的 ruby 类 Espresso::MyExampleClass。
module Espresso
class MyExampleClass
def my_first_function(value)
puts "my_first_function"
end
def my_function_to_run_before
puts "Running before"
end
end
end
使用类中的某些方法,我想执行类似于 ActiveSupport 回调 before_action 或 before_filter 的 before 或 after 回调。我想在我的课堂上放这样的东西,它将在my_first_function之前运行my_function_to_run_before:
before_method :my_function_to_run_before, only: :my_first_function
结果应该是这样的:
klass = Espresso::MyExampleClass.new
klass.my_first_function("yes")
> "Running before"
> "my_first_function"
如何在 Rails 等普通 ruby 类中使用回调在每个指定方法之前运行方法?
编辑2:
感谢@tadman 推荐XY problem。我们遇到的真正问题是使用令牌过期的 API 客户端。在每次调用 API 之前,我们需要检查令牌是否过期。如果我们有大量的 API 函数,那么每次检查令牌是否过期会很麻烦。
这是示例类:
require "rubygems"
require "bundler/setup"
require 'active_support/all'
require 'httparty'
require 'json'
module Espresso
class Client
include HTTParty
include ActiveSupport::Callbacks
def initialize
login("admin@example.com", "password")
end
def login(username, password)
puts "logging in"
uri = URI.parse("localhost:3000" + '/login')
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Post.new(uri.request_uri)
request.set_form_data(username: username, password: password)
response = http.request(request)
body = JSON.parse(response.body)
@access_token = body['access_token']
@expires_in = body['expires_in']
@expires = @expires_in.seconds.from_now
@options = {
headers: {
Authorization: "Bearer #{@access_token}"
}
}
end
def is_token_expired?
#if Time.now > @expires.
if 1.hour.ago > @expires
puts "Going to expire"
else
puts "not going to expire"
end
1.hour.ago > @expires ? false : true
end
# Gets posts
def get_posts
#Check if the token is expired, if is login again and get a new token
if is_token_expired?
login("admin@example.com", "password")
end
self.class.get('/posts', @options)
end
# Gets comments
def get_comments
#Check if the token is expired, if is login again and get a new token
if is_token_expired?
login("admin@example.com", "password")
end
self.class.get('/comments', @options)
end
end
end
klass = Espresso::Client.new
klass.get_posts
klass.get_comments
【问题讨论】:
-
这种方法链接在实现方面变得非常丑陋,因为您必须重新定义
x以环绕x。 ActiveRecord 不包装方法,因为它有更好的内部调度系统。 -
为了避免XY Problems,创建一个比返回玩具字符串更能代表您的意图的示例可能更有意义。
-
@DogEatDog 您正在使用
ActiveSupport::Callbacks,但据我所知似乎没有使用它。您是否尝试过实现类似于their example 的东西? -
@DogEatDog 值得一试。也许你可以展示你之前的尝试
标签: ruby activesupport