Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I've been looking on google for an answer but I can't seem to find the right answer.
Basically I want to test out different User Interfaces(Console) in my engine. I was told to use Mock Classes, and I can't find a straight answer anywhere.
Edit:
Would this be a good way to mock a class(UI)
class UiMock
def initialize
#player_one = true
#player_two = true
#board = ["1", "2", "3", "4", "5", "6", "7", "8", "9"]
end
def set_move(mark, index)
#move_set = true
#board[(index.to_i) - 1] = mark
end
Test would be something like this
ui = UiMock.new
game = Game.new(ui)
it "creates a game" do
game.player_one.should be_true
game.player_two.should be_true
end
it "sets a move" do
game.set_move("X", 5)
ui.move_set.should be_true
end
The simplest mock object might literally be:
mock_ui = Object.new
game = Game.new( mock_ui )
# Now run your test
Normally you will need the mock to respond to methods that the Game class uses. If you provide an example of one method of the Game class that you need to test, and which methods of the real UI class that it calls, I could extend this answer to show how that might work.
It is not clear whether you are being asked to write a full emulation of a known ui class, or something simpler and tighter for specific tests. Full emulations for mocks are used less often, because they take a lot of effort to write, but the advantage is that the tests become less sensitive to changes in implementation. For example you could write a mock memcached service using hashes, and almost completely replicate the interface to Memcached class (the functionality you would lose is cross-process caching, usually not something you'd test - at least not in a unit test).
I think you current mock and test could be streamlined a little, as there is code that doesn't seem to be testing anything (yet)
class UiMock
attr_reader :move_set
def set_move(mark, index)
#move_set = true
end
end
Test:
ui = UiMock.new
game = Game.new(ui)
it "sets a move" do
game.set_move("X", 5)
ui.move_set.should be_true
end
the reason for removing some of the code is that it was not clear whether or not it was needed. Maybe you will need to represent the board and players in your mock UI, but so far the test assertions you have written don't require it. It is advisable to build these up over time as your test and code require them (even alternating between adding one or two tests and adding matching features - just enough on each part to show what needs to be coded next), unless you already have a very clear picture in your head on how all the code will fit together at the end.
Note that mocha has a simple pattern for the above test:
require 'mocha'
ui = Object.new
game = Game.new(ui)
it "sets a move" do
ui.expects( :set_move )
game.set_move("X", 5)
end
I think you're looking for Aruba, an extension of cucumber.
Also this page is a great resource for all-things command-line.
Related
Tldr: how do I 'include Shoes methods' into the Array class and classes ive created, with minimal code, without totally restructuring everything?
I've written a functioning program in Ruby, and now I want to make a Shoes app from it.
I'm having the problem described at the beginning of the manual - Shoes.app is a sort of block in itself, so self always refers to it, and Shoes methods like "para" aren't necessarily going to be available everywhere the way "puts" is in Ruby. But I'm not smart enough to fix it (I've only just got my head around using self and return in pure Ruby, bear with me)
For example, I've created a new method for Array: putdata, which loops through a student's test score array displaying each automatically as a list:
self.each do |ea|
puts/para "#{ea.topic}: #{ea.score}"
end
Works in ruby. Doesn't work in Shoes: Array class doesn't have access to the method para. I've tried:
making Array < Shoes (it really doesn't like that)
adding stack.app do...end at various places in the program (no impact)
trying to call Shoes::para instead of para (farts)
I've tried using require 'file with all my classes and methods in.rb' instead of the same code in the file (reports no method for class)
tried requiring my code directly before calling a method, to ensure my code is in the scope of Shoes (reports no method for class)
making my custom classes (Course and Student) < Shoes, so it'd have access to its methods (causes a runtime error)
I've got it to function by:
1. Removing this bit of code from the Array class, and making it a floating/generic method rather than an Array method
2. Private method error --> then rephrasing it so instead of an Array method (array.putdata) it's a generic method which takes an array as an argument (putdata(array))
But I really, really don't want to go through my code and individually un-organise it like this.
It's my first 1000 line program, with 42 methods, and I worked hard on making it as maintainable and neat as possible, with everything tucked away in classes or methods for easy upkeep. I got it from everything in massive, step-by-step generic methods down to lots of snappy ones, which seemed a bit more like how OOP is meant to go. Now the only way I can see to make this work is to UN-OOP it, and have no class methods or anything.
I was hoping I could Shoes the program fairly seamlessly from this tidy, functional back-end: the Ruby program has lots of "if string == "SAVE", save(student); else...", so I was hoping to straightforwardly pop in "button.click {save(student)}" with the same back code.
#
Is there something fundamental I'm missing to let me do this? And can I fix the para problem easily, seeing as all my classes contain ways of displaying their own data? I'd like to copypasta "include 'Shoes methods'" at the top of each class and be done.
Or do I need to be writing with the GUI in mind from the start in future?
(Info about my program:
Layout is a series of pages, linked from a sidebar, using index with linked pages as copied straight from the Nobody Knows Shoes book, or the class-book sample.
Students can input their new levels, and view a readout of their current progress.
There are generic methods for major "parts" of the program, which have things like the title of the page and some instructions, and which then call on student objects or Module methods to do the things as instructed by the user.
Higher up: student is a custom class, with methods like "save", "display flattened data ", "add one to your level IF this ELSE don't", and associated bits of data, like an array with all their course objects in.
Each course is also a custom class ("Module"), which has the score, the module name etc as variables, and some tiny methods like display formatted name, or add one to this module.)
I'm glad to see a question about shoes, it's been a long time.
You'r new on SO so first: your question is way too elaborated, too much to read and far too little information to help you.
You need to provide piecess of code that give error or don't do what you expect, things we can take over and try. This means extracting from your code tests or pieces of code that run by themself and show the problem.
We also need to know which Ruby version and which version and color of shoes you are using. The example I'll be using is green shoes.
I'm sure the following isn't exactly what you were after but I've made a sample based on your description of an Array that needs to be listed both by puts and para.
Change the question or make a new one if this is not what you are after.
require 'green_shoes'
s = Struct.new(:topic, :score)
s1 = s.new("test1", 1)
s2 = s.new("test2", 2)
A = [s1, s2]
class Array
def putsdata(shoes = nil)
if shoes.class == Shoes::App
self.each do |ea|
shoes.para "#{ea.topic}: #{ea.score}"
end
else
self.each do |ea|
puts "#{ea.topic}: #{ea.score}"
end
end
end
end
A.putsdata
# gives in the console
# test1: 1
# test2: 2
Shoes.app do
A.putsdata(self)
end
# gives in a graphic window
# test1: 1
# test2: 2
The puts also works in the shoes block, but of course the result doesn't come in the graphic window but on the console where you started, after the first list.
This question already has answers here:
When to use lambda, when to use Proc.new?
(14 answers)
Closed 8 years ago.
I am new to ruby, and while learning it I didn't understand the concept of lambdas or procs. I know lambda and proc are the blocks of code that have been bound to a set of local variables. But I don't understand their use.
So
what advantage does a programmer get from it?
I had asked this question in past and got marked as duplicate and was given a link that had totally unrelated answered so please before marking it as duplicate or scolding me please view the answers of other links by yourself first.
This is a broad question. You're basically asking "why are closures important?". Two uses that come to mind for me are:
DISCLAIMER: I haven't actually run any of this code, but it should get the point across.
Delayed execution of code. If I want to pass some code as a callback (e.g. Rails' after_create), I can use a closure to "hook" into Rails by passing a block. That block has the context of the current class, but it doesn't need to get run until Rails says so.
class SuperClass
def self.after_create(&block)
#__after_create = block
end
def self.create
# do normal create logic
instance = self.new
if #__after_create
#__after_create.call(instance)
end
end
end
class MyClass < SuperClass
after_create {|instance| instance.log}
def log
puts 'hello world!'
end
end
MyClass.create
Passing functions as parameters. This makes it easier to do things like write a generic tree traversal algorithm that just passes each node of the tree to some function:
def Tree.elements
["hello", "world!"]
end
def Tree.traverse(&block)
elements.each {|el| block.call(el)}
end
Tree.traverse {|el| puts el} # "hello" "world!"
Tree.traverse {|el| puts el.size} # "5" "6"
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I'm aware that ruby class files should generally be quite small, but sometimes I find logic in classes that (a) don't really warrant their own file, but (b) would be more readable if I could group them somehow.
For example, in certain classes I may have (let's say) 10 methods which determine paths. At the moment, I tend to just throw some a few lines of decorative "### PATHS ###" type comments around them to distinguish them from the rest of the group. I'm wondering if theres a better way(?)
Am I right in thinking implementing subclasses/modules within a class just to improve readability is a little excessive, or do other folks do this? Any other thoughts appreciated.
Maybe they do warrant their own file - Think single responsibility principle. Since you haven't shown us any code, here's an idea for a separate class that handles the paths for an object:
class FooPaths
def initialize(foo)
#foo = foo
end
def path_one
# code to calculate path using #foo
end
def path_two
#code to calculate another path using #foo
end
end
The idea is that your class Foo is probably doing too many things. Create smaller classes which accept #foo in the initializer, and then that smaller class can handle a smaller subset of operations involving Foo. It's also a lot easier to test.
When I have a bunch of similar helper methods, that means one of two things.
I have a business concept (read: object) that needs to be defined
I have a bunch of business concepts that act in a similar way.
For the first case, very often, the first argument passed into the method is the name of the business concept
class User < ActiveRecord::Base
# active record attributes :first_name, :last_name
def self.full_name(first_name, last_name)
[first_name, last_name].compact.join(" ")
end
def self.extract_first_name(full_name)
full_name.split.first
end
end
So I would create a concept for full_name:
class User << ActiveRecord::Base
# active record attributes :first_name, :last_name
def full_name
FullName.from_parts(first_name, last_name)
end
def full_name=(val)
if val
self.first_name, self_last_name = val.partsfirst_name, val.last_name
else
self.first_name = self.last_name = nil
end
end
end
class FullName
attr_accessor :first_name, :last_name
def to_s
parts.join(" ")
end
def parts
[first_name, last_name].compact
end
def eq(other)
to_s.eq(other)
end
def self.from_parts(first_name, last_name)
# [...]
end
def self.from_full_name(full_name)
# [...]
end
end
I know the example is contrived, but I've found that a lot of view logic and helpers groups around this concept. So if you end up finding more concepts that can be brought into this, or you notice that you often pass these around in groups, then it is a great candidate. Also, if you have had a number of conversations with the business users around the full name of a user, then that is really saying that you want a business concept here.
For the second case, it is sometimes the case that you want to add "the same" attribute onto a bunch of disparate business objects. They just happen to be calculated in different ways. The path for a chapter book and a dictionary are different. Introduce the concept of a chapter book and a dictionary, both having the path parameter. As stated above, if you find that you are not using these business concepts often with your users, chances are, this is not the right approach here.
I created a program that tracks car mileage and service history in order to update the user for upcoming service needs for the car.
I have three classes: Car, CarHistory, and CarServiceHistoryEntry. The third one is straightforward; it holds all the attributes associated with a service: date, mileage, service performed, etc. The CarHistory class is as follows:
require_relative 'car_service_history_entry'
class CarHistory
attr_reader :entries
def initialize (*entry)
if entry.size > 1
#entries = []
else
#entries = entry
end
end
def add_service_entry entry
#entries << entry
end
def to_s
entries_string = ""
#entries.each {|entry| entries_string << "#{entry.to_s}\n"}
entries_string
end
end
In initialize, should the class of entry be checked?
In add_service_entry, adopting duck typing (as in Andy Thomas's argument in "Programming Ruby"), would I even test if a CarServiceHistoryEntry could be added? Couldn't I just pass a String instead of setting up and then adding CarServiceHistoryEntry in my unit testing?
Since the only necessary attributes of a CarHistory are the entries array and the to_s method, should I just scrap this class all together and put it into the car class?
For 1 and 2, you need to release your tight grip on "strict-typing" when you move to a loose-typed language like Ruby.
Should you check your input arguments ? The traditional answer would be yes. An alternative way would be to have good names and unit tests that document and specify how the type is supposed to work. If it works with other types, fine.. that's an added bonus. So if you pass in an incompatible type, it would blow up with an exception, which is good enough in most-cases. Try it out and see how it feels (possible outcomes: Liberating / "Retreat!". But give it a fair try.). Exceptions would be if you're designing public APIs for shared libraries - in which the rules are different. You need to fail fast and informatively for bad-input.
As for clubbing car_history into car - I'd ask what the responsibilities of your Car class are. If maintaining its own history is one of them, you could club them. In the future, if you find a lot of methods creeping in related to car history, you could again reverse this decision and extract the CarHistory type again. Use the SingleResponsibilityPrinciple to make an informed decision. This is just OOP - Ruby doesn't degrade object design.
Code Snippet: the code can be more concise
# just for simplicity, I'm making HistoryEntry a string, it could be a custom type too
class CarServiceHistoryEntry << String
end
class CarHistory
attr_reader :entries
def initialize(*history_entries)
#entries = history_entries
end
def add_service_entry(entry)
#entries << entry
end
def to_s
#entries.join("\n")
end
end
irb>x = CarHistory.new("May 01 Overhaul", "May 30 minor repairs")
irb>x.add_service_entry("June 12 Cracked windshield")
irb>x.to_s
=> "May 01 Overhaul\nMay 30 minor repairs\nJune 12 Cracked windshield"
It's hard to comment on the relationship of the CarHistory class to your others, but I'm sure it will become clear to you as you go along.
A couple of your methods could be simplified, although I must say I didn't understand the if in initialize, perhaps it was just backwards and should have been > 0.
def initialize *entry
#entries = entry # if not specified it will be [] anyway
end
def to_s
#entries.join "\n"
end
And yes, Ruby should be simple. You don't need to litter your code with runtime type checks. If the code runs your unit tests then you can just declare victory. The zillions of explicit conversions tend to patch up type errors anyway.
Ruby is going to check your types at run-time anyway. It's perfectly reasonable to leave the type checking to the interpreter and put your effort into functional tests.
I'll skip the first two questions and answer the third. If the only attribute of a CarServiceHistoryEntry is a string, then yes, scrap CarHistory (as well as CarServiceHistoryEntry) and add a service_history attribute to Car which would just be an array of strings. Until proven otherwise, simpler is better.
As to duck typing, you would never want to test if something 'is a' only see if it 'responds to' (at most).
Finally, to answer question #1, no its supposed to be even simpler :)
Hope this helps,
Brian
I have a class that is provided to me by an external library. I have created a subclass of this class. I also have an instance of the original class.
I now want to turn this instance into an instance of my subclass without changing any properties that the instance already has (except for those that my subclass overrides anyway).
The following solution seems to work.
# This class comes from an external library. I don't (want) to control
# it, and I want to be open to changes that get made to the class
# by the library provider.
class Programmer(object):
def __init__(self,name):
self._name = name
def greet(self):
print "Hi, my name is %s." % self._name
def hard_work(self):
print "The garbage collector will take care of everything."
# This is my subclass.
class C_Programmer(Programmer):
def __init__(self, *args, **kwargs):
super(C_Programmer,self).__init__(*args, **kwargs)
self.learn_C()
def learn_C(self):
self._knowledge = ["malloc","free","pointer arithmetic","curly braces"]
def hard_work(self):
print "I'll have to remember " + " and ".join(self._knowledge) + "."
# The questionable thing: Reclassing a programmer.
#classmethod
def teach_C(cls, programmer):
programmer.__class__ = cls # <-- do I really want to do this?
programmer.learn_C()
joel = C_Programmer("Joel")
joel.greet()
joel.hard_work()
#>Hi, my name is Joel.
#>I'll have to remember malloc and free and pointer arithmetic and curly braces.
jeff = Programmer("Jeff")
# We (or someone else) makes changes to the instance. The reclassing shouldn't
# overwrite these.
jeff._name = "Jeff A"
jeff.greet()
jeff.hard_work()
#>Hi, my name is Jeff A.
#>The garbage collector will take care of everything.
# Let magic happen.
C_Programmer.teach_C(jeff)
jeff.greet()
jeff.hard_work()
#>Hi, my name is Jeff A.
#>I'll have to remember malloc and free and pointer arithmetic and curly braces.
However, I'm not convinced that this solution doesn't contain any caveats I haven't thought of (sorry for the triple negation), especially because reassigning the magical __class__ just doesn't feel right. Even if this works, I can't help the feeling there should be a more pythonic way of doing this.
Is there?
Edit: Thanks everyone for your answers. Here is what I get from them:
Although the idea of reclassing an instance by assigning to __class__ is not a widely used idiom, most answers (4 out of 6 at the time of writing) consider it a valid approach. One anwswer (by ojrac) says that it's "pretty weird at first glance," with which I agree (it was the reason for asking the question). Only one answer (by Jason Baker; with two positive comments & votes) actively discouraged me from doing this, however doing so based on the example use case moreso than on the technique in general.
None of the answers, whether positive or not, finds an actual technical problem in this method. A small exception is jls who mentions to beware of old-style classes, which is likely true, and C extensions. I suppose that new-style-class-aware C extensions should be as fine with this method as Python itself (presuming the latter is true), although if you disagree, keep the answers coming.
As to the question of how pythonic this is, there were a few positive answers, but no real reasons given. Looking at the Zen (import this), I guess the most important rule in this case is "Explicit is better than implicit." I'm not sure, though, whether that rule speaks for or against reclassing this way.
Using {has,get,set}attr seems more explicit, as we are explicitly making our changes to the object instead of using magic.
Using __class__ = newclass seems more explicit because we explicitly say "This is now an object of class 'newclass,' expect a different behaviour" instead of silently changing attributes but leaving users of the object believing they are dealing with a regular object of the old class.
Summing up: From a technical standpoint, the method seems okay; the pythonicity question remains unanswered with a bias towards "yes."
I have accepted Martin Geisler's answer, because the Mercurial plugin example is a quite strong one (and also because it answered a question I even hadn't asked myself yet). However, if there are any arguments on the pythonicity question, I'd still like to hear them. Thanks all so far.
P.S. The actual use case is a UI data control object that needs to grow additional functionality at runtime. However, the question is meant to be very general.
Reclassing instances like this is done in Mercurial (a distributed revision control system) when extensions (plugins) want to change the object that represent the local repository. The object is called repo and is initially a localrepo instance. It is passed to each extension in turn and, when needed, extensions will define a new class which is a subclass of repo.__class__ and change the class of repo to this new subclass!
It looks like this in code:
def reposetup(ui, repo):
# ...
class bookmark_repo(repo.__class__):
def rollback(self):
if os.path.exists(self.join('undo.bookmarks')):
util.rename(self.join('undo.bookmarks'), self.join('bookmarks'))
return super(bookmark_repo, self).rollback()
# ...
repo.__class__ = bookmark_repo
The extension (I took the code from the bookmarks extension) defines a module level function called reposetup. Mercurial will call this when initializing the extension and pass a ui (user interface) and repo (repository) argument.
The function then defines a subclass of whatever class repo happens to be. It would not suffice to simply subclass localrepo since extensions need to be able to extend each other. So if the first extension changes repo.__class__ to foo_repo, the next extension should change repo.__class__ to a subclass of foo_repo and not just a subclass of localrepo. Finally the function changes the instanceø's class, just like you did in your code.
I hope this code can show a legitimate use of this language feature. I think it's the only place where I've seen it used in the wild.
I'm not sure that the use of inheritance is best in this case (at least with regards to "reclassing"). It seems like you're on the right track, but it sounds like composition or aggregation would be best for this. Here's an example of what I'm thinking of (in untested, pseudo-esque code):
from copy import copy
# As long as none of these attributes are defined in the base class,
# this should be safe
class SkilledProgrammer(Programmer):
def __init__(self, *skillsets):
super(SkilledProgrammer, self).__init__()
self.skillsets = set(skillsets)
def teach(programmer, other_programmer):
"""If other_programmer has skillsets, append this programmer's
skillsets. Otherwise, create a new skillset that is a copy
of this programmer's"""
if hasattr(other_programmer, skillsets) and other_programmer.skillsets:
other_programmer.skillsets.union(programmer.skillsets)
else:
other_programmer.skillsets = copy(programmer.skillsets)
def has_skill(programmer, skill):
for skillset in programmer.skillsets:
if skill in skillset.skills
return True
return False
def has_skillset(programmer, skillset):
return skillset in programmer.skillsets
class SkillSet(object):
def __init__(self, *skills):
self.skills = set(skills)
C = SkillSet("malloc","free","pointer arithmetic","curly braces")
SQL = SkillSet("SELECT", "INSERT", "DELETE", "UPDATE")
Bob = SkilledProgrammer(C)
Jill = Programmer()
teach(Bob, Jill) #teaches Jill C
has_skill(Jill, "malloc") #should return True
has_skillset(Jill, SQL) #should return False
You may have to read more about sets and arbitrary argument lists if you aren't familiar with them to get this example.
This is fine. I've used this idiom plenty of times. One thing to keep in mind though is that this idea doesn't play well with old-style classes and various C extensions. Normally this wouldn't be an issue, but since you are using an external library you'll just have to make sure you're not dealing with any old-style classes or C extensions.
"The State Pattern allows an object to alter its behavior when its internal state changes. The object will appear to change it's class." - Head First Design Pattern. Something very similar write Gamma et.al. in their Design Patterns book. (I have it at my other place, so no quote). I think that's the whole point of this design pattern. But if I can change the class of an object at runtime, most of the time i don't need the pattern (there are cases when State Pattern does more than simulate a class change).
Also, changing class at runtime doesn't always work:
class A(object):
def __init__(self, val):
self.val = val
def get_val(self):
return self.val
class B(A):
def __init__(self, val1, val2):
A.__init__(self, val1)
self.val2 = val2
def get_val(self):
return self.val + self.val2
a = A(3)
b = B(4, 6)
print a.get_val()
print b.get_val()
a.__class__ = B
print a.get_val() # oops!
Apart from that, I consider changing class at runtime Pythonic and use it from time to time.
Heheh, fun example.
"Reclassing" is pretty weird, at first glance. What about the 'copy constructor' approach? You can do this with the Reflection-like hasattr, getattr and setattr. This code will copy everything from one object to another, unless it already exists. If you don't want to copy methods, you can exclude them; see the commented if.
class Foo(object):
def __init__(self):
self.cow = 2
self.moose = 6
class Bar(object):
def __init__(self):
self.cat = 2
self.cow = 11
def from_foo(foo):
bar = Bar()
attributes = dir(foo)
for attr in attributes:
if (hasattr(bar, attr)):
break
value = getattr(foo, attr)
# if hasattr(value, '__call__'):
# break # skip callables (i.e. functions)
setattr(bar, attr, value)
return bar
All this reflection isn't pretty, but sometimes you need an ugly reflection machine to make cool stuff happen. ;)
This technique seems reasonably Pythonic to me. Composition would also be a good choice, but assigning to __class__ is perfectly valid (see here for a recipe that uses it in a slightly different way).
In ojrac's answer, the break breaks out of the for-loop and doesn't test any more attributes. I think it makes more sense to just use the if-statement to decide what to do with each attribute one at a time, and continue through the for-loop over all attributes. Otherwise, I like ojrac's answer, as I too see assigning to __class__ as weird. (I'm a beginner with Python and as far as I remember this is my first post to StackOverFlow. Thanks for all the great information!!)
So I tried to implement that. I noticed that dir() doesn't list all the attributes. http://jedidjah.ch/code/2013/9/8/wrong_dir_function/ So I added 'class', 'doc', 'module' and 'init' to the list of things to add if they're not there already, (although they're probably all already there), and wondered whether there were more things dir misses. I also noticed that I was (potentially) assigning to 'class' after having said that was weird.
I will say this is perfectly fine, if it works for you.