我发现自己在课堂上初始化了很多变量,我想知道是否有更简单的方法可以做到这一点。一旦你获得了20个变量,就会变得有点多余。
class Car
attr_reader :make,
:model,
:year,
:id
def initialize(args)
@make = args["make"]
@model = args["model"]
@year = args["year"]
@id = args["id"]
end
end
谢谢!
答案 0 :(得分:1)
如果您特别关注immutable_struct
,有一个名为attr_reader
的宝石
https://github.com/iconara/immutable_struct
class Spaceship < ImmutableStruct.new(:name, :max_speed)
end
ship = Spaceship.new('Enterprise', 'Warp 9')
puts ship.max_speed # => Warp 9
ship.max_speed = '299792458 m/s' # raises NoMethodError
但如果你对attr_accessor
没事,普通的Struct
应该这样做。
答案 1 :(得分:1)
您也可以这样做:
class Car
def initialize(args)
args.each do |key, value|
instance_variable_set("@#{key}", value)
end
end
end
car = Car.new({name: 'My car', make: 'BMW'})
p car #<Car:0x007fe80c8875d8 @name="My car", @make="BMW">
答案 2 :(得分:1)
您可以使用一些动态技术,使您的代码具有灵活的外观示例:
class Car
def initialize(args = {})
args.each do |ar|
instance_variable_set(:"@#{ar.first}", ar.last)
end
end
def method_missing(m, *args, &blk)
if instance_variables.include? :"@#{m}"
instance_variable_get("@#{m}")
else
super
end
end
end
c = Car.new(foo: 1, bar: '132', baz: 'foo')
puts c.foo
puts c.baz
puts c.bar
puts c.barfoo
在irb中运行:
$ irb -r ./example.rb
#> 1
#> foo
#> 132
#> example.rb:14:in `method_missing': undefined method `barfoo' for #<Car:0x000000015bc740 @foo=1, @bar="132", @baz="foo"> (NoMethodError)
正如您所看到的,您可以根据需要将具有任意数量的对键值的散列作为参数传递,但是当属性不可用时它也会引发错误
instance_variables
,instance_variable_set
,instance_variable_get
,method_missing
这是使用class_eval
方法的另一个技巧:
class Car
def initialize(args = {})
args.each_pair do |k, v|
self.class.class_eval do
attr_reader k
end
instance_variable_set(:"@#{k}", v)
end
end
end
c = Car.new(foo: 1, bar: '132', baz: 'foo')
puts c.foo
puts c.baz
puts c.bar
puts c.inspect
在irb中运行:
#> 1
#> foo
#> 132
#> #<Car:0x00000002dc1fc0 @foo=1, @bar="132", @baz="foo">
再次在运行时为给定的密钥添加attr_reader
并使用该密钥的值设置实例变量。
答案 3 :(得分:0)
我无法帮助自己写一个宝石来帮助我,因为我自己经常遇到同样的烦恼。它被称为&#34; attr_args_shorthand&#34;。
基本上你可以在gem的帮助下这样做:
class User
def initialize(args)
AttrArgsShorthand.set(self, args)
end
end
然后你可以这样做:
user = User.new(name: "Kasper")
user.name #=> "Kasper"
user.name = "Christina"
user.name #=> "Christina"
user.instance_variable_get(:@name) #=> "Christina"