I see this popping up all the time in my code
class Foo
def initialize(foo)
#foo = foo
end
#...
end
This isn't too bad, but it gets worse:
class Foo
def initialize(foo,baz,bar,a,b,c,d)
#foo = foo
#baz = baz
#bar = bar
#etc...
You can sortof get around this by doing something like
#foo, #baz, #bar = foo, baz, bar
But even that feels wrong and is annoying to type. Is there a better way to define instance variables according to arguments?
Edit:
There seem to be 2 distinct solutions to this problem. See:
spickermann's answer
Antarr Byrd's answer
You might want to consider using a Struct:
class Foo < Struct.new(foo,baz,bar,a,b,c,d)
end
foo = Foo.new(1,2,3,4,5,6,7)
foo.bar #=> 2
No need to define an extra initialize method at all...
Yes, that's the preferred way to initialize instance variables in Ruby. It can be annoying to type, but it's a well understood pattern. As always in Ruby, using metaprogramming to automate it away is possible, but will make your code harder to follow.
I'd also argue that it's probably a good thing for a class to look ugly when it's taking more than two or three arguments. If your class depends on six different things to function, it's a strong candidate for refactoring.
def initialize args
#foo, #baz, #bar = *args
end
I think there are 3 ways to make initialization of instance variables shorter:
Use Struct or OpenStruct.
Use ruby's parallel assignment.
Use metaprogramming to make a macro like this.
The fattr gem was recently endorsed on Ruby Tapas to help solve this problem. Another consideration though, is whether there are too many things being passed into the initializer. It could be that this class is doing too much and needs to be broken into smaller pieces.
Related
Looking for a little wisdom from fellow Rubyists. For a while now, I've used the following for convenience in some of my applications, and I'm wondering if there's a language feature I'm just missing:
class Object
def as_block
yield
end
end
There are other uses, but the normal case for me is a conditional assignment that requires a little non-trivial logic. Two obvious ways to do this:
# via a second method:
def foo
#foo ||= set_foo
end
# via conditional logic:
def foo
if #foo
#foo
else
# do complicated stuff
end
end
Both of these approaches seem kind of ugly: in the first case, #set_foo seems extraneous, and the second just looks kind of nasty. So, instead, I like this:
def foo
#foo ||= as_block do
# do complicated stuff
end
end
The problem here (aside from monkey patching Object) is that it's really a dependency (on the monkey patch) that looks like a language feature. That is, something like this really shouldn't be in (say) a Rails initializer---it seems like it should be in a gem, so the dependency can be managed correctly. Then I'm packaging an entire gem to run five lines of code to monkey patch Object...
So, my questions:
1. Anyone else use this, or something like it?
2. Has the Ruby team ever considered including something like this by default? It seems like a really easy way to use blocks as plain old expressions, but it's not there (as far as I know) which makes me wonder if there's some reason for not including it, or...
3. Is there already some better way of doing this that I'm just unaware of?
Thanks!
-E
What you're looking for is begin ... end. This isn't the same thing as a block or Proc, as it's not an object you can pass around or a closure which creates a new scope, but it should serve your purpose just fine:
def foo
#foo ||= begin
# do complicated stuff
end
end
You could use a lambda:
def foo
#foo ||= lambda do
# do complicated stuff
end.call
end
Note that it is important to call the lambda to actually execute the expression, ie
def foo
#foo ||= lambda do
# do complicated stuff
end
end
will return a lambda rather than your evaluated expression.
The issue I am faced with is that I need to prevent a Ruby class from being manipulated after it is defined. I can freeze it, but that doesn't stop people from just overwriting it all together.
I realize that some will want to respond with some sort of "Ruby isn't meant to be used like this" mantra. I get it, but my case is very special. This is for codewars.com where user submitted solutions are combined with a custom test framework, so I need to stop the user-submitted code from tinkering with the Test class.
I had thought that it wasn't possible at all to make constants true constants, but I noticed that the $? global variable is like this. Its likely that its because its built-in to the language to be like this and not something that can be done with custom variables.
That's because it is built into the language.
In Ruby there is no way to truly define a constant. The closest you can come is writing custom getters/setters and throwing an error if a variable has already been set.
Throw exception when re-assigning a constant in Ruby?
This is defined as "The status of the last executed child process." so, if you assign something to that variable, it will be immediately overwritten by the language with the result of the last (your) assignation.
I would think about a custom implementation - perhaps extracted into some helper gem?
def foo
#foo
end
def foo=(foo)
if defined?(#foo)
warn "warning: already initialized foo"
else
#foo = foo
end
end
self.foo = :bar
puts foo # => bar
self.foo = :baz # => warning: already initialized foo
puts foo # => bar
I'm using Ruby, and writing classes with inheritance.
For example:
class Canine
def initialize
end
def make_noise
puts "whoosh whoosh"
end
end
class Dog < Canine
def initialize
end
def make_noise
puts "wong wong"
super
end
end
Now I have a dog object:
jack = Dog.new
Is it possible to call the make_noise() method of Canine through the dog object?
In other languages it would be a typecast, something like:
(Canine)jack.make_noise
Note this is not Ruby syntax, hence, my question.
Is it possible to do this in Ruby? And if so, how?
You can do something like this:
Canine.instance_method(:make_noise).bind(jack).call
A better plan would be to just give the method in the super class an alias, or rename it.
Ruby does not allow casting or conversion in this fashion, at least not in the conventional sense. This is rarely necessary anyway, since Ruby is based on duck typing and not a rigid type system.
Are you expecting "whoosh whoosh" from the call? That's something that would only happen with non-virtual methods in a more strictly typed language like C++. It goes against proper object oriented design.
If you explore the design patterns employed in object-oriented design, you can always solve this sort of problem another way.
What you might want here is a presenter to handle the make_noise functionality.
Otherwise you'll need to write a to_canine method that can convert to the base type, though it's still not clear why you'd need such a thing.
You can do it like this:
d = Dog.new
d.class.superclass.instance_method(:make_noise).bind(d).call
or
Canine.instance_method(:make_noise).bind(d).call
. . . not pretty! I'm not sure if there's a better way
Edit: I think I agree with other answers here, in that Ruby's approach to OO will give you access to other patterns that achieve whatever goals this construct might help you with (perhaps in other languages). I don't see this kind of class/superclass method munging in practice on projects I have been involved in.
I am not sure why you need this, depending on needs it may be done totally differently, but with limited knowledge I would suggest this
class Dog < Canine
def initialize
end
def make_noise only_parent=false
puts "wong wong" if !only_parent
super
end
end
or
class Dog < Canine
def initialize
end
alias :make_super_noise :make_noise
def make_noise
puts "whoosh whoosh"
super
end
end
(StackOverflow is telling me that this question is "subjective and likely to be closed"… well, I'll give it a shot regardless)
I'm writing a bunch of helper methods (for a TextMate bundle), and I'd like (and I need) to have them neatly namespaced.
These methods are really just functions, i.e. they don't operate on anything outside their own scope, and thus don't really belong in a class. There's nothing that needs instantiating.
So far, I've been doing this and that works just fine
module Helpers::Foo
module_function
def bar
# ...
end
end
Helpers::Foo.bar # this is how I'd like to call the method/function
But would it be better to:
1. Skip module_function and declare the methods/functions as self.*?
2. Or would it be better to declare a class instead of a module?
3. Or use class << self (inside a module or a class)?
4. Or something else entirely?
I realize this is a pretty open-ended question, but I'm really just looking to hear what people are doing.
I prefer either
module Foo
def self.bar
"bar"
end
end
Foo.bar #=> "bar"
or
module Foo
def Foo.bar
"bar"
end
end
Foo.bar #=> "bar"
but probably lean towards the former, i think self. is really descriptive.
Edit: After reading the comments I propose a third option that I prefer for readability. Technically I think this would be defined as extending the methods included on the Eigen class.
module Foo
module ClassMethods
def baz
"baz"
end
end
extend ClassMethods
end
Foo.baz #=> "baz"
I often have functions which take a parameter, set an instance variable to that parameter, and then do other things, e.g.:
def updateFoo(self, foo):
self.foo = foo
fooProcessor1(foo)
fooProcessor2(self.foo)
Do you prefer to pass the parameter itself, as in fooProcessor1, or the newly-set instance variable, as in fooProcessor2? Why or why not?
A function named setFoo() really shouldn't do anything more than setting foo unless it is computing and caching a value derived from foo, in which case I would advise something along the lines of:
def setFoo(self, foo):
self.foo = foo
self.__fooUpdated()
def __fooUpdated(self):
# Recompute values derived from foo, dispatch signal to listeners, etc.
Of the options you suggested, I prefer fooProcessor1(foo). That said, it is mostly a matter of personal preference. As long as you are consistent, I don't think it matters all that much.
Coders should be lazy. self. is way too much to type at 1 am.