ruby - 如何在Ruby的模块文件中引用类之外的类变量
问题描述
我正在尝试在模块文件的类中引用类变量:
require 'pry'
require_relative '../lib/concerns/memorable'
class Song
extend Memorable::ClassMethods
extend Findable::ClassMethods
attr_accessor :name
attr_reader :artist
@@songs = []
def initialize
@@songs << self
end
# def self.find_by_name(name)
# @@songs.detect{|a| a.name == name}
# end
def self.all
@@songs
end
# def self.reset_all
# self.all.clear
# end
#
# def self.count
# self.all.count
# end
def artist=(artist)
@artist = artist
end
def to_param
name.downcase.gsub(' ', '-')
end
end
module Findable
module ClassMethods
def all
@@artists
end
def all
@@songs
end
def find_by_name(name)
@@songs.detect{|a| a.name == name}
end
def self.find_by_name(name)
@@artists.detect{|a| a.name == name}
end
end
end
解决方案
实现共享行为的一种常见方法是需要某个接口。例如,核心Enumerable
模块需要您实现each
大多数方法才能工作。(有些方法sort
需要其中的元素来实现<=>
运算符。)
将此应用于您尝试做的事情,您可能需要扩展模块的类来实现all
方法。你不需要专门检查这个。假设该all
方法在那里,如果不是,用户将看到一个异常“NoMethodError:未定义方法'all' for Song:Class”,这很清楚。
module Findable
##
# The class extending Findable::ClassMethods must provide a method
# `all` which returns an Enumerable collection.
module ClassMethods
def find_by_name(name)
all.select { |instance| instance.name == name }
end
end
end
class Song
extend Findable::ClassMethods
attr_accessor :name, :artist
@@songs = []
def initialize
@@songs << self
end
def self.all
@@songs
end
end
foo = Song.new
foo.name = "foo"
bar = Song.new
bar.name = "bar"
Song.all
#=> [#<Song:0x0055828c8ca3e8 @name="foo">, #<Song:0x0055828c8cc9e0 @name="bar">]
Song.find_by_name("foo")
#=> [#<Song:0x0055828c8ca3e8 @name="foo">]
推荐阅读
- android - 如何在 Android 中设置 3 级菜单布局
- java - 将 Tiles 与 Springmvc 集成时出现错误 404
- android-room - Android Architecture Components(MVVM) - 使用存储库模式处理远程和本地数据的理想方式
- azure - 适用于 Dynamics NAV 和 AZURE Active Directory 的 SSO
- python - 如何知道 django 模型中 pk 的值
- dataframe - pyspark 为每一行创建一个数据框,一些列值需要设置为 1
- html - 网页不会适应浏览器窗口大小
- neo4j - 在 Neo4j 中收集非常慢
- groovy - Groovy 星型导入和“部分”包的使用
- algorithm - 对从小到大的物体进行空间分区/碰撞检测的最佳算法?