我的Rails应用程序中有一个私有方法来连接到Amazon S3,执行一个传递的代码块,然后关闭到S3的连接.看起来像这样
def S3 AWS::S3::Base.establish_connection!( :access_key_id => 'Not telling',:secret_access_key => 'Really not telling' ) data = yield AWS::S3::Base.disconnect data end
它被称为这样(作为示例);
send_data(S3 {AWS::S3::S3Object.value("#{@upload_file.name}",'bucket')},:filename => @upload_file.name)
我在控制器和模型中以多种方式调用此方法,因此将其作为私有方法包含在这两个类中.这工作正常,我很高兴,但它不是很干.
我如何使这种方法可以访问我的模型和控制器,但只有代码出现一次?这更像是Rails问题的Ruby问题,反映了我对OOP的新意.我猜测一个模块或混合是答案,但是直到现在还没有真正使用这些模块,需要一些手持.
谢谢.
解决方法
模块用于ruby中的3种不同的东西.首先是命名空间在模块中具有类或常量定义不会与该模块之外的类或常量相冲突.这样的东西
class Product def foo puts 'first' end end module Affiliate class Product puts 'second' end end p = Product.new p.foo # => 'first' p = Affiliate::Product.new p.foo # => 'second'
模块的第二个用途是将其他地方真的没有地方的方法粘贴在一起.你也可以在类里面做一些这样的事情,但是使用一个模块来告诉人们阅读代码并不意味着被实施.这样的东西
module Foo def self.bar puts 'hi' end end Foo.bar #=> 'hi'
最后(最令人困惑的是)模块可以包含在其他类中.以这种方式使用它们也被称为混合,因为您将所有方法“混合”到任何包含的内容中.
module Foo def bar puts 'hi' end end class Baz include Foo end b = Baz.new b.bar #=> 'hi'
Mixins实际上是一个比较受欢迎的主题,然后我在这里讨论,但是更深入的可能会令人困惑.
现在,对我来说,S3似乎是一个真正属于控制器的东西,因为控制器通常是处理传入和传出连接的事情.如果是这种情况,我将在应用程序控制器上拥有一个受保护的方法,因为所有其他控制器都可以访问,但仍然是私有的.
如果你有一个很好的理由在模特儿,我会去混合.就像是
module AwsUtils private def S3 AWS::S3::Base.establish_connection!\ :access_key_id => 'Not telling',:secret_access_key => 'Really not telling' data = yield AWS::S3::Base.disconnect data end end
如果你把它放在lib / aws_utils.rb中,你应该可以通过在控制器和模型中添加include AwsUtils来使用它. Rails知道在lib中查找类和模块,但只有当名称匹配时(大写).我称之为AwsUtils,因为我知道哪些rails会看到(aws_utils.rb),而且老实说,我不知道S3Utils将需要什么?-)
如果我不清楚某事,请随时询问更多信息.模块往往是ruby中的一个,虽然惊人,但对新手来说,是彻头彻尾的困惑.