【问题标题】:Set instance variables using hash [duplicate]使用哈希设置实例变量
【发布时间】:2018-08-09 23:58:11
【问题描述】:

我正在尝试设置实例变量,而不用单个设置器对我的对象进行穿孔。我想使用我称为 group setter 的方法。

我想遍历对象的instance_variables,对于那些与预先提供的哈希中的键匹配的对象,使用instance_variable_set 单独设置它们。我不想遍历哈希对来限定实例变量的设置,因为这是一个安全问题。

这是我的代码:

class Pickle
  attr_accessor :id, :name, :colour, :status

  def initialize()
    @id = nil
    @name = nil
    @colour = 'green'
    @status = 'new'
  end

  def into_me(incoming)
    instance_variables.each do |i|
      puts i
      puts incoming[i]
      instance_variable_set(i, incoming[i])
    end
  end
end

a = Pickle.new
# >> @id
# => #<Pickle:0x00007fef6782c978 @colour="green", @id=nil, @name=nil, @status="new">

newstuff = {:name => 'Peter', :colour => 'red'}
a.into_me(newstuff)
# >> @name
# >> @colour
# >> @status
# => #<Pickle:0x00007fef6782c978 @colour=nil, @id=nil, @name=nil, @status=nil>

它很接近,但它似乎无法在哈希中找到提供的键/值对。我不明白为什么它不能使用提供的哈希来查找符号作为键。

我做错了什么?

由于instance_variable 变量类型不匹配,它不是重复的并且之前已回答。如果你读了这篇文章,上面写着It's close, but it can't seem to find the provided key/value pair in the hash. I don't see why it can't use the provided hash to look up symbols as keys.

【问题讨论】:

  • 因为:name@name不一样
  • @Joe :id = nil in initialize() 会引发错误。不清楚你指的是哪个。
  • puts incoming[i] 永远不会匹配,因为来自instance_variables.eachi 正在返回像@name 这样的项目,但是您传入的哈希具有像:name 这样的符号键
  • 不能解析成正确的形式吗?
  • 你能解释一下为什么迭代属性与哈希是一个更好的解决方案吗?你可以在这里弄乱字符串,去掉@,然后调用.to_sym 来匹配它们,但这似乎很混乱,因为好处不清楚。

标签: ruby instance-variables


【解决方案1】:

我这样做的一种方法是翻转作业,例如

def initialize(**h)
    h.each do |k, v|
        setter = "#{k}="
        next unless respond_to? setter # skip if we don't have a setter for this key
        public_send setter, v
    end
end

这会处理传入的哈希并为在哈希中找到的每个调用分配操作。它将跳过任何没有显式设置器的值。

【讨论】:

  • 是的,这就是我要反转焦点的意思。我不喜欢这样,因为传入的散列很松散。我想通过将其实现为方法来过滤新的实例 var 分配,而不是使用哈希迭代的推送。
  • 为什么这是一个“安全问题”?
  • 提供的哈希来自外部。它可能是表单参数,或者来自其他地方。为了避免必须将散列限定为安全,使用遍历instance_variables 的方法更容易。这就是为什么我把它放在OP中。我不想开始为传入的哈希编写验证。这违背了所有这一切的意义。
  • “安全”是否意味着哈希不包含您声明的设置器之外的值?这很容易处理,无需手动验证哈希。见编辑。
  • 嗯,就是这样。你不知道,也不想知道,因为有人以某种方式注射。 setter 是我试图完成的方法,从方法向外,通过询问哈希而不是将哈希推入对象。啊,我看到了你的内部限定符。我会检讨。谢谢。
猜你喜欢
  • 2010-12-01
  • 2020-08-30
  • 2010-12-09
  • 2019-02-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多