I'm a somewhat beginner programmer who has a background in using Processing. I'm currently trying to make an app with Shoes, but I'm confused over how objects and classes work.
I understand that the following would run in Ruby:
class Post
def self.print_author
puts "The author of all posts is Jimmy"
end
end
Post.print_author
But why won't the following run in Shoes? How would I make it run?
class Post
def self.print_author
para "The author of all posts is Jimmy"
end
end
Shoes.app do
Post.print_author
end
I'm not too familiar with Shoes, but the problem you're likely having here is that you're trying to call a method called para
on the Post
class, and no such method exists.
When you call Shoes.app do ...
, I suspect Shoes is changing the current execution context to one that includes those methods. That is, you should expect this to work:
Shoes.app do
para "The author of all posts is Jimmy"
end
This is equivalent to:
Shoes.app do
self.para("The author of all posts is Jimmy")
end
When you call Post.print_author
, self
is no longer the Shoes object, but rather, is the Post class. You have a few options at that point:
Pass in the Shoes instance, and call your Shoes-specific methods on that. You should probably do it this way when you don't need any state from Post:
class Post
def self.print_author(shoes)
shoes.para "The author of all posts is Jimmy"
end
end
Shoes.app do
Post.print_author(self)
end
Create a Post class which accepts a Shoes object, so you don't have to keep passing it around. You should do it this way if Post is going to have any substantial amount of state:
class Post
def initialize(shoes)
@shoes = shoes
end
def print_author
@shoes.para "The author of all posts is Jimmy"
end
end
Shoes.app do
post = Post.new(self)
post.print_author
end
You could use a variant on the 2. option to automatically pass calls to the @shoes
object. This starts to get into Ruby metaprogramming, which I'd recommend you avoid until you're more comfortable in Ruby, but I'm leaving it here to pique your interest:
class Post
def initialize(shoes)
@shoes = shoes
end
def print_author
para "The author of all posts is Jimmy"
end
def method_missing(method, *args, &block)
@shoes.send(method, *args, &block)
end
end
Shoes.app do
post = Post.new(self)
post.print_author
end
What this does is tell Ruby "if a method isn't found on the Post instance, try sending it to the @shoes instance instead". As you can imagine, this can allow for some very nice DSLs, but you have to use it carefully, as it can make code difficult to follow if you abuse it.