Initializing attributes in Ruby objects
You want to use instance variables inside an instance of a class to define attributes, not a local variable. local variables will go out of scope as soon as the method is finished executing. the code below should be more along the lines of what you need:
module Test
class Spam
attr_accessor :hooray, :name
def initialize
@hooray = []
@name = "Whammy"
end
end
end
Ruby class initialization
I would try using a hash for your constructor like the code below adapted from DRY Ruby Initialization with Hash Argument
class Example
attr_accessor :id, :status, :dateTime
def initialize args
args.each do |k,v|
instance_variable_set("@#{k}", v) unless v.nil?
end
end
end
That way setting each of your properties in the constructor becomes optional. As the instance_variable_set method will set each property if the has contains a value for it.
Which means you could support any number of ways to construct your object. The only downside is you might have to do more nil checking in your code but without more information it is hard to know.
Creating a new Object - Usage Examples
To create a new object with this technique all you need to do is pass in a hash to your initialiser:
my_new_example = Example.new :id => 1, :status => 'live'
#=> #<Example: @id=1, @status='live'>
And its flexible enough to create multiple objects without certain properties with one constructor:
my_second_new_example = Example.new :id => 1
#=> #<Example: @id=1>
my_third_new_example = Example.new :status => 'nonlive', :dateTime => DateTime.new(2001,2,3)
#=> #<Example: @id=1, @dateTime=2001-02-03T00:00:00+00:00>
You can still update your properties once the objects have been created:
my_new_example.id = 24
How to cleanly initialize attributes in Ruby with new?
def initialize(params)
params.each do |key, value|
instance_variable_set("@#{key}", value)
end
end
What is the most efficient way to initialize a Class in Ruby with different parameters and default values?
The typical way to solve this problem is with a hash that has a default value. Ruby has a nice syntax for passing hash values, if the hash is the last parameter to a method.
class Fruit
attr_accessor :color, :type
def initialize(params = {})
@color = params.fetch(:color, 'green')
@type = params.fetch(:type, 'pear')
end
def to_s
"#{color} #{type}"
end
end
puts(Fruit.new) # prints: green pear
puts(Fruit.new(:color => 'red', :type => 'grape')) # prints: red grape
puts(Fruit.new(:type => 'pomegranate')) # prints: green pomegranate
A good overview is here: http://deepfall.blogspot.com/2008/08/named-parameters-in-ruby.html
Initialize an object using a block instead of constructor arguments
It's actually really easy to add this functionality to most classes provided they already have attr_writer
and/or attr_accessor
in place:
class Grammar
attr_accessor :rules, :start, ...
def initialize(rules, start)
@rules = rules
@start = start
...
yield self if block_given?
end
end
Where you can now do exactly what you wanted. The yield self
part will supply the object being initialized to the block, and block_given?
is only true
if you've supplied a block to the new
call. You'll want to run this after setting all your defaults.
Initialize an object with a block
Of course, you can yield
from within initialize
, there's nothing special about it:
class Foo
attr_accessor :bar, :baz
def initialize
yield self
end
end
Foo.new do |f|
f.bar = 123
f.baz = 456
end
#=> <Foo:0x007fed8287b3c0 @bar=123, @baz=456>
You could also evaluate the block in the context of the receiver using instance_eval
:
class Foo
attr_accessor :bar, :baz
def initialize(&block)
instance_eval(&block)
end
end
Foo.new do
@bar = 123
@baz = 456
end
#=> #<Foo:0x007fdd0b1ef4c0 @bar=123, @baz=456>
Initialize class object variable in Ruby
In Ruby, @@
before a variable means it's a class variable. What you need is the single @
before the variable to create an instance variable. When you do Result.new(..)
, you are creating an instance of the class Result
.
You don't need to create default values like this:
@@min = 0
@@max = 0
You can do it in the initialize
method
def initialize(min = 0, max = 0)
This will initialize min
and max
to be zero if no values are passed in.
So now, your initialize
method should like something like
def initialize(min=0, max=0)
@min = min
@max = max
end
Now, if you want to be able to call .min
or .max
methods on the instance of the class, you need to create those methods (called setters and getters)
def min # getter method
@min
end
def min=(val) # setter method
@min = val
end
Now, you can do this:
result.min #=> 1
result.min = 5 #=> 5
Ruby has shortcuts for these setters and getters:
attr_accessor
: creates the setter and getter methods.attr_reader
: create the getter method.attr_writer
: create the setter method.
To use those, you just need to do attr_accessor :min
. This will create both methods for min
, so you can call and set min values directly via the instance object.
Now, you code should look like this
class Result
attr_accessor :min, :max
def initialize(min=0, max=0)
@min = min
@max = max
end
end
result = Result.new(1, 10)
result.max #=> 10
Rails: Initializing attributes that are dependent on one another
Oh jeeezzzz... this is insanely simple, now that I puzzled on it a little more. I just need to override the "initialize(attributes = {})" method on the PropertyValue class like so:
def initialize(attributes = {})
property = Property.find(attributes[:property_id]) unless attributes[:property_id].blank?
super(attributes)
end
Now I'm always sure that the property association is filled before the other attributes are set. I just didn't realize soon enough that Rails' "build(attributes = {})" and "create(attributes = {})" operations eventually boil down to "new(attributes = {})".
Related Topics
Ruby Daemons and Jruby - Alternative Options
Specifying Content Type in Rspec
/Usr/Bin/Env Ruby_Noexec_Wrapper Fails with No File or Directory
Rvm System-Wide Install Script Url Broken -- What Is Replacement
Ruby on Rails Activerecord Scopes VS Class Methods
How to Use the Fetch Method for Nested Hash
How to Require File from 'Gem' Which Are Not Under 'Lib' Directory
Thread Safe Enumerator in Ruby
Initialize a Ruby Class from an Arbitrary Hash, But Only Keys with Matching Accessors
How to Require a Block in Ruby
Rails 5.0.0 When Installing "Nio4R":Failed to Build Gem Native Extension
Ruby: Differencebetween the Comparatives: "||" and "Or"
How to Use Escape Characters in Strings
Error Installing Ruby 2.6.7 on MAC Os - How to Resolve
How to Get the Destination Url of a Shortened Url Using Ruby