我用原来的答案咆哮着错误的树 - 我仍然有问题,但情节变粗
我将Ruby 1.8.7 / Rails 3.0.20项目升级到Ruby 2.1.2 / Rails 4.1.8
在代码中,我有一个委托了许多实例方法的类。
class Account < ActiveRecord::Base
has_one :subscription
delegate :trial?, :payg? :to => :subscription
end
我有一个装饰师
class AccountOverview < SimpleDelegator
def self.for(account)
new(account)
end
def description
if payg?
'Pay As You Go'
elsif trial?
'Free Trial'
else
'Subscription'
end
end
end
从视图中访问装饰器会显示错误消息:
ActionView :: Template :: Error(未定义的局部变量或方法`m&#39; for):
我寻找一个外来的m,但找不到一个。
我原以为它使用装饰器确定没有包含委托方法的方法,并且通过在类中定义委托函数来阻止错误:
def payg?
subscription.payg?
end
def trial?
subscription.trial?
end
但事实并非如此。我所看到的是第二次尝试渲染视图成功。但是,如果我重新启动服务器,我会再次收到错误。
我已尝试按照建议实例化SimpleDelegator,而不是从中派生,并发现我无法访问原始类中的方法。
在rails控制台中尝试:
class Test1
def testing
puts 'hi'
end
end
class Test2
def initialize(test)
SimpleDelegator.new(test)
end
def testing2
puts 'hello'
end
end
t = Test1.new
t.testing
hi
=> nil
h = SimpleDelegator.new(t)
h.testing
hi
=> nil
h = Test2.new(t)
h.testing
NoMethodError: undefined method `testing' for #<Test2:0x007fbea15d27a0>
但如果我使用
2.1.2 :008 > class Test2 < SimpleDelegator
2.1.2 :009?> def testing2
2.1.2 :010?> puts 'hello'
2.1.2 :011?> end
2.1.2 :012?> end
=> :testing2
2.1.2 :013 > h = Test2.new(t)
=> #<Test1:0x007fee090afc90>
2.1.2 :014 > h.testing
hi
=> nil
2.1.2 :015 > h.testing2
hello
=> nil
另外,我发现在视图中渲染失败的代码在控制台中工作(从SimpleDelegator派生):
a = Account.last
c = AccountOverview.new(a)
c.description
=> "Free Trial"
将课程简化为最简单的
class AccountOverview < SimpleDelegator
def self.for(account)
new(account)
end
def description
'Pay As You Go'
end
class Account < ActiveRecord::Base
end
仍然看到相同的错误,指的是缺少方法m
创建了一个全新的rails 4项目,并添加了相同的代码并针对相同的数据库运行 - 这没有任何错误,所以它在我的遗留设置中。
放弃并从代码中删除了SimpleDelegator,并使用委托将所需的函数映射到基础对象的实例变量,并且它现在正在工作。但不是很满意。
class AccountOverview
delegate :payg?, :trial? :to => :@account
def initialize(account)
@account = account
end
def description
if payg?
'Pay As You Go'
elsif trial?
'Free Trial'
else
'Subscription'
end
end
end