YARD: document custom getter/setter pair like attr_accessor - ruby

I'm using YARD to document my project. YARD document attributes created with
attr_accessor :some_attribute
in a separate section "Instance Attribute Summary". Now I have another attribute, but with custom setter and getter
def some_other_attribute
# ...
end
def some_other_attribute= value
# ...
end
so basically my question is, how can I get YARD to document this pair of setter/getter just like attr_accessor in the previous case, and list some_other_attribute within "Instance Attribute Summary"?

As of 0.8 (which is in pre-release right now), the #!attribute directive is the recommended way to denote that an object is an attribute. The #attr_* tags are deprecated in favour of this directive. You could also do (in 0.8.0+):
# #!parse attr_accessor :some_attribute
To parse code that isn't necessarily executed by Ruby. Prior to 0.8, you could just add the attr_accessor directly and then redefine the setter/getter as follows:
class MyClass
attr_accessor :foo
def foo; something_else end
def foo=(v) something_else(v) end
end
Ruby shouldn't mind, except that in ruby -w it will warn about method redefinitions. If this bugs you, you can add undef foo, foo= in there too. It's a little messy (if you care about -w), which is why we added things like #!parse and #!attribute.

You should be able to use the #attr tag on the class:
# #attr [String] name The name of this object.
class MyClass
def name
end
def name=
end
end
There are other tags (like #attr_reader and #attr_writer) than can also be helpful.

Related

Im trying to understand "Getters" and "Setters" in the ruby programming language

Im currently doing some online tutorials about the ruby programming langauge and I think the explanations/examples I have been given thus far are lacking. I have two examples Id like to show you before directly asking the question.
The first example is:
Traditional Getters/Setters;
class Pen
def initialize(ink_color)
#ink_color = ink_color # this is available because of '#'
end
# setter method
def ink_color=(ink_color)
#ink_color = ink_color
end
# getter method
def ink_color
#ink_color
end
end
And the second example is:
ShortCutt Getter/Setters;
class Lamp
attr_accessor :color, :is_on
def initialize(color, is_on)
#color, #is_on = color, false
end
end
Ok, So for the first example I think its pretty straight forward. I am 'initializing' an accessible variable throughout my entire Lamp class called "#ink_color". If I wanted to set "#ink_color" to red or blue I would simply call my 'Setter' method and pass 'red' or 'blue' to the parameter (ink_color) in my setter. Then If I wanted to access or 'Get/Getter' the color I have 'Set/setter' I would call my getter method and ask for 'ink_color'.
The second example makes sense to me as well; Instead of typing out what the getter and setter methods look like, ruby provides a 'shortcut' that essentially runs code to build the getter and setter for you.
But heres the question - How do I reverse engineer the 'shortcut' version? Lets say I was looking at my above shortcut example and wanted to do it the "traditional" way without a shortcut?
Would the reverse engineering of the "shortcut" look something like the below code(my attempt that doesn't seem right to me)....
My Attempt/Example
class Lamp
def initialize(color, is_on)
#color = color
#is_on = is_on
end
def color=(color)
#color = color
end
def is_on=(is_on)
#is_on = is_on
end
def color
#color
end
def is_on
#is_on
end
end
Is my attempt right/workable code? It just seems like im missing a piece conceptually when it comes to this getter/setter stuff.
Understanding attr_accesor, attr_reader and attr_writer
These are Ruby's getters and setters shortcut. It works like C# properties, that injects the get_Prop (getter) and set_Prop (setter) methods.
attr_accessor: injects prop (getter) and prop= (setter) methods.
attr_reader: it's a shortcut for read-only properties. Injects prop method. The prop value can only be changed inside the class, manipulating the instance variable #prop.
attr_writer: it's a shortcut for write-only properties. Injects prop= method.
Ruby doesn't have methods called get_prop (getter) and set_prop (setter), instead, they're called prop (getter) and prop= (setter).
That being said, you can infer that
class Person
attr_accessor :name, :age
end
is the short version for
class Person
# getter
def name
return #name
end
# setter
def name=(value)
#name = value
end
end
You don't need to call return, Ruby methods returns the last executed statement.
If you are using Ruby on Rails gem, you can build model objects using new and passing properties values as arguments, just like:
p = Person.new(name: 'Vinicius', age: 18)
p.name
=> 'Vinicius'
That's possible because Rails injects something like this initialize method to ActiveRecord::Base and classes that includes ActiveModel::Model:
def initialize(params)
params.each do |key, value|
instance_variable_set("##{key}", value)
end
end

What is the difference between the following two? [duplicate]

In Ruby there are four different getter and setter methods for instance variables, attr, attr_reader, attr_writer, and attr_accessor. The question is, is in Ruby attr :dilithium, the same as attr_reader :dilithium, and identical to attr_accessor :dilithium if an additional parameter true is passed? That is to say is
class Enterprise
attr :dilithium, true
identical to
class Enterprise
attr_accessor :dilithium
Are the two functions attr and attr_accessor more or less redundant?
One difference is that attr_accessor and friends are clearer, and the optional boolean argument to attr is now deprecated. Other than that, and the fact that attr has no documentation, there's no real difference.
In Ruby 1.8, attr can define only a single attribute, with an optional true to create a setter . In 1.9 it behaves like attr_reader:it allows for multiple attributes. As #Linuxios says, the optional boolean is deprecated.
If you look at the C code in Ruby 2.3.0, you will see that attr and attr_reader are actually doing the same thing (except for the deprecated code path). They are essentially equivalent functions.
For me, the main differences are:
attr is a bit easier to write down as it's shorter. I like the way it feels in the context of functional/immutable programming too (in those contexts, attr_writer and attr_accessor are irrelevant and thus using attr_reader feels verbose and redundant).
attr with multiple instance variables makes it hard to document, except in very specific situations, e.g.
# The coordinates in WGS84.
attr :x, :y
# The location name.
attr :name
# The popularity of the location.
attr :popularity
It would be harder to document :name and :popularity independently if they were on the same line attr :name, :popularity.
Apart from that it boils down to personal preference. There is in practice no performance difference or any other difference.
attr and attr_accessor are methods in Ruby that are used to define instance variables in classes.
attr creates a simple getter method that returns the value of an instance variable with the same name as the symbol passed as an argument. For example:
class MyClass
attr :my_variable
def initialize
#my_variable = "Hello World"
end
end
my_object = MyClass.new
puts my_object.my_variable # outputs "Hello World"
attr_accessor creates both getter and setter methods for an instance variable with the same name as the symbol passed as an argument. For example:
class MyClass
attr_accessor :my_variable
def initialize
#my_variable = "Hello World"
end
end
my_object = MyClass.new
puts my_object.my_variable # outputs "Hello World"
my_object.my_variable = "Goodbye World"
puts my_object.my_variable # outputs "Goodbye World"
In the example above, my_object.my_variable can be read and written. The attr_accessor method creates both getter and setter methods, allowing the value of the instance variable to be read and written.

What does attr mean in Ruby? [duplicate]

In Ruby there are four different getter and setter methods for instance variables, attr, attr_reader, attr_writer, and attr_accessor. The question is, is in Ruby attr :dilithium, the same as attr_reader :dilithium, and identical to attr_accessor :dilithium if an additional parameter true is passed? That is to say is
class Enterprise
attr :dilithium, true
identical to
class Enterprise
attr_accessor :dilithium
Are the two functions attr and attr_accessor more or less redundant?
One difference is that attr_accessor and friends are clearer, and the optional boolean argument to attr is now deprecated. Other than that, and the fact that attr has no documentation, there's no real difference.
In Ruby 1.8, attr can define only a single attribute, with an optional true to create a setter . In 1.9 it behaves like attr_reader:it allows for multiple attributes. As #Linuxios says, the optional boolean is deprecated.
If you look at the C code in Ruby 2.3.0, you will see that attr and attr_reader are actually doing the same thing (except for the deprecated code path). They are essentially equivalent functions.
For me, the main differences are:
attr is a bit easier to write down as it's shorter. I like the way it feels in the context of functional/immutable programming too (in those contexts, attr_writer and attr_accessor are irrelevant and thus using attr_reader feels verbose and redundant).
attr with multiple instance variables makes it hard to document, except in very specific situations, e.g.
# The coordinates in WGS84.
attr :x, :y
# The location name.
attr :name
# The popularity of the location.
attr :popularity
It would be harder to document :name and :popularity independently if they were on the same line attr :name, :popularity.
Apart from that it boils down to personal preference. There is in practice no performance difference or any other difference.
attr and attr_accessor are methods in Ruby that are used to define instance variables in classes.
attr creates a simple getter method that returns the value of an instance variable with the same name as the symbol passed as an argument. For example:
class MyClass
attr :my_variable
def initialize
#my_variable = "Hello World"
end
end
my_object = MyClass.new
puts my_object.my_variable # outputs "Hello World"
attr_accessor creates both getter and setter methods for an instance variable with the same name as the symbol passed as an argument. For example:
class MyClass
attr_accessor :my_variable
def initialize
#my_variable = "Hello World"
end
end
my_object = MyClass.new
puts my_object.my_variable # outputs "Hello World"
my_object.my_variable = "Goodbye World"
puts my_object.my_variable # outputs "Goodbye World"
In the example above, my_object.my_variable can be read and written. The attr_accessor method creates both getter and setter methods, allowing the value of the instance variable to be read and written.

attr vs attr_accessor

In Ruby there are four different getter and setter methods for instance variables, attr, attr_reader, attr_writer, and attr_accessor. The question is, is in Ruby attr :dilithium, the same as attr_reader :dilithium, and identical to attr_accessor :dilithium if an additional parameter true is passed? That is to say is
class Enterprise
attr :dilithium, true
identical to
class Enterprise
attr_accessor :dilithium
Are the two functions attr and attr_accessor more or less redundant?
One difference is that attr_accessor and friends are clearer, and the optional boolean argument to attr is now deprecated. Other than that, and the fact that attr has no documentation, there's no real difference.
In Ruby 1.8, attr can define only a single attribute, with an optional true to create a setter . In 1.9 it behaves like attr_reader:it allows for multiple attributes. As #Linuxios says, the optional boolean is deprecated.
If you look at the C code in Ruby 2.3.0, you will see that attr and attr_reader are actually doing the same thing (except for the deprecated code path). They are essentially equivalent functions.
For me, the main differences are:
attr is a bit easier to write down as it's shorter. I like the way it feels in the context of functional/immutable programming too (in those contexts, attr_writer and attr_accessor are irrelevant and thus using attr_reader feels verbose and redundant).
attr with multiple instance variables makes it hard to document, except in very specific situations, e.g.
# The coordinates in WGS84.
attr :x, :y
# The location name.
attr :name
# The popularity of the location.
attr :popularity
It would be harder to document :name and :popularity independently if they were on the same line attr :name, :popularity.
Apart from that it boils down to personal preference. There is in practice no performance difference or any other difference.
attr and attr_accessor are methods in Ruby that are used to define instance variables in classes.
attr creates a simple getter method that returns the value of an instance variable with the same name as the symbol passed as an argument. For example:
class MyClass
attr :my_variable
def initialize
#my_variable = "Hello World"
end
end
my_object = MyClass.new
puts my_object.my_variable # outputs "Hello World"
attr_accessor creates both getter and setter methods for an instance variable with the same name as the symbol passed as an argument. For example:
class MyClass
attr_accessor :my_variable
def initialize
#my_variable = "Hello World"
end
end
my_object = MyClass.new
puts my_object.my_variable # outputs "Hello World"
my_object.my_variable = "Goodbye World"
puts my_object.my_variable # outputs "Goodbye World"
In the example above, my_object.my_variable can be read and written. The attr_accessor method creates both getter and setter methods, allowing the value of the instance variable to be read and written.

Sharing variables across submodules and classes

I am trying to build a simple little template parser for self-learning purposes.
How do I build something "modular" and share data across it? The data doesn't need to be accessible from outside, it's just internal data. Here's what I have:
# template_parser.rb
module TemplateParser
attr_accessor :html
attr_accessor :test_value
class Base
def initialize(html)
#html = html
#test_value = "foo"
end
def parse!
#html.css('a').each do |node|
::TemplateParser::Tag:ATag.substitute! node
end
end
end
end
# template_parser/tag/a_tag.rb
module TemplateParser
module Tag
class ATag
def self.substitute!(node)
# I want to access +test_value+ from +TemplateParser+
node = #test_value # => nil
end
end
end
end
Edit based on Phrogz' comment
I am currently thinking about something like:
p = TemplateParser.new(html, *args) # or TemplateParser::Base.new(html, *args)
p.append_css(file_or_string)
parsed_html = p.parse!
There shouldn't be much exposed methods because the parser should solve a non-general problem and is not portable. At least not at this early stage. What I've tried is to peek a bit from Nokogiri about the structure.
With the example code you've given, I'd recommend using composition to pass in an instance of TemplateParser::Base to the parse! method like so:
# in TemplateParser::Base#parse!
::TemplateParser::Tag::ATag.substitute! node, self
# TemplateParser::Tag::ATag
def self.substitute!(node, obj)
node = obj.test_value
end
You will also need to move the attr_accessor calls into the Base class for this to work.
module TemplateParser
class Base
attr_accessor :html
attr_accessor :test_value
# ...
end
end
Any other way I can think of right now of accessing test_value will be fairly convoluted considering the fact that parse! is a class method trying to access a different class instance's attribute.
The above assumes #test_value needs to be unique per TemplateParser::Base instance. If that's not the case, you could simplify the process by using a class or module instance variable.
module TemplateParser
class Base
#test_value = "foo"
class << self
attr_accessor :test_value
end
# ...
end
end
# OR
module TemplateParser
#test_value = "foo"
class << self
attr_accessor :test_value
end
class Base
# ...
end
end
Then set or retrieve the value with TemplateParser::Base.test_value OR TemplateParser.test_value depending on implementation.
Also, to perhaps state the obvious, I'm assuming your pseudo-code you've included here doesn't accurately reflect your real application code. If it does, then the substitute! method is a very round about way to achieve simple assignment. Just use node = test_value inside TemplateParser::Base#parse! and skip the round trip. I'm sure you know this, but it seemed worth mentioning at least...

Resources