Ruby:通过使用模块扩展 File 来处理文件格式

2024-01-23

一旦我有一个File http://ruby-doc.org/core-2.3.1/File.html例如,我想检查它是否匹配文件格式并且extend http://ruby-doc.org/core-2.3.1/Object.html#method-i-extend该实例具有相应的方法:

module MP3
  def self.extended(base)
    raise "Can only extend a File" unless base.is_a?(File)
    raise "Incorrect file format" unless is_mp3?(base)
  end

  def self.is_mp3?(file)
    # Full metadata check if it is a MP3 format
  end

  def year
    # Extract year from metadata
  end
end

song = File.new("song.mp3")
if MP3.is_mp3?(song)
  song.extend(MP3)
  puts song.ctime # Original File method
  puts song.year  # Extended MP3 method
end

picture = File.new("picture.jpg")
MP3.is_mp3?(picture) #=> False
picture.extend(MP3)  #=> raise "Incorrect file format"

我想这不是传统的,但我的需求是:

  • 能够处理多种文件格式。
  • 在知道文件格式之前打开文件。
  • 重复使用相同的File实例,而无需创建新对象。 (见下文)
  • 两个原件都有File方法和格式化同一对象中的特定方法。
  • 添加相应方法之前请检查文件格式是否正确。

这种做法正确吗?

这个问题是一个后续问题上一个问题 https://stackoverflow.com/questions/39934261/ruby-do-something-when-extending-an-instance-with-a-module.

我想扩展现有的File实例而不是创建一个新实例,因为我正在使用包装器File,它将整个文件保存在 RAM 中(从不允许顺序访问的磁带驱动器读取)。


您所提议的内容将太多选择要使用哪个类的逻辑放入调用者的代码中。每次添加新文件类型时,都需要更改使用代码的所有位置。

相反,使用工厂模式 https://en.wikipedia.org/wiki/Factory_method_pattern。编写一个类(工厂)来检查文件名并决定要做什么。除了我要使用更优越的Pathname http://ruby-doc.org/stdlib-2.3.1/libdoc/pathname/rdoc/Pathname.html.

require "pathname"

class Pathname::Format
  def self.from_filename(filename)
    path = Pathname.new(filename)

    from_pathname!(path)

    return path
  end

  def self.from_pathname!(path)
    case path.extname
    when ".mp3"
      path.extend(MP3)
    when ".jpg"
      path.extend(JPG)
    end

    return
  end
end

重点是将该决定放入工厂类中,而不是调用代码中。

然后你就可以编写你的模块了。

module JPG
  def type
    return "JPG"
  end
end

module MP3
  def type
    return "MP3"
  end

  def year
    puts "MP3 year called"
  end
end

现在调用者只使用工厂。

# From a filename
song = Pathname::Format.from_filename("song.mp3")
puts song.ctime # Original File method
puts song.year  # Extended MP3 method

# From a Pathname
picture = Pathname.new("picture.jpg")
Pathname::Format.from_pathname!(picture)
puts picture.type

与其使用大量特殊方法来检查对象是否属于特定类型,不如检查type方法,检查它是否是一种模块,或者依赖鸭子打字 https://stackoverflow.com/questions/4205130/what-is-duck-typing#4205163.

if song.type == "MP3"
  puts song.year
end

if song.kind_of?(MP3)
  puts song.year
end

if song.respond_to?("year")
  puts song.year
end
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Ruby:通过使用模块扩展 File 来处理文件格式 的相关文章

  • 如何阻止与 RSpec 和 Capybara 的外部连接?

    在我的 Rails 项目中 我想编写非理想条件的测试 例如缺乏互联网连接或超时 例如 我正在使用 gem 来联系 API 并且希望确保在我的应用程序和外部 API 之间存在连接问题时能够正确处理错误 我已经可以通过用录像机制作固定装置并从
  • SSL_connect 返回=1 errno=0 状态=SSLv3 读取服务器证书 B:证书验证仅在代理时失败

    这篇文章几乎重复了许多其他帖子 包括Rails 4 和 Ruby 2 Net HTTP SSL 请求 OpenSSL SSL SSLError SSL connect returned 1 errno 0 state SSLv2 v3 re
  • 红宝石边缘情况

    ruby 有一些边缘情况很难解释 因为解析会带来一些有趣的问题 我在这里列出其中两个 如果您知道更多 请添加到列表中 def foo 5 end this one works if tmp foo puts tmp to s end How
  • “没有可用的二元红宝石”是什么意思?

    每当我使用rvm install x x x 即使安装成功 我也会收到此警告 No binary rubies available for osx 10 12 x86 64 ruby 2 4 0 Continuing with compil
  • 从 Ruby 中的 DateTime 变量获取时间

    我在 ruby 中工作 我有一个包含数据库中今天的日期时间的对象 我只想要时间截断数据 我怎样才能得到那个 Try 日期时间 strftime http www ruby doc org stdlib 1 9 3 libdoc date r
  • 如何向 Time.now 添加两周?

    如何在 Ruby 中向当前 Time now 添加两周 我有一个使用 DataMapper 的小型 Sinatra 项目 在保存之前 我有一个字段填充了当前时间加上两周 但未按需要工作 任何帮助是极大的赞赏 我收到以下错误 NoMethod
  • Watir 更改 Mozilla Firefox 首选项

    我正在使用 Watir 运行 Ruby 脚本来自动执行一些操作 我正在尝试自动将一些文件保存到某个目录 因此 在我的 Mozilla 设置中 我将默认下载目录设置为桌面并选择自动保存文件 然而 当我开始运行脚本时 这些更改并未反映出来 似乎
  • 如何从 Ruby 程序发送邮件?

    我想从 Ruby 应用程序发送电子邮件 核心语言中是否有调用来执行此操作 或者是否有我应该使用的库 最好的方法是什么 如果你不想使用行动邮递员 http wiki rubyonrails org rails pages ActionMail
  • Heroku 部署错误

    在 Windows 环境中 尝试部署到 Heroku 时出现以下错误 C Ruby lib ruby gems 1 8 gems heroku 1 9 13 lib heroku commands base rb 32 in 没有这样的文件
  • 多重要求和允许强参数rails 4

    在下面的情况下 我尝试使用强参数 我想要求email address password并允许remember me fields 但像下面这样使用它只允许最后一行在方法示例中 在下面的情况下 它只需要params permit rememb
  • 我在 Rails 中使用了保留字吗?

    这是我的模型 class Record lt ActiveRecord Base belongs to user belongs to directory end class Directory lt ActiveRecord Base h
  • REXML - 如何提取单个元素

    我正在用 ruby 编写一些验收测试 其中涉及断言响应 XML 中值的存在 我的 XML 是这样的
  • 在 ruby​​ 中下载多个 FTP 文件,如 d*.txt

    我需要连接到 ftp 站点并下载一堆名为 D txt 的文件 最多 6 个 你能帮我用 Ruby 编写这个代码吗 下面的代码只是 ftp Net FTP new ftp server site ftp login user pwd ftp
  • Ruby require 'file' 不起作用,但 require './file' 可以。为什么?

    我有一个充满 ruby 文件的文件夹 当我尝试使用位于同一目录中的另一个文件中的一个文件时require file 我得到一个LoadError但是当我使用require file 一切正常 有人可以向我解释为什么会发生这种情况吗 如果有什
  • 红宝石接球和效率

    catch在 Ruby 中意味着跳出深度嵌套的代码 在 Java 中 例如用Java也可以达到同样的效果try catch用于处理异常 但它被认为是糟糕的解决方案 而且效率非常低 在 Ruby 中 我们有处理异常的方法begin raise
  • Ruby/Rails 集合到集合

    我有两个表与一个连接表连接 这只是伪代码 Library Book LibraryBooks 我需要做的是 如果我有一个图书馆的 id 我想获取该图书馆拥有的所有书籍所在的所有图书馆 因此 如果我有图书馆 1 图书馆 1 中有书籍 A 和
  • RoR - Rails 中的大文件上传

    我有一个 Rails Web 应用程序 允许用户上传视频 视频存储在 NFS 安装的目录中 当前的设置适用于较小的文件 但我也需要支持大文件上传 最多 4GB 当我尝试上传 4GB 文件时 它最终会发生 但从用户体验的角度来看很糟糕 上传开
  • Ruby 是否有一个 Expect 等效 gem?

    Ruby 是否有一个 Expect 等效 gem 我尝试在 code google 和 ruby gems org 上搜索 但遗憾的是它没有出现 FYI Expect http en wikipedia org wiki Expect是一个
  • Shoulda/RSpec 匹配器 - 条件验证

    在我的代码中 我使用 Shoulda 匹配器进行了以下验证 效果很好 it should validate presence of name 在我的模型中 我已将条件添加到验证中 validates presence of name if
  • 使用哈希参数进行 DRY Ruby 初始化

    我发现自己经常在构造函数中使用哈希参数 尤其是在为配置或最终用户将接触到的其他 API 编写 DSL 时 我最终做的是类似以下的事情 class Example PROPERTIES name age PROPERTIES each p a

随机推荐