hoodwink.d enhanced


Less method_missing in Markaby #

by why in inspect

In the new Markaby branch, I’ve got a list of valid tags and attributes generated from the XHTML 1.0 Transitional and XHTML 1.0 Strict DTDs. Which means Markaby can validate as you go.

 >> div :styl => 'margin:10px' do
 >>   h1 "Never To Be Seen" 
 >> end
 Markaby::InvalidXhtmlError: no attribute `styl' on div elements

 >> salect :onclick => 'javascript:alert("GIMMICK!")' do
 >>   option '- please -'
 >> end
 NoMethodError: no such method `salect'

However, there is no check right now to make sure that the nesting is right. It’ll let you put a tbody in a div, for example. But it’s a start.

The implicit stringification of tags and helpers is working fantastic now as well. Can ERB compete with this (from CampSh [103]):

 strong(author) + " worked on: " + 
   cmds.map { |cmd| 
     a cmd.name, :href => R(Show, cmd.name) }.join(", ")

There’s little need for the capture statement any longer. If you need to force a capture, call to_s on the HTML fragment.

 div { 
   @a = small('Miniature').to_s
   @b = strong('Large').to_s
   h1 "Monkeys" 
   h2 { "Giraffes #{@a} and #{@b}" }
   h3 "Donkeys" 
   h4 { "Parakeet #{@b} as well..." }

It’s not needed in the above example, though, since the string interpolation will call to_s for you. Does that make sense?

said on 22 May 2006 at 17:44


And here I’ve been thinking the small tag was deprecated (it ain’t).

said on 22 May 2006 at 18:16

OK, what exactly is CampSH? It’s never seemed to do anything for me. At all.

said on 22 May 2006 at 18:42

Oh… Validate as you go feature… that’s very nice!

said on 23 May 2006 at 08:20

Is there any easy way to restrict method calls to only Markaby tags?

For security reasons – like if you wanted to grant customer access to markaby view templates without them being able to plug in any ol’ arbitrary ruby?

said on 23 May 2006 at 09:32

That’s a good question. The primary problem being that top-level modules are still addressable from a closure anywhere in script.

 div.content do
   Kernel::fork while true

It can be done, but you’ll need do some serious sandboxing: removing all possible harmful methods and modules, then executing their script inside a Thread with heightened $SAFE.

I mean you’re still going to need some Ruby around. (Time.now, string and array methods, etc.)

said on 23 May 2006 at 12:06

Nice job on the validity constraints, why! Do good for the cause of validation everywhere.

said on 23 May 2006 at 12:20

As far as sandboxing goes, I still haven’t been able to figure out a robust solution that didn’t involve setting up a whole other separate Ruby interpreter with a gutted environment (as TryRuby does).

I think everyone would like something like TCL ’s interp stuff, which as far as I can remember are basically all in the same environment but names resolve differently inside each.

To do something like that in Ruby, it looks like you can hack the name part of things pretty easily in variable.c, and then elsewhere make those “namespaces” selectable on a per-thread basis. The problem is that you still have to cope with things like “who is rb_cObject to-day?”

said on 23 May 2006 at 12:27

Well, alternately to having different rb_cObjects in different “namespaces”, you could have ivar tables look different on a per-namespace basis.

That’s got to be simpler than swapping around rb_cObject. Now, to figure out how to make the overhead not suck…

said on 23 May 2006 at 12:57

Yeah, it’s tricky, but I think it can be done. If you eval within a binding where everything is a proxy object, it’d be a bit slower, but you could watch objects pass in and out and make sure there’s no reference to any thing in the actual environment. It’d have to be in a C extension, though, since you can’t hide somethings.

The rb_cObject point hits it though. I mean if there’s anyway to get a handle to that, you’re sunk.

said on 23 May 2006 at 15:26

Wow, great response.

OK, what about a psuedo markaby where the whole template looks/acts like real markaby but is really interpreted by another process. Then when a decent sandboxing exists, make the switch and all the templates still work, users will be none the wiser and champagne will flow forth, etc.

said on 23 May 2006 at 17:32

why: no, you can’t proxy everything. If nothing else, NIL_P() needs the real Qfalse and Qnil to work with.

But you’ve also got to deal with the various sorts of Ruby expressions that create objects without an intervening method call. If someone creates an array and gets ahold of the real rb_cArray or rb_cString (or rb_cProc!), that’s just as bad really.

I’m becoming certain that only solution is to have rb_cObject, rb_cArray, rb_cString, etc. offer different constants and methods depending on which “partition” you’re in.

It’s not hard to see how to make this work—just add an interface from variable.c to create and select a current “partition”, and then make the notion of a “current partition” part of the thread state. Threads inherit the partition of their parent until the link is severed and they receive a copy to modify.


said on 23 May 2006 at 17:41

Well, hmm. So we create a fresh object in one partition and pass it to another partition. Will that work? It’s got a fresh blank ivar table in the other partition…

said on 23 May 2006 at 17:56

I guess the only problem is if certain ivar entries are expected to always be there by the Ruby runtime itself? Are there any?

said on 23 May 2006 at 18:10

Ah, but how are proxy objects supposed to work? I’ll have to think about this some more.

said on 23 May 2006 at 18:14

Okay, so each sandbox represents a new, blank symbol table. Eval is hacked to point to that symbol table. Remember: all the default VALU Es (rb_cObject, rb_cString, etc.) are just numbers. So it’s okay if those get passed around, so long as eval always hits the sandboxed st_table.

I need to do some studying on rb_class_tbl and sym_tbl. I think the latter could be shared.

said on 23 May 2006 at 22:03

Hmm, that sounds promising.

said on 23 May 2006 at 22:29

I wrote the word ‘bacon’ on every single page of my year 9 diary.

said on 24 May 2006 at 12:12

One more thing to think about—isthis sandboxing stuff similar to selector namespaces? Maybe it should be approached as a generalization of them?

said on 24 May 2006 at 12:27

I guess something else to think about is how to bootstrap an empty partition/namespace/sandbox. I do think the ability to create one that is totally empty is really important to be able to use it for sandboxing.

said on 24 May 2006 at 16:39

I might be a bit dense, but I can’t for the life of me get markaby to validate the headers that it wants to generate. I patched, pleaded, and cajoled and markaby gives up on xml:lang, then meta, then me. Any suggestions? Should I just hurry up and wait?

said on 24 May 2006 at 17:01

yeah i had to tweak this version for Raelian purposes..

- tag!(:html, :xmlns => “http://www.w3.org/1999/xhtml”, “xml:lang” => “en”, :lang => “en”, &block)

otherwise it was devalidating its own header! + tag!(:html, :xmlns => “http://www.w3.org/1999/xhtml”, :lang => “en”, &block)

said on 24 May 2006 at 17:03

and set the metatag and xml_struction config keys to False (in the source code, since it didnt seem to be picking up on environment.rb)

maybe i just dont know enough about this XHTML thing, can you start a doc with or something instead?

said on 24 May 2006 at 18:58

carmen, hogepodge: Okay, the branch is updated. I think xml:lang wasn’t part of xhtml 1.0. Anyway, give it a try.

said on 24 May 2006 at 19:05

I take that back. Namespaced tags aren’t policed anymore.

said on 25 May 2006 at 11:46

how would i write a helper method that looked something like this:

foobar do h1 “here” end

and produced:


said on 25 May 2006 at 13:54

that ‘here’ was supposed to be a h1 tag enclosed in a div tag. i wasn’t using fancy stuff right.

so how can i produce some markup with #foobar and have the given block produce some markup inside of #foobar’s markup?

said on 25 May 2006 at 15:54

div.foobar! do
  h1 "here" 
This isn’t succinct enough?
said on 25 May 2006 at 16:01

Good job, dogberry. _why feeds dogberry a handful of catraisins.

said on 26 May 2006 at 16:25

Maybe I’m missing something, but shouldnt it be…

:table => Attrs + [ :cellpadding, :cellspacing, :border, :width, :frame, :rules ]

to satisfy: http://www.w3.org/TR/xhtml-modularization/abstract_modules.html#sec_5.6.

And actually, it seems to me that all elements should have AttrCustom…

said on 27 May 2006 at 03:53

mentalguy, i was wondering about the selector namespace thing too. is there a writeup anywhere about the proposed implementation of selector namespaces in 2.0?

said on 28 May 2006 at 15:26

zem: not that I can find.

12 Jul 2010 at 22:21

* do fancy stuff in your comment.