ruby-on-rails - 如何在 Rails 中使一个方法对我的 Controller 和模型都可用?

标签 ruby-on-rails ruby oop

我的 Rails 应用程序中有一个私有(private)方法来连接到 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)

我在我的 Controller 和模型中以多种方式调用此方法,因此将它作为私有(private)方法包含在两个类中。这工作正常,我很满意,但不是很干。

如何让我的模型和 Controller 都可以访问此方法,但代码只出现一次?这更像是一个 Ruby 问题而不是 Rails 问题,反射(reflect)了我对 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 似乎是真正属于 Controller 的东西,因为 Controller 通常是处理传入和传出连接的东西。如果是这样的话,我会在应用程序 Controller 上有一个 protected 方法,因为所有其他 Controller 都可以访问它,但仍然是私有(private)的。

如果你也有充分的理由让它出现在模型中,我会选择混合。有点像

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,您应该能够通过在 Controller 和模型中添加 include AwsUtils 来使用它。 Rails 知道在 lib 中查找类和模块,但前提是名称匹配(在大写情况下)。我将其命名为 AwsUtils,因为我知道 rails 在看到 (aws_utils.rb) 时会寻找什么,老实说,我不知道 S3Utils 需要什么 ;-)

如果我对某些事情不清楚,请随时询问更多信息。模块往往是 ruby​​ 中的一种东西,虽然令人惊叹,但对新手来说却完全令人困惑。

关于ruby-on-rails - 如何在 Rails 中使一个方法对我的 Controller 和模型都可用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3562131/

相关文章:

ruby - 相当于Python中Ruby中的动态导入语句?

oop - mixin 可以访问它们在 Dart 中混合的类的状态吗?

java - Java 是 100% 面向对象的吗?

ruby-on-rails - rails has_one 一个 has_many 关联

mysql - 续集 JOIN 和 WHERE

ruby-on-rails - Heroku 上的 Rails 5.2 - 缺少 Coffee_script

ruby-on-rails - 如何解决 "Can' t mass-assign protected attributes : translations_attributes"error?

c++ - 当数组从函数返回时,为什么我不能使用基于范围的循环?

ruby-on-rails - 我如何调用 Rake 中的另一个任务

ruby-on-rails - 将包含 AM/PM 的 12 小时时间字符串转换为 24 小时时间