In Ruby, how can I get instance variables in a hash instead of an array?
To create a hash of all instance variables you can use the following code:
class Object
def instance_variables_hash
Hash[instance_variables.map { |name| [name, instance_variable_get(name)] } ]
end
end
But as cam mentioned in his comment, you should use instance_variable_get
method instead:
object.instance_variable_get :@my_instance_var
Make instance variable accessible through hash in Ruby
It's not "through Hash", it's "array access" operator.
To implement it, you need to define methods:
def [](*keys)
# Define here
end
def []=(*keys, value)
# Define here
end
Of course, if you won't be using multiple keys to access an element, you're fine with using just key
instead of *keys
, so that you have not an array of keys (even if only one is given), but just a single key.
Plenty of other classes implement it, namely Struct
s, so you're free to pick an existing implementation or roll out your own.
Getting instance variables to be affected by these methods means implementing them using instance_variable_get
/instance_variable_set
. Nothing fancy.
Accessing an object's instance variable from an array
accounts
is an array. So you have to access one of its elements' account_number
instance variable. For example the first element's:
# accounts[0] would return an instance of `AccountMaker `
accounts[0].instance_variable_get(:account_number)
Also, you don't need to use instance_variable_get
, since you already declared it as accessor. So, you can just call account_number
method on it.
accounts[0].account_number
Convert hash params into instance variables on Ruby initializer
I want to do this in a clean way.
You won't get attr_accessor
s and instance variables without defining them. The below is using some simple metaprogramming (does it qualify for "clean"?)
class PriceChange
def initialize(data = {})
data.each_pair do |key, value|
instance_variable_set("@#{key}", value)
self.class.instance_eval { attr_accessor key.to_sym }
end
end
end
Usage:
price_change = PriceChange.new(foo: :foo, bar: :bar)
#=> #<PriceChange:0x007fb3a1755178 @bar=:bar, @foo=:foo>
price_change.foo
#=> :foo
price_change.foo = :baz
#=> :baz
price_change.foo
#=> :baz
Calculating a map of instance variables
This works of course, but I wonder whether there isn't a simpler way to achieve the same result.
There are some slight simplifications that you could do:
- Use
Array#to_h
instead ofHash::[]
. - Use
Array#zip
. - Use point-free style using
Object#method
or something like the method reference operator if that is ever added to Ruby.
module M
def self.ivar_map
instance_variables.zip(instance_variables.map(&method(:instance_variable_get))).to_h
end
end
or with the experimental (and removed again in 2.7.0-preview3) method reference operator:
module M
def self.ivar_map
instance_variables.zip(instance_variables.map(&self.:instance_variable_get)).to_h
end
end
After all, Ruby somehow has to maintain such a symbol table already, mapping the variables to their content.
Actually, that is not true. Several Ruby Implementations (including YARV, the most widely-used one) optimize instance variables to some extent. E.g. I believe YARV stores up to three instance variables in the object header directly, without using an instance variable table.
And YARV is on the more simple side when it comes to optimizations. Other implementations like Rubinius, JRuby, TruffleRuby, and RubyOMR perform much more sophisticated optimizations.
Quickly setting instance variables with options hash in Ruby?
def initialize(opts={})
opts.each { |k,v| instance_variable_set("@#{k}", v) }
end
How to get all instances variables in ruby class?
You can use instance_variables
to collect them in an Array. You will get all initialized instance variables.
class MyClass
attr_accessor :name1
attr_accessor :name2
...
attr_accessor :namen
def inner_func():
all_vars = instance_variables
res = out_func(all_vars)
do_more_stuff(res)
end
end
What is an elegant way in Ruby to tell if a variable is a Hash or an Array?
You can just do:
@some_var.class == Hash
or also something like:
@some_var.is_a?(Hash)
It's worth noting that the "is_a?" method is true if the class is anywhere in the objects ancestry tree. for instance:
@some_var.is_a?(Object) # => true
the above is true if @some_var is an instance of a hash or other class that stems from Object. So, if you want a strict match on the class type, using the == or instance_of? method is probably what you're looking for.
can I pass a hash to an instance method to create instance variables?
Sure you can do something like this in your initialize method:
hash.each do |k, v|
instance_variable_set("@#{k}", v)
self.class.send(:attr_reader, k)
end
Here's an example using your input hash:
class Reminder
def initialize(hash)
hash.each do |k, v|
instance_variable_set("@#{k}", v)
self.class.send(:attr_reader, k)
end
end
end
reminder_hash = {"bot_client_id"=>"test-client-id", "recurring"=>true, "recurring_natural_language"=>"everyday", "time_string"=>"10AM", "time_zone"=>"America/Los_Angeles", "via"=>"slack", "keyword"=>"test-keyword", "status"=>"active", "created_time"=>1444366166000}
reminder = Reminder.new(reminder_hash)
puts reminder
puts reminder.bot_client_id
Output:
#<Reminder:0x007f8a48831498>
test-client-id
Related Topics
Select Checkbox Pass Array in Ruby on Rails
Automatically Open a File as Binary with Ruby
Mismatched Bundler Version - Bundler 2, Ruby 2.6
Ruby on Rails - Doesn't Create Script/Server
Can't Convert String into Integer in Ruby/Ruby-On-Rails
Is the .Each Iterator in Ruby Guaranteed to Give the Same Order on the Same Elements Every Time
Erroneous "Insecure World Writable Dir Foo in Path" When Running Ruby Script
How to Declare 8-Bit Unsigned Integer in Ruby
Rspec Commandline Variable Input
Preserving Case in Http Headers with Ruby's Net:Http
Splitting String into Pair of Characters in Ruby
How to Write to File When Using Marshal::Dump in Ruby for Object Serialization
How to Rescue from a 'Require': No Such File to Load in Ruby
Use Ruby Array for a JavaScript Array in Erb. Escaping Quotes
Rails SQL Query Builder... or Activerecord Query Builder
How to Convert JSON to a Hash, Search for and Change a Value