Occasionally you will see the following code.
attr_accessor(*Hoge::ATTRIBUTES)
When I was talking to my colleague Mr. S, I was wondering why this writing method works, and when I looked it up, it was interesting, so I will summarize it.
-The array can be expanded by adding *
to the argument when calling the method.
・ ʻAtr_accessorcan receive multiple Symbols ・ When ʻattr_accessor (* Hoge :: ATTRIBUTES)
is set, the array is expanded and multiple Symbols are passed.
I think it's common to define a constant array of attributes in one class and reuse it in multiple classes.
・ ・. I don't know what you're saying in a sentence ...
I think it's faster to actually see it, so let's take a look at the code immediately.
class Hoge
ATTRIBUTES = %i[
name
age
].freeze
attr_accessor(*Hoge::ATTRIBUTES)
end
class Huga
attr_accessor(*Hoge::ATTRIBUTES)
end
In the case of this example, Hoge defines a constant array of attributes and Huga also uses it. This will reduce duplicate code. Convenient! !!
By now, I hope you have somehow understood how to use it. However, it remains a mystery why it works ...
I tried various things to see how it actually works.
*
when passing as an argumentclass Hoge
ATTRIBUTES = %i[
name
age
].freeze
attr_accessor(*Hoge::ATTRIBUTES)
end
class Huga
#In front of Hoge`*`Is erased
attr_accessor(Hoge::ATTRIBUTES) # == attr_accessor([:name, :age])
end
When I tried the above, the following error was displayed.
TypeError: [:name, :age] is not a symbol nor a string
Looking at the error message, it seems that it says that it only accepts symbol
or string
.
Looking at Reference,
[PARAM] name: Specify one or more Strings or Symbols.
It seems that an error occurred because the array could not be passed. The important part here is ** Specify one or more String or Symbol **.
*
is added in the first place?Somehow, I've come to understand that the behavior changes depending on whether or not \ * is added to the ** argument **. When investigating how it changes concretely, I found this article and expanded the array by adding \ * and passed it. I found that I could do it.
I will actually try it.
pry(main)> p([1,2])
[1, 2]
pry(main)> p(*[1,2])
1
2
Certainly, by adding *
, it seems that the array is expanded and passed.
By now, you may have already noticed, The part of ʻattr_accessor (* Hoge :: ATTRIBUTES) `is as follows.
class Hoge
ATTRIBUTES = %i[
name
age
].freeze
attr_accessor(*Hoge::ATTRIBUTES) # == attr_accessor(:name, :age)
end
class Huga
attr_accessor(*Hoge::ATTRIBUTES) # == attr_accessor(:name, :age)
end
In other words, the array was expanded by adding *
, and multiple Symbols were passed to ʻattr_accessor`.
As I mentioned earlier, the Reference
Specify one or more String or Symbol
Since it is possible to specify multiple Symbols, it seems that it was possible to set it without problems.
The more I knew about Ruby, the more new discoveries I made, and I thought again that it was an interesting language!
Recommended Posts