我有一个代码片段,它生成一个模型属性名称和setter等价物的扁平数组,然后使用splat运算符将此数组作为变量传递给Module.delegate()
,将所有User.attributes
委托给BaseUser类。这很好。
请参阅https://apidock.com/rails/Module/delegate
class BaseUser
include ActiveModel::Model
attr_accessor :user
# The code snippet described above
delegate(*::User.attribute_names.map {|attr| [attr, "#{attr}="] }.flatten, to: :user)
def initialize(user_attributes)
@user = ::User.new(user_attributes)
end
end
现在,我希望将此片段重新编写为可以将[ModelName] < ActiveRecord::Base
类常量作为参数的方法。但是,我的尝试(下面)导致了几个语法错误。我哪里错了?
def delegate_getters_and_setters(model)
delegate(*::model.attribute_names.map {|attr| [attr, "#{attr}="] }.flatten, to: model.downcase.to_sym)
end
感谢您的帮助!
修改
以下是Sublime Text 3突出显示的语法错误。
-:6: syntax error, unexpected tIDENTIFIER, expecting tCONSTANT
delegate(*::model.attribute_names.map {|attr| ...
^
-:6: syntax error, unexpected tLABEL, expecting '='
...ttr, "#{attr}="] }.flatten, to: model.downcase.to_sym)
... ^
-:6: syntax error, unexpected ')', expecting keyword_end
答案 0 :(得分:4)
::model
毫无意义。 model
是一个局部变量。只需删除它前面的双冒号:
delegate(*model.attrib......
答案 1 :(得分:3)
现在,我希望将此代码段重新编写为可以将
[ModelName] < ActiveRecord::Base
类常量作为参数的方法。
您不能将常量作为参数。您只能将对象作为参数。常量不是对象。
但是,我的尝试(下面)导致了几个语法错误。我哪里错了?
您假设您将常数作为参数。但你没有。有人打电话时
delegate_setters_and_getters(Foo)
你没有得到常量Foo
作为参数。你不能,因为常量Foo
不是一个对象。相反,常量Foo
在调用站点被取消引用,并且您可以在调用站点将任何对象Foo
解析为(可能是一个类)作为参数。
它与任何其他表达式完全相同。如果你打电话
delegate_setters_and_getters(foo)
你不传递局部变量foo
作为参数,你传递foo
引用的对象作为参数。 (事实上,你无法传递局部变量作为参数,即使你想要,因为变量不是对象。)
如果你打电话
delegate_setters_and_getters(bar.baz)
你不传递方法调用bar.baz
作为参数,你在通过解除引用局部变量baz
获得的对象上调用方法bar
然后将该方法调用的返回值作为参数传递。 (同样,方法调用不是对象,所以即使你想要也不能传递它们。)
答案 2 :(得分:2)
除了@mudasobwa说的话:
::
是常量完全限定名称(FQN)语法的一部分。前导::
有助于消除名称解析的歧义。
在您的情况下,delegate_getters_and_setters
常量名称已经解析,model
是对常量 * 的引用,无论它是什么。
*其中“引用常量”我的意思是“引用常量指向的同一个对象”,当然。