Due to the fact that Ruby doesn't support overloading (because of several trivial reasons), I am trying to find a way to 'simulate' it.
In static typed languages, you mustn't use instanceof, (excepting some particular cases of course...) to guide the application.
So, keeping this in mind, is this the correct way to overload a method in which I do care about the type of the variable? (In this case, I don't care about the number of parameters)
class User
attr_reader :name, :car
end
class Car
attr_reader :id, :model
end
class UserComposite
attr_accessor :users
# f could be a name, or a car id
def filter(f)
if (f.class == Car)
filter_by_car(f)
else
filter_by_name(f)
end
end
private
def filter_by_name(name)
# filtering by name...
end
def filter_by_car(car)
# filtering by car id...
end
end
There are cases where this is a good approach, and Ruby gives you the tools to deal with it.
However your case is unclear because your example contradicts itself. If f.class == Car then filter_by_car accepts a _car, not a _car_id.
I'm assuming that you're actually passing instances of the class around, and if so you can do this:
# f could be a name, or a car
def filter(f)
case f
when Car
filter_by_car(f)
else
filter_by_name(f)
end
end
case [x] looks at each of its when [y] clauses and executes the first one for which [y] === [x]
Effectively this is running Car === f. When you call #=== on a class object, it returns true if the argument is an instance of the class.
This is quite a powerful construct because different classes can define different "case equality". For example the Regexp class defines case equality to be true if the argument matches the expression, so the following works:
case "foo"
when Fixnum
# Doesn't run, the string isn't an instance of Fixnum
when /bar/
# Doesn't run, Regexp doesn't match
when /o+/
# Does run
end
Personally, I don't see a big problem in branching that way. Although it would look cleaner with a case
def filter(f)
case f
when Car
filter_by_car(f)
else
filter_by_name(f)
end
end
Slightly more complicated example involves replacing branching with objects (ruby is oop language, after all :) ). Here we define handlers for specific formats (classes) of data and then look up those handlers by incoming data class. Something along these lines:
class UserComposite
def filter(f)
handler(f).filter
end
private
def handler(f)
klass_name = "#{f.class}Handler"
klass = const_get(klass_name) if const_defined?(klass_name)
klass ||= DefaultHandler
klass.new(f)
end
class CarHandler
def filter
# ...
end
end
class DefaultHandler # filter by name or whatever
def filter
# ...
end
end
end
There could be a problem lurking in your architecture - UserComposite needs to know too much about Car and User. Suppose you need to add more types? UserComposite would gradually become bloated.
However, it's hard to give specific advice because the business logic behind filtering isn't clear (architecture should always adapt to your real-world use-cases).
Is there really a common action you need to do to both Cars and Users?
If not, don't conflate the behavior into a single UserComposite class.
If so, you should use decorators with a common interface. Roughly like this:
class Filterable
# common public methods for filtering, to be called by UserComposite
def filter
filter_impl # to be implemented by subclasses
end
end
class FilterableCar < Filterable
def initialize(car)
#car = car
end
private
def filter_impl
# do specific stuff with #car
end
end
class DefaultFilterable < Filterable
# Careful, how are you expecting this generic_obj to behave?
# It might be better replace the default subclass with a FilterableUser.
def initialize(generic_obj)
# ...
end
private
def filter_impl
# generic behavior
end
end
Then UserComposite only needs to care that it gets passed a Filterable, and all it has to do is call filter on that object. Having the common filterable interface keeps your code predictable, and easier to refactor.
I recommend that you avoid dynamically generating the filterable subclass name, because if you ever decide to rename the subclass, it'll be much harder to find the code doing the generating.
Related
Say I have a parent class:
class Stat
def val
raise "method must be implemented by subclass"
end
end
And a subclass:
class MyStat < Stat
def val
#performs costly calculation and returns value
end
end
By virtue of extending the parent class, I would like the subclass to not have to worry about caching the return value of the "val" method.
There are many patterns one could employ here to this effect, and I've tried several on for size, but none of them feel right to me and I know this is a solved problem so it feels silly to waste the time and effort. How is this most commonly dealt with?
Also, it's occurred to me that I may be asking the wrong questions. Maybe I should't be using inheritance at all but composition instead.
Any and all thoughts appreciated.
Edit:
Solution I went with can be summed up as follows:
class Stat
def value
#value ||= build_value
end
def build_value
#to be implemented by subclass
end
end
Typically I use a simple pattern regardless of the presence of inheritance:
class Parent
def val
#val ||= calculate_val
end
def calculate_value
fail "Implementation missing"
end
end
class Child < Parent
def calculate_val
# some expensive computation
end
end
I always prefer to wrap the complex and expensive logic in its own method or methods that have no idea that their return value will be memoized. It gives you a cleaner separation of concerns; one method is for caching, one method is for computing.
It also happens to give you a nice way of overriding the logic, without overriding the caching logic.
In the simple example above, the memoized method val is pretty redundant. But the pattern it also lets you memoize methods that accept arguments, or when the actual caching is less trivial, maintaining that separation of responsibilities between caching and computing:
def is_prime(n)
#is_prime ||= {}
#is_prime[n] ||= compute_is_prime
end
If you want to keep the method names same and not create new methods to put logic in, then prepend modules instead of using parent/child inheritance.
module MA
def val
puts("module's method")
#_val ||= super
end
end
class CA
def val
puts("class's method")
1
end
prepend MA
end
ca = CA.new
ca.val # will print "module's method" and "class's method". will return 1.
ca.val # will print "module's method". will return 1.
I have a class in Ruby that holds some stuff, I'll call FooBox:
class FooBox
...
end
I have two possible backing-data stores for FooBox called BoxA and BoxB with different characteristics but the same interface:
class BoxA
include Enumerable
def put_stuff(thing)
...
end
end
class BoxB
include Enumerable
def put_stuff(thing)
...
end
end
How can I instantiate a FooBox, and, based on a parameter, decide whether to back it with a BoxA or BoxB implementation? I do not want to pass in the implementation into the constructor; I only want to pass something to determine which kind to use.
class FooBox
def initialize(implementation_choice)
# ???
end
end
I usually do something like this:
class BoxA
def self.match? options
# figure out if BoxA can be used given options
end
end
# Implement BoxB (and other strategies) similarly to BoxA
class FooBox
STRATEGIES = [BoxA, BoxB]
def initialize options
#options = options
end
def strategy
#strategy ||= STRATEGIES.detect { |strategy| strategy.match? #options }
end
end
This keeps the responsibility of “knowing” if the strategy is able to be used within the strategy itself (rather than making the context class monolithic), and then just picks the first one in the list that says it can work.
I’ve used this pattern (and similar variations for slightly different problems) several times and have found it very clean.
The simple solution is create a mapping for the strategy's type and strategy class, just like #Andrew Marshall's solution
But to be better I would considering two things:
The strategies' holder (here is the FooxBox ) now need to know every box implenentation, and hard-coding their names to itself; this is not a flexiable
approach, considering one day you want to add another strategy, go to the code and add it? With ruby we can do it with a 'self registering' easily.
You don't want to strategies holder will return implementation wildly, I mean both 'BoxA' and 'BoxB' or someday's 'BoxXYZ' should belong to same strategy
concept, in Java, it maybe means all of them should implemente an interface, with ruby we generally do it with include SomeMoudle
In my application I use the following solution(just demo)
module Strategies
def self.strategies
##strategies ||= {}
end
def self.strategy_for(strategy_name)
##strategies[strategy_name]
end
end
module Strategy
def self.included(base)
base.class_eval do
def self.strategy_as(strategy_name)
Strategies.strategies[strategy_name] = self
end
end
end
end
class BoxA
include Strategy
strategy_as :box_a
def do_stuff
puts "do stuff in BoxA"
end
end
class BoxB
include Strategy
strategy_as :box_b
def do_stuff
p "do stuff in BoxB"
end
end
## test
Strategies.strategy_for(:box_a).new.do_stuff
Strategies.strategy_for(:box_b).new.do_stuff
If you want to detect strategy with match block, you can change strategy_as to accept a block. then use Strategies.strategy_for{...}.new.do_stuff
Can someone explain the difference between initializing "self" and having #variables when defining classes?
Here's an example
class Child < Parent
def initialize(self, stuff):
self.stuff = stuff
super()
end
end
So in this case, wouldn't I be able to replace self.stuff with #stuff? What's the difference? Also, the super() just means whatever is in the Parent initialize method the Child should just inherit it right?
In general, no, self.stuff = stuff and #stuff = stuff are different. The former makes a method call to stuff= on the object, whereas the latter directly sets an instance variable. The former invokes a method which may be public (unless specifically declared private in the class), whereas the latter is always setting a private instance variable.
Usually, they look the same because it is common to define attr_accessor :stuff on classes. attr_accessor is roughly equivalent to the following:
def stuff
#stuff
end
def stuff=(s)
#stuff = s
end
So in that case, they are functionally identical. However, it is possible to define the public interface to allow for different results and side-effects, which would make those two "assignments" clearly different:
def stuff
#stuff_called += 1 # Keeps track of how often this is called, a side effect
return #stuff
end
def stuff=(s)
if s.nil? # Validation, or other side effect. This is not triggered when setting the instance variable directly
raise "Argument should not be nil"
end
#stuff = s
end
You actually can't use self.stuff= unless you specifically create an attr_writer for modifying that value.
In fact, these are equivalent:
class Child
attr_writer :stuff
end
class Child
def stuff=(val)
#stuff = val
end
end
It is more common to use an attr_writer if that is the functionality you want, rather than the explicit method. But you will often use an explicit method if you want to perform extra error checking or change the way the assignment works.
To your question of when to use #stuff = and when to use self.stuff =, I would use the former if you only have simple assignments and if your class is simple, and would move towards the latter if your requirements might become more complicated. There are many other reasons too, but it's more a matter of style than anything else.
Is it possible to do something like this in Ruby (1.9.2-p290)?
class SomeClass
include SomeModuleThatProvidesLotOfConstants
def build(&block)
singleton_class.instance_eval(&block)
end
end
obj = SomeClass.new
obj.build do
some_class_method SomeConstant, :an => :option
...
end
Where some_class_method is a method that is available to SomeClass (not to instances of it) and SomeConstant is a class/module that is in scope inside of SomeClass, but would have to be references as SomeClass::SomeConstant from outside.
I can get this working if I always pass fully-qualified class names inside my block, but I'm trying to effectively "re-scope" the block when it is invoked. Is this possible? I'm pretty sure RSpec and other such tools that make heavy use of blocks achieve something like this :)
Note that while I'm calling class methods from inside the block, I only want the changes to affect this individual singleton class, rather than propogate to all instances.
EDIT | Ok, here's the non-pseudo version of what I'm trying to achieve. I'm trying to add some DataMapper properties at runtime, but only to singleton classes... I don't want them to suddenly appear across all instances of the model.
class Post
include DataMapper::Resource
property :id, Serial
property :title, String
property :created_at, DateTime
... etc ...
def virtualize(&block)
singleton_class.instance_eval(&block)
self
end
end
def suspend_post
#post = Post.get!(1).virtualize do
property :delete_comments, Boolean
end
end
I know there are other ways to do virtual attributes (I'm currently using a couple of different approaches, depending on the complexity), but I'm just experimenting with a few ideas to avoid cluttering my model definitions with transient methods that are only used for transporting form data in one specific part of the site and don't mean anything when you're reading the source code of the model by itself. One or two virtual attributes are ok, but as they start to mount up on commonly used models I start to explore things like this ;)
In the above, the resource would have all of the standard properties defined in the concrete class, plus any that are added in the #virtualize method. It's the reference to Boolean without the DataMapper::Property:: prefix that's throwing it off.
You've already got what you want with respect to methods. If you define some_class_method like this:
def Foo.some_class_method(name)
define_method name do
puts("this is the method #{name}")
end
end
and do
f = Foo.new
f.build { some_class_method "new_method" }
f.singleton_methods # => [:new_method]
You've defined behavior on just that one instance.
However I don't think you can get what you're looking for with respect to constants. One option would be to use methods instead of constants for those arguments. Another would be to have the client code mix in whatever module defines the constants.
Do keep in mind this is pretty dense metaprogramming, so the complexity may not be justified.
What's wrong with this:
class SomeClass
SOME_CONSTANT = 42
class << self
def some_class_method
'foo'
end
end
def build &block
self.class.instance_eval(&block)
end
end
SomeClass.new.build do
puts "#{some_class_method} #{SOME_CONSTANT}"
end
#=>foo 42
Learning ruby. I'm under the impression that boolean attributes should be named as follows:
my_boolean_attribute?
However, I get syntax errors when attempting to do the following:
class MyClass
attr_accessor :my_boolean_attribute?
def initialize
:my_boolean_attribute? = false
end
end
Apparently ruby is hating the "?". Is this the convention? What am I doing wrong?
Edit: three-years later; the times, they are a-changin'…
Julik's answer is the simplest and best way to tackle the problem these days:
class Foo
attr_accessor :dead
alias_method :dead?, :dead # will pick up the reader method
end
My answer to the original question follows, for posterity…
The short version:
You can't use a question mark in the name of an instance variable.
The longer version:
Take, for example, attr_accessor :foo — it's simply conceptually a bit of syntactic sugar for the following:
def foo
#foo
end
def foo=(newfoo)
#foo = newfoo
end
Furthermore, the question-mark suffix is mostly just a convention to indicate that the return value of a method is a boolean.
The best approximation I can make of what you're going for here…
class MyClass
def initialize
#awesome = true
end
def awesome?
#awesome
end
end
In this case, there may be a case to be made for using attr_accessor — after all, it may be explicit that you're working directly with a boolean attribute. Generally, I save the question-mark suffix for when I am implementing a method whose boolean return value is based on slightly more complex conditions than just the value of an attribute.
Cheers!
Edit, two years later, after a recent comment:
Ruby enforces certain naming conventions. Symbols in Ruby can't have question marks. Thus invocations of :my_boolean_attribute? both will fail with a NameError. Edit: not correct, just use the quoted syntax for a symbol, e.g., :"my_attribute?"
Symbols are immutable, attempting to assign to one will throw a SyntaxError.
The easiest way to quickly add a "question method" is to use aliasing for your reader method
class Foo
attr_accessor :dead
alias_method :dead?, :dead # will pick up the reader method
end
The attr_accessor symbol implies that the variable name is #my_boolean_attribute, so that's what you should be setting (not the symbol).
Also, you can't use ? for variables, just method names.
? is convention for methodnames, not variables. You can't use an instance variable named #foo?, however you could use a variable named #foo and name the (manually created) getter method foo? if you wanted to.
Monkey-patching metaprogramming - maybe it can be made more elegant, this is only a quick draft, and I haven't done metaprogramming for a little while...
# inject the convenience method into the definition of the Object class
class Object
def Object::bool_attr(attrname)
class_eval { define_method(attrname.to_s,
lambda { instance_variable_get('#' + attrname.to_s.chop) }) }
class_eval { define_method(attrname.to_s.chop+"=",
lambda { |x| instance_variable_set('#'+attrname.to_s.chop, x) }) }
end
end
### somewhere later
class MyClass
bool_attr :my_boolean_attribute?
def initialize
#my_boolean_attribute = true
end
end
# yet even more later
foo = MyClass.new
bar = MyClass.new
foo.my_boolean_attribute = 1
puts foo.my_boolean_attribute?
puts bar.my_boolean_attribute?
With this approach, you can be DRY and get the nice questionmark too. You just might need to pick a better name than "bool_attr", like, "bool_attr_accessor" or something similar.
The definitions that I made are a bit cranky, in a sense that the question mark is present in the original symbol. Probably a cleaner approach would be to avoid the questionmark in the symbol name and append it during the definition of the method - should be less confusing.
Oh, and almost forgot to include the obligatory link: Seeing metaclasses clearly
I looked through the answers, and while the accepted answer is on-target, it introduces "extra" noise in the class. The way I'd suggest solving this issue is:
class Animal
attr_writer :can_swim
def initialize(animal_type_name)
#can_swim = true
#animal_type_name = animal_type_name
end
def can_swim?
#can_swim
end
def to_s
#animal_type_name
end
end
dog = Animal.new('Dog in a bag')
dog.can_swim = false
puts "Can this #{dog} Swim? --- [#{dog_without_legs.can_swim? ? 'YEP!' : 'NOPE!'}]"