I have a simple class that, on initialization, takes between one and eight parameters. It sets the accessors to these to use later. Rubocop is trying to arrest me for the ABC being too high, but I'm not sure if there's actually anything wrong with what I've done. Is this a case where I just disable the inspection on my initialize?
class Foo
attr_accessor :one, :two, :three, :four
attr_accessor :five, :six, :seven, :eight
def initialize(p={})
@one = p[:one] if p[:one].present?
# ...
@eight = p[:eight] if p[:eight].present?
end
end
My only thought on reducing size would be to do something like iterating through all my attr_accessors on initialize, seeing if there is a corresponding symbol passed through in the has, and if so assigning it.
class Foo
attr_accessor :one, :two, :three, :four
attr_accessor :five, :six, :seven, :eight
def initialize(p={})
instance_variables.each do |variable|
send("@#{variable}") = p["#{send(variable)}".to_sym] if p["#{send(variable)}".to_sym].present?
end
end
end
But this seems kind of weak.
Here is one of the ways to achieve what you are trying to do:
class Foo
attr_accessor(*%i[one two three four five six seven eight])
def initialize(p = {})
p.keys.each { |k| instance_variable_set("@#{k}", p.fetch(k, nil)) }
end
end
Check out for Hash#fetch
method.
You can also use it to just access the key-value pairs of p
variable, if you instead of 8 variables decide to go with one (@p
)
Just out of curiosity wrote this version (some meta programming used) - it will dynamically add attr_accessor
for added instance variables:
class Foo
def initialize(p = {})
p.keys.each do |k|
instance_variable_set("@#{k}", p.fetch(k, nil))
self.class.__send__(:attr_accessor, k)
end
end
end
What is happening, is we take provided to initialize
method argument (hash p
), get its keys and create instance variables from them, assigning each variable with value corresponding to the key. Then we're defining attr_accessor
for each of the keys.
a = Foo.new(a: 2, b: 3)
#=> #<Foo:0x00000002d63ad8 @a=2, @b=3>
You shouldn't assign each of those as different variables. You should rather save that to a variable as a single hash, and access the hash when you need the values. In fact, you already seem to have a variable p
. So keep that as @p = p
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With