attr_访问器

rxztt3cl  于 2021-09-29  发布在  Java
关注(0)|答案(1)|浏览(273)

我试图找到一种基于父类动态生成子类的方法。在我的特定情况下,我希望每个示例变量都有attr_访问器,在父类中初始化并在子类中继承。我的类是三个不同的模型,代表数据库中三个不同的表。
“record”是我的父类,我想在其中存储和编写所有代码post”和“user”是继承的子类。
我的代码

class Record

  attr_reader :id
  # attr_accessor

  def initialize(**params)
    @id = params[:id]
    instance_variable_set("@#{params.keys[0]}", params.values[0])
    instance_variable_set("@#{params.keys[1]}", params.values[1])
    instance_variable_set(:@votes, params["votes"] || 0) if instance_of?(Post)
    # p self.title
  end

我想要实现的是设置attr_accessor,例如在我想要调用的子类“post”中

post = Post.new(title: "New post", url: "some url")
puts post.title

我可以访问title示例变量而不引发nomethoderror
有人能给我指点迷津吗?谢谢

2nc8po8w

2nc8po8w1#

你是在倒退。父类不必知道或实现其子类的特定逻辑。

class Record
  attr_reader :id

  def initialize(**attributes)
    attributes.each do |key, value|
      send("#{key}=", value)
    end
  end
end
class Post < Record
  attr_accessor :title
  attr_accessor :votes
end
irb(main):066:0> Post.new(id: 1, votes: 10, title: "Hello World").title
=> "Hello World"
``` `attr_accessor` 只是定义方法的元编程便利,因此无论如何都可以继承访问器方法。但是,如果您正在编写对象关系管理器之类的东西,那么您需要定义自己的宏方法来定义属性,以便跟踪类的属性:

module Attributes
def self.included(base)
base.extend(ClassMethods)
base.class_eval do
@attributes ||= {}
end
end

assigns the passed attributes to the instance

def initialize(**attributes)
attributes.each do |key, value|
send "#{key}=", value
end
end

gets all the attributes of an instance

def attributes
self.class.attributes.keys.each_with_object(Hash.new) do |key, hash|
hash[key] = send(key)
end
end

module ClassMethods
# Inherits the attributes of the parent class
def inherited(subclass)
attributes.tap do |parent_attributes|
subclass.class_eval do
@attributes ||= {}.merge(parent_attributes)
end
end
end

# defines an attribute that is inherited
def attribute(name, type = nil,**kwargs)
  @attributes[name] = { type: type }.merge(kwargs)
  attr_accessor name
end

def attributes
  @attributes
end

end
end

class Record
include Attributes
attribute :id, Integer
end

class Post < Record
attribute :title, String
attribute :votes, Integer
end

irb(main):101:0> Post.new(votes: 10, title: "Hello World").attributes
=> {:id=>nil, :title=>"Hello World", :votes=>10}

这将属性定义存储在一个类示例变量中,该变量允许您附加“元数据”,该元数据为以后需要的功能打开,例如类型转换、序列化和脏跟踪。

相关问题