网站的互动基于用户的输入。例如,如果用户选择“VISA”作为支付方式,他将被重定向到另一个要求信用卡号的控制器/动作。如果用户选择“Paypal”,则他/她将被重定向到外部网站。
为了可扩展性,我不是将所有逻辑放在动作本身中,而是考虑在对象中抽象它。实施例。
class Payment < ActiveRecord::Base; end
class VisaPayment < Payment
def process
...
end
end
class PaypalPayment < Payment
def process(controller)
...
controller.redirect_to "http://paypal.com"
end
end
class OrdersController < ApplicationController
def accept
params[:select].constantize.new.process(self)
end
end
这不起作用,因为像“redirect_to”这样的方法受到保护。这种代表团有成语或共同模式吗?
P.S。上面的代码是真正的想象力,而不是任何实际编码的摘录
答案 0 :(得分:1)
将控制器和模型逻辑分开。你以后会感谢我。
class OrdersController < ApplicationController
def accept
payment_path = case params[:select]
when 'visa': credit_card_controller_path(payment_type)
when 'paypal': 'http://www.paypal.com'
end
redirect_to payment_path
end
end
我喜欢这种方法的是它具有可读性和表现力。你确切知道发生了什么。代码并不比必要的更聪明。
答案 1 :(得分:0)
我会把它放到一个模块中并通过case-switch执行正确的方法:
case credit_card_system:
when "VISA" then: VisaToolbox::ExecuteTransaction(params)
when "MasterCard" then: MasterCardToolbox::ExecuteTransaction(params)
else
...
end
我会将其他东西放在一个控制器中......
答案 2 :(得分:0)
我不喜欢使用调用控制器代码的ActiveRecord代码。但是,如果你必须这样做,我会在付款中创建一个类方法,我将定义你的“过程部分”,然后在控制器中将instance_eval定义为:
class Foo
def self.define_process(&block)
@process = block
end
def self.apply_to(controller)
controller.instance_eval(&@process)
end
end
class SpecificFoo < Foo
define_process do
puts self.bar
end
end
class Something
attr_accessor :bar
end
something = Something.new
something.bar = 42
SpecificFoo.apply_to(something)
请注意,define_process'slock / iterator / coroutine中的代码是通过自我指向某个东西(在你的情况下是控制器)执行的,你可以访问受保护的和私有的东西。