http://cleverdevil.org/computing/52/making-a-statement-with-elixir
This is one of the more interesting features of Elixir, I think.
--
Jonathan LaCour
http://cleverdevil.org
Wow, that's definitely very cool.
In the Taggable where you define "get_by_tag", can't you use "cls" in
place of "entity"? Using "entity" you're creating a closure with a
circular reference between the "entity" class and the function.
Probably not a big deal since the entity classes will be declared at
the module level, so garbage collection isn't an issue, but "cls" is
less typing anyways ;)
-- Matt Good
Very nice. I'll shut up now about declarative stuff, because this is
really darned cool.
> This is one of the more interesting features of Elixir, I think.
Indeed :)
--
"Bureaucrat Conrad, you are technically correct -- the best kind of correct."
> Wow, that's definitely very cool.
I think so too :)
Now, lets get some people cracking on writing a huge library of useful
Elixir plugins:
acts_as_taggable()
acts_as_versioned()
acts_as_ratable()
acts_as_secured()
converts_using_textile(on_field='content')
converts_using_markdown(on_field='content')
... and the list goes on and on!
> In the Taggable where you define "get_by_tag", can't you use "cls"
> in place of "entity"? Using "entity" you're creating a closure with
> a circular reference between the "entity" class and the function.
> Probably not a big deal since the entity classes will be declared at
> the module level, so garbage collection isn't an issue, but "cls" is
> less typing anyways ;)
Yeah, you could use 'cls' instead. I am not sure it really matters
though :)
>I just posted a tutorial on how to create your own Elixir DSL
>statements:
>
>http://cleverdevil.org/computing/52/making-a-statement-with-elixir
Really nice tutorial, it really opens a lot of possibilities.
>This is one of the more interesting features of Elixir, I think.
Indeed !
--
(°> Nicolas Évrard
/ ) http://openhex.org
^^
This is very nice syntax -- the taggable example really brings that to
light. Pretty and flexible!
But unfortunately the current implementation is flawed.
zope.interface and other libs that do this sort of manipulation of a
surrounding
class via non-assignment statements do it by finding the frame of the
calling class. But elixir uses a global statements list (effectively,
as it's a class property of the Statement class), which I means that
if you were to try to define multiple elixir entities in separate
threads, you would be in big trouble as their statements would
randomly intermingle.
You can see this happen even without resorting to threads -- try
defining one entity as an inner class of another:
from elixir import *
class Thing(Entity):
has_field('name', String(40))
has_field('type', String(40))
class Stuff(Entity):
has_field('ping', String(32))
has_field('pong', String(32))
has_field('other', String(40))
Then look at Thing.c -- 2 columns, 'id' and 'other'. All of the other
columns attach to Stuff.
If you wade through at zope.interface.declarations (especially see the
_implements() function), they are doing pretty similar stuff, but
finding the class to manipulate using sys.get_frame and modifying it
by writing to the locals of the class frame. That's the safe way to
implement this sort of thing -- the only safe way I know of, at least.
JP
> This is very nice syntax -- the taggable example really brings that to
> light. Pretty and flexible!
Thanks, I am glad to hear you like it!
> But unfortunately the current implementation is flawed.
>
> zope.interface and other libs that do this sort of manipulation of a
> surrounding class via non-assignment statements do it by finding the
> frame of the calling class. But elixir uses a global statements list
> (effectively, as it's a class property of the Statement class), which
> I means that if you were to try to define multiple elixir entities
> in separate threads, you would be in big trouble as their statements
> would randomly intermingle.
Yes, I was aware of the problem, but wasn't aware of that particular
solution that you suggested. Its actually quite simple to fix thanks to
your suggestion of inspecting the callframes. I just committed a change
to the Elixir SVN repository, along with a test, that fixes this
problem. We'll roll a new release at some point soon.
I was going to attempt to fix it using locks, and a more traditional
approach, but this way is much easier, if not a little weird.
> You can see this happen even without resorting to threads -- try
> defining one entity as an inner class of another:
>
> from elixir import *
>
> class Thing(Entity):
> has_field('name', String(40))
> has_field('type', String(40))
>
> class Stuff(Entity):
> has_field('ping', String(32))
> has_field('pong', String(32))
>
> has_field('other', String(40))
And thanks for this nice way to test it without having to resort to
using threads :) I used this exact example in the unit test that I just
added.
Again, I appreciate the feedback.
Glad to help. I didn't see a bug tracker linked off of the elixir site
-- did I miss it, or is it not set up yet?
JP
We have no bug tracker yet... but this obviously needs to be resolved.
I'd like to keep it simple, since our goal is eventually to become an
SQLAlchemy extension and use their bug tracking, etc. I am not really
sure that Trac fits the bill there, but I don't know of anything else
that we could use in the meantime.
Lets see if Daniel or Gaetan (or anyone else) has an idea.