[Nitro] TRANS: Facets annotation problems

TRANS transfire at gmail.com
Wed Sep 20 07:25:28 EDT 2006


On 9/20/06, Michael Fellinger <manveru at weez-int.com> wrote:
> Heya,
>
> Well, guess i should apologize as well, since annotations drove my weak brain
> mad.
> but it was just impossible for us to figure out how they actually are intended
> to work and how they really work.
> could you please explain us some more things given some examples?

No need to apologoize. I understand the 1.4.5 version is mind numbing,
which is why I re-wrote it. It's MUCH simpler now. But likewise there
still some tweaks needed  to get it to work just right, which I'm
working on.

> <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< lots of code >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>
> require 'rubygems'
> require 'facets/more/annotation'
>
> class A
>   # those seem to be annotations for the class itself?
>   ann.self.foo = 1
>   ann self, :foo => 2

Yes. And these two notations are equivalent, annotating the class itself. Ie.

  A.ann(A).foo

>   # annotations for instances?
>   ann[:foo] = 3
>   ann.foo = 4

Nope. You need another level. Eg.

  ann :foo, :bar => 3

Which is why you are getting null when you try to read it. The
annotation key (in this case :foo) generally represents a method, to
which you apply key-value settings (eg :bar=>3).

Okay. Let's back up a sec. You may recall me bringing this up before
and I think maybe this is a good time to do so again. At first I
thought the A.ann.foo.bar notation was great, but over time I've come
to no longer like it  so much. I don't think it's very intuitive and I
also think it's better to have fewer forms to learn. Presently, all
these do the same thing:

   A.ann.foo.bar
   A.ann.foo[:bar]
   A.ann[:foo][:bar]
   A.ann(:foo)[:bar]
   A.ann(:foo).bar
   A.ann[:foo].bar
   A.ann(:foo, :bar)

I think it would be better if only the last one worked, plus:
A.ann[:foo,:bar] (which currently doesn't work). It may not look as
pretty but it's more versitle and easier to comprehend then all of the
above.

> ok, i've got no idea what's going on there :)
> but it seems rather mysterious to say .self all the time and get null
> otherwise.

Yea, the null is a fluke and your doing something that actually should
raise an error b/c your not supplying the key-value pair. This problem
doesn't arise in the new version

> also, regarding ? and ! - i didn't check if they work properly, i just got
> some errors regarding these lines:
>
> owner_class.ann :self, :join_tables => [] unless owner_class.ann.join_tables?
> owner_class.ann.join_tables! << join_table_info
>
> and... well, i just thought there was some mysterious and deep magic going
> on... calling methods on a method with ! seems to me very un-ruby-like :)

Not really. '!' generally means "in place" and that's pretty much
what's going on here. The '!' serves a similar purpose by duplicting
the superclass annotation key-value to the subclass. << is an inplace
operation so that is sometimes needed in order to "prime" the value.
Otherwise it would raise an error 'undefined method for nil'. In this
particular case though I don't think it's neccessary b/c the
superclass/subclass is not involved.

(Note the use of '!' I think change slightly from a much older version
of annotations that used inheritor.rb, which might explain this usage.
But it's been too long and I don't recall for sure.)

> i somehow got that ? returns a boolean, but in some cases i got a usual object
> back, not true|false, so i was stupified by that as well.

In Ruby there is no such thin as boolean. All things a "true" except
false and nil. So ? returns the object if it exists, otherwise unless
'nil' (as opposed to null).

> could you explain in a couple of sentences what annotations are made for, how
> they are integrated in nitro (and especially, og) and how we should make use
> of them?

Annotations are "notes" used to programmatically describe other parts
of the system. The overwhelmingly common use is to describe
information for attributes (and methods, which is what attribute's are
in Ruby). So for instance, lets say I want to describe the class of
object an attribute is supposed to hold. I could do:

  class A
    attr :a
    ann :a, :class => Integer
  end

The annotation doesn't actually _do_ anything. It's just a note about
attribute :a. But elsewhere I might have a validator method that looks
at this annotation to determine if #a has valid content.

Nitro uses annotations primarily to describe ORM information --how a
classes' attributes map to a database.

You can use them for whatever you like. After all they're just notes.
The only thing one needs to be careful about is stepping on other
people's annotation "toes", i.e. using the same key for different
purposes (which is probably the weakest point of annotations b/c it
can be hard to tell what other annotations might already be in use).
Common uses that I've already seen are ORM, validation and built-in
help information.

Finally, I'll note that Annoations and how they basically work are
George's invention, and were designed with Og in mind. I took on
implementation b/c I saw the general utility of such a lib and thought
it a good fit for Facets.

HTH,
T.

-- 
( o-
 //    trans.
/ /    transfire at gmail.com

       http://weblands.blogspot.com
       http://7ranscode.blogspot.com
       http://stampact.blogspot.com


More information about the Nitro-general mailing list