Ruby - 代码有人解释以下代码

问题描述 投票:0回答:3

我在a library中有以下代码,有人可以解释代码(“#{k} =”)在下面的代码中的含义是什么?

if respond_to?("#{k}=")
  public_send("#{k}=", v)
else
  raise UnknownAttributeError.new(self, k)
end

我理解respond_to是Ruby中的默认函数,但没有给出这种语法的定义/解释,请帮助我们。

编辑:

我得到了上述代码的异常(unknown attribute 'token' for PersonalAccessToken. (ActiveModel::UnknownAttributeError)

/opt/gitlab/embedded/lib/ruby/gems/2.5.0/gems/activemodel-5.0.7.1/lib/active_model/attribute_assignment.rb:40:in `block in _assign_attributes'
/opt/gitlab/embedded/lib/ruby/gems/2.5.0/gems/activemodel-5.0.7.1/lib/active_model/attribute_assignment.rb:48:in `_assign_attribute': unknown attribute 'token' for PersonalAccessToken. (ActiveModel::UnknownAttributeError)

所以考虑k为'token',在哪种情况下我会得到异常(在哪种情况下它会进入else状态?)

ruby-on-rails ruby ruby-on-rails-3 rubygems
3个回答
1
投票

此代码public_send("#{k}=", v)动态调用存储在k变量中的setter。请考虑以下示例:

class FooBarBaz
  attr_accessor :foo, :bar, :baz

  def set_it what, value
    public_send("#{what}=", value)
  end
end

它大致相当于:

  def set_it what, value
    case what
    when "foo" then public_send("foo=", value)
    when "bar" then public_send("bar=", value)
    when "baz" then public_send("baz=", value)
    end
  end

它大致相当于:

  def set_it what, value
    case what
    when "foo" then self.foo=(value)
    ...
    end
  end

它大致相当于:

  def set_it what, value
    case what
    when "foo" then self.foo = value
    ...
    end
  end

提前调用respond_to?以检查在这个实例中是否确实为此k定义了setter,以防止有点像:

FooBarBaz.new.set_it :inexisting, 42
#⇒ NoMethodError: undefined method `inexisting=' for #<FooBarBaz:0x0056247695a538>

此答案中类的修改版本正确:

class FooBarBaz
  attr_accessor :foo, :bar, :baz

  def set_it what, value
    public_send("#{what}=", value) if respond_to?("#{what}=")
  end
end

它没有抛出异常。

FooBarBaz.new.set_it :inexisting, 42
#⇒ nil

0
投票

“#{}”是ruby中的字符串插值。例如:

k = 'world'
puts "hello #{k}"
# hello world

因此,在您的示例中,它看起来像是在创建一个值为k和=的字符串

EG

k = 'something'
"#{k}="
# something=

如果你想知道k是什么,你可以在上面的行中添加puts k.to_s然后运行代码并检查你的控制台。

更好的是,如果你使用像RubyMine这样的东西,只需使用调试器并在该行上粘贴一个断点。


-1
投票

我想你在_assign_attribute看到了this docs方法

k是'key'的缩写含义,v是'value'的同义词

"#{k}="是字符串文字对动态方法的某种方法名称。

它可能是“更新”或“创建”,“拆分”,其他任何东西。

等号(“=”)是指分配像这样的user.attributes = { :username => 'Phusion', :is_admin => true }的方法

在上面的例子中,“k”是.attributes,“k =”是attributes=,“v”是{ :username => 'Phusion', :is_admin => true }

public_send是在公共范围内发送方法的方法。

因此,public_send("#{k}=", v)是在公共方法中调用名称为“k”的方法的含义,并且此方法将被指定为“v”作为值。

我希望这个解释对你有所帮助。


添加一些示例进行评论

k是程序员的输入,因此它与Class或Module中的方法名称不匹配。

在现实中,有一些常见的错误案例。

class User
  # this attribute can be called from a instance of User
  attr_accessor :name
end

# this causes a error when call assign_attribute
User.new.wrong_name

# this is fine
User.new.name

assignment method reference

© www.soinside.com 2019 - 2024. All rights reserved.