ruby, a teeny bit at a time.

So I’ve learned Ruby and I am in love. And I just learned something that is going to make my life a whole lot easier and my scripts a lot less convoluted. Perhaps this was in one of the several books/tutorials I’ve read on the language, but I don’t remember it, or it was not presented in a way that seemed relevant to my applications.

My question was how do I get back to nameless, label-less objects based on their instance attributes? Here’s a silly example:

Here’s the definition of the Cat class:

class Cat
attr_reader :name, :byear

def initialize(name, byear)
@name = name
@byear = byear
end #def initialize
end #class Cat

My initial array—I’ll call it catdata—looked like this:
[["Be", 1996], ["Cu", 1996], ["Hal", "unknown"], ["Felix", 1919]]

I created an array of Cat objects:
cats = []

catdata.each do |e|
newcat = Cat.new(e[0], e[1])
cats.push(newcat)
end #catdata.each do

Now cats is an array of mysterious objects:
[#<Cat:0x7ff6d324>, #<Cat:0x7ff6d34c>, ...etc]

My Problem: Variable names are not assigned to the Cat objects when they are created. How do I access those Cat objects using their instance attributes? For instance, if I want to pull out all the cats born in 1996, what do I do?

I’d come up with a very ugly workaround (don’t ask), but this is much, much cleaner and I believe it can easily be defined as a method for the Cat class. (And if there is an even better/more direct way to do this, please share!)

_1996cats = cats.find_all do |cat|
cat.instance_variable_get(:@byear) == 1996
end

The result is an array with two elements: the objects for Be and Cu. Hooray!

scroodle, or, how regexps are driving me batt(y|ier).

So cataloging is picky. The content recorded has to be right. The order of elements has to be right. The capitalization has to be right. The punctuation has to be right. The spacing has to be right. The handwriting has to be right. O WATE. Thank Gautama we are no longer at the latter…

Say the correct thing to put in a particular field (ISBN) is:

1234567890 (pbk.)

But students often want to do things like record:
ISBN 1234567890 Pbk.
1234567890 (pbk.).
1-2345-6789-0

or any combination of the above, but with a mistyped number OR another valid ISBN number appearing in the book, but not the right one for the field at hand.

Main varying elements:
whether the digits recorded are correct
whether “ISBN” is put at the front or not
whether hypens are recorded or not
whether the qualifier (pbk.) is included
whether the qualifier (pbk.) is included in parentheses
whether the p in pbk. is capitalized
whether the period at the end of pbk. is included
whether a period is placed at the end of the field

But someone always comes up with something creative… And the possible combinations of errors… an explosion…

I have been using a module (lesson) in Moodle (the course/assignment development app I’m using) which allows me to construct a series of regexps and regexp-like snippets to analyze student answers step by step based on these varying elements:

First, does the typed in answer match the correct answer? Yes? Good. Have some points. Go on…

Then, are the numbers right?
^.*1-?2345-?6789-?0.*$
If that doesn’t match the answer, say “Did you record the ISBN for the manifestation you are cataloging? If you are sure you did, check to make sure you transcribed all the proper digits in order.”
If that does match, check for the next thing…

Did they include “ISBN”?
^ISBN.*$
If that matches, say “Check MARC input conventions and ignore what AACR2 says about the format for recording ISBNs.”
If it doesn’t match, go to the next thing…

and so on.

But in this module, it is very cumbersome to create exercises. It is very cumbersome to *do* the exercises, as you can only fill in one field per page.

So there is another module (quiz)that is much better for developing exercises, providing as-you-go feedback on exercises, and taking the exercises. There is a plugin to allow regexp questions. The catch?

Because the Generation routine is meant to generate all possible sentences from a regExp, the set of special/meta-characters in such a regExp is restricted to: parentheses (), the pipe | and the ? characters, the square brackets [] and the escape sign .

So I’m having a bit of trouble figuring out how to check for all these different possible errors without the handy .*

The obvious answer seemed to be to construct a regexp like:

^(ISBNs)?1-?2345-?6789-?0(s([Pp]bk.?))?s?.?$
No match? Check the numbers you put in…

And then tweak various segments to check for the common errors, like so:

^ISBNs1-?2345-?6789-?0(s([Pp]bk.?))?s?.?$
If that matches, say “Check MARC input conventions and ignore what AACR2 says about the format for recording ISBNs.”
If it doesn’t match, go to the next thing…

^(ISBNs)?1-2345-6789-0(s([Pp]bk.?))?s?.?$
If match, hint not to put in hyphens.

^(ISBNs)?1-?2345-?6789-?0s?.?$
If match, you seem to be missing the qualifying phrase.

^(ISBNs)?1-?2345-?6789-?0(s(Pbk.?))?s?.?$
If match, check the capitalization of the qualifier.

etc.

But of course this doesn’t work.

I’m afraid I’m being stupid and missing something about matching an optional phrase which is in literal parentheses. I can’t get any regexp-checker/expander/matcher thingie to accept anything I can think of to deal with this. They all choke on confusing the literal ( and ) I’m checking for, and the ( and )s I’m using to group optional strings.

So I can’t figure out how to set up this exercise to systematically check for errors, give helpful feedback and hints, and NOT require me to manually express the minor combinatorial explosion happening here.

Any ideas? Moodle is all in PHP, so I’m assuming that’s the regexp flavor in play.

Is there something about parentheses that has gone completely over my head here?

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

Alternately, how hard would it be to just make my own app/widget/dealio for these assignments?

I know how to do html forms.
I’m fairly familiar with basic regexps. (I think. Unless I’m doing something dumb above.)
I know the basic pieces of how I’d provide X feedback for Y response and tally scores.
I have various ideas about how collecting scores could work.
But I don’t know how to tie these pieces together and I really don’t have any extra time.

In fact, I’m kind of feeling physically ill about all the time I just spent figuring out what I couldn’t do with the tools at hand. And nothing to show for it.

Hence random yelling of wordless yells for catharsis… AAAAAAAAAAAAAAAAAHHRRRG!