Reputation: 8424
Suppose I have:
Book = Struct.new(:title, :content)
book = Book.new('harry potter', 'a bunch of content here')
p book.title #=> harry potter
What I want the last line to produce is "Harry Potter". I know I can do something like:
Book = Struct.new(:title, :content) do
def capitalized_title
self.title.gsub(/\S+/, &:capitalize)
end
end
and then call capitalized_title, but what I want is to not have to create a separate method, instead, have some way of when you assign "title" to a new Book object, the title is immediately capitalized. Some kind of hook method, I would guess.
Upvotes: 2
Views: 1666
Reputation: 110685
You could create an initialize
method for the class Book
(borrowing @falsetru's nice way of capitalizing the the words in title
). First note that Book
does not have its own initialize
method;;
Book = Struct.new(:title, :content)
#=> Book
Book.private_instance_methods(false)
#=> []
Rather, it inherits from Struct
:
Book.private_instance_methods.include?(:initialize)
#=> true
Book.instance_method(:initialize).owner
#=> Struct
Struct.private_instance_methods(false)
#=> [:initialize, :initialize_copy]
We add an initialize
method in the usual way:
Book = Struct.new(:title, :content) do
def initialize(title,content)
self.title = title.gsub(/\S+/, &:capitalize)
self.content = content
end
end
confirm:
Book.private_instance_methods(false)
#=> [:initialize]
and test:
book = Book.new('harry potter', 'a bunch of content here')
book.title
#=> "Harry Potter"
book.content
#=> "a bunch of content here"
If there were more than just two instance variables, we might do this:
Book = Struct.new(:title, :content) do
def initialize(title,content)
super
self.title = title.gsub(/\S+/, &:capitalize)
end
end
Upvotes: 2
Reputation: 369094
class Book < Struct.new(:title, :content)
def title
super.gsub(/\S+/, &:capitalize)
end
end
book = Book.new('harry potter', 'a bunch of content here')
book.title # => "Harry Potter"
Book = Struct.new(:title, :content) do
alias orig_title title
def title
orig_title.gsub(/\S+/, &:capitalize)
end
end
To prevent title
is called every time, override title=
:
Book = Struct.new(:title, :content) do
alias orig_title= title=
def initialize(*args)
super
self.title = title
end
def title= value
self.orig_title = value.gsub(/\S+/, &:capitalize)
end
end
Upvotes: 5