I have a magical proposal for the anti-magic web framework. Controller methods do not use arguments and yet expect arguments. This is handled through this params hash because we don''t know in advance what parameters a client could pass to Merb. But in almost every instance, it is too much to know all the query parameters - one doesn''t care if the user threw in an extraneous variable - one only cares about the variables we need to process the action. Instead of using params we could make actions more functional by taking advantage of this cool programming concept called ''arguments''. An example class ProductController def show(id) # GET /products/show?id=12 @product = Product.find(id) render end def index(page = 1) # GET /products?page=2 @products = Product.paginate_all(page) render end end Getting a parameter list for a method is rather difficult, but using zenspider''s ParseTree, it is possible. (Attached is a proof of concept. It is also viewable at http://pastie.caboo.se/93218 ) ParseTree is slow, but it only needs to be run once at load - we can cache the argument lists for each method. It is extremely magical, but the magic is limited in scope - we are not going to be using this all around the the source tree. Only for controller actions. It does not increase the frame stack and should have zero effect on performance. Advantages: - Less to type. No more params[:username], just username - Cleaner API. At a glance it is visible what parameters actions take. - params in its current state is slightly dangerous. Clients can pass to it whatever (key, value) pairs they want and Merb will blindly symbolizes the keys. These symbols are never garbage collected. - We can automatically raise a BadRequest if the user does not supply all of the arguments needed. I would happily implement this if Ezra and the list thinks that this would be a welcome feature. ry -------------- next part -------------- A non-text attachment was scrubbed... Name: method_args.rb Type: text/x-ruby-script Size: 831 bytes Desc: not available Url : http://rubyforge.org/pipermail/merb-devel/attachments/20070902/d8fed299/attachment.bin
On Sep 2, 2007, at 5:17 AM, ry dahl wrote:> I have a magical proposal for the anti-magic web framework. >Personally, I appreciate magic when it''s scientifically reasonable :)> Controller methods do not use arguments and yet expect arguments. This > is handled through this params hash because we don''t know in advance > what parameters a client could pass to Merb. But in almost every > instance, it is too much to know all the query parameters - one > doesn''t care if the user threw in an extraneous variable - one only > cares about the variables we need to process the action. > > Instead of using params we could make actions more functional by > taking advantage of this cool programming concept called ''arguments''. > An example > > class ProductController > def show(id) # GET /products/show?id=12 > @product = Product.find(id) > render > end > > def index(page = 1) # GET /products?page=2 > @products = Product.paginate_all(page) > render > end > end >I would like this a lot. One side effect might be, however, that the ''params'' hash currently in use in the views will no longer be available. We could, of course, just leave the params hash in as well, but let''s assume we remove it completely. Does this mean that controllers would have to wrap arguments in instance variables if it''s necessary to pass them along to the view? e.g.: def index(page = 1, show_extra = true) @show_extra = show_extra # ... end Perhaps these arguments should become "locals" in the view as well?> Getting a parameter list for a method is rather difficult, but using > zenspider''s ParseTree, it is possible. (Attached is a proof of > concept. It is also viewable at http://pastie.caboo.se/93218 ) > > ParseTree is slow, but it only needs to be run once at load - we can > cache the argument lists for each method. >Would this make Merb a *nix-only framework?> It is extremely magical, but the magic is limited in scope - we are > not going to be using this all around the the source tree. Only for > controller actions. > > It does not increase the frame stack and should have zero effect on > performance. > > Advantages: > - Less to type. No more params[:username], just username > - Cleaner API. At a glance it is visible what parameters actions take.The cleaner API is what makes my preference tip towards magic in this case. Controllers become very readable with this addition.> - params in its current state is slightly dangerous. Clients can pass > to it whatever (key, value) pairs they want and Merb will blindly > symbolizes the keys. These symbols are never garbage collected.Hmm. I didn''t know that.> - We can automatically raise a BadRequest if the user does not supply > all of the arguments needed. >Nice.> I would happily implement this if Ezra and the list thinks that this > would be a welcome feature. >Just to throw it out there for discussion, is it possible to prepare the framework in such a way that we could turn a ParseTree controller implementation into a plugin? Regards, Duane Johnson (canadaduane)
> I would like this a lot.Thanks :)> One side effect might be, however, that the > ''params'' hash currently in use in the views will no longer be > available. We could, of course, just leave the params hash in as > well, but let''s assume we remove it completely. Does this mean that > controllers would have to wrap arguments in instance variables if > it''s necessary to pass them along to the view? e.g.: > > def index(page = 1, show_extra = true) > @show_extra = show_extra > # ... > end > > Perhaps these arguments should become "locals" in the view as well?I would recommend keeping the params hash around for backwards compatibility but with a depreciation warning. I don''t think query params should automatically become locals of the view. it''s not so often that you pass query params directly to the view> Would this make Merb a *nix-only framework?I don''t know if ParseTree compiles on windows, but if it doesn''t, there isn''t any reason why it shouldn''t be able to. It only uses pure ruby stuff.> Just to throw it out there for discussion, is it possible to prepare > the framework in such a way that we could turn a ParseTree controller > implementation into a plugin?Probably (maybe with the help of some new hooks in the dispatcher). However, I would really like to have this considered for the core controller since it''s a fairly fundamental API issue and doesn''t effect performance/memory footprint (I think!). I guess the real tough question is: do people mind having ParseTree as a dependency? ry
> I don''t know if ParseTree compiles on windows, but if it doesn''t, > there isn''t any reason why it shouldn''t be able to. It only uses pure > ruby stuff.This came out wrong. I meant that its written in C but the only C library it uses is ruby. ry
On Sep 2, 2007, at 8:16 AM, ry dahl wrote:>> I don''t know if ParseTree compiles on windows, but if it doesn''t, >> there isn''t any reason why it shouldn''t be able to. It only uses pure >> ruby stuff. > > This came out wrong. I meant that its written in C but the only C > library it uses is ruby. > > ryRy- We already implemented this exact thing in a bit more robust way: http://pastie.caboo.se/93260 But I decided that ParseTree is too heavy of a dependency. Partree will never work on windows with the one click installer. Since it uses rubyinline it needs a C compiler every time it''s run :( So adding this as a dependency would not only make it not work on windows anymore, it would also make it not work on production servers that don''t have a C compiler installed which is a lot of production *nix servers. I do like the idea of it and it does not affect performance because parsetree is only ran once on server boot. But it''s not going to happen because of the heavy dependency that would limit where merb can run. Most shared hosts don''t let you use a C compiler and windows definitely doesn''t work with parsetree unless you use cygwin which is not really a solution. Cheers- -- Ezra Zygmuntowicz -- Founder & Ruby Hacker -- ez at engineyard.com -- Engine Yard, Serious Rails Hosting -- (866) 518-YARD (9273)
> We already implemented this exact thing in a bit more robust way: > > http://pastie.caboo.se/93260Wow! Hot!> But I decided that ParseTree is too heavy of a dependency. Partree > will never work on windows with the one click installer. Since it > uses rubyinline it needs a C compiler every time it''s run :( So > adding this as a dependency would not only make it not work on > windows anymore, it would also make it not work on production servers > that don''t have a C compiler installed which is a lot of production > *nix servers. > > I do like the idea of it and it does not affect performance because > parsetree is only ran once on server boot. But it''s not going to > happen because of the heavy dependency that would limit where merb > can run. Most shared hosts don''t let you use a C compiler and windows > definitely doesn''t work with parsetree unless you use cygwin which is > not really a solution.I could (probably) extract/repackage the code from ParseTree to do just the parameter extraction (and without RubyInline). If we had that extension, would it change your opinion? ry
On Sun, Sep 02, 2007 at 01:17:01PM +0200, ry dahl wrote:> I have a magical proposal for the anti-magic web framework....> Instead of using params we could make actions more functional by > taking advantage of this cool programming concept called ''arguments''. > An example > > class ProductController > def show(id) # GET /products/show?id=12 > @product = Product.find(id) > render > end > > def index(page = 1) # GET /products?page=2 > @products = Product.paginate_all(page) > render > end > endJust to add a dissenting voice - I very much dislike this idea. I consider Merb to be a simple framework, "what you would end up with if you started writing a Mongrel custom handler" was I think how someone described it. I don''t like the idea of my code having to be *parsed* to add magic, and I wouldn''t be confident that it would work in all cases (e.g. what about if I put controller actions in a module and mix them in? What if I define controller actions dynamically at runtime, e.g. based on reflecting the database?) I would prefer, if this is done, that it be made as a plugin, so I don''t have to have it. However I have a couple of observations to add: (1) Bog-standard rdoc is able to parse method definitions, so it probably doesn''t need a heavyweight parsing library. Perhaps even rdoc itself could be used. (2) I can think of a much simpler way to get a similar effect: use method_missing to define an accessor method the first time a parameter is accessed. Outline: def method_missing(arg, *rest) if params.has_key(arg) and rest.size == 0 eval("def #{arg}; params[#{arg.inspect}]; end") # FIXME!! return params[arg] end raise NoMethodError end As long as the method is defined in the controller class, not the controller instance, then the eval is run only the first time it is used. Of course, when you write Product.paginate_all(page) then ''page'' still has the overhead of a method call, rather than dereferencing a local variable, but I believe that would be very small in the majority of cases. It would also be offset against the overhead of preparing the correct argument list in the "magic" design. Also, ''id'' would need to be a special case given that it''s a (deprecated) existing method. def id params[:id] end> - params in its current state is slightly dangerous. Clients can pass > to it whatever (key, value) pairs they want and Merb will blindly > symbolizes the keys. These symbols are never garbage collected.This is a separate problem. I think the solution is to leave the keys as strings in the params hash; I guess they start out as strings initially (e.g. from regexp matching or XML parsing). So no extra garbage is created up-front, and indeed less work will be done up-front in converting parameters to symbols which may not actually be used. Of course, params[''id''] still generates garbage unfortunately, as will params[:id] if it is converted to a string internally, as I believe HashWithIndifferentAccess from ActiveSupport does. The solution I propose is something like Symbol#to_s which returns the *same* frozen string object each time it is called. That''s easily implemented: class Symbol @@_stringreps = Hash.new { |h,k| h[k] = k.to_s.freeze } def to_fring @@_stringreps[self] end end irb(main):008:0> :foo.to_fring => "foo" irb(main):009:0> :foo.to_fring.object_id => -605563374 irb(main):010:0> :foo.to_fring.object_id => -605563374 irb(main):011:0> :foo.to_fring.object_id => -605563374 irb(main):012:0> :bar.to_fring.object_id => -605617824 irb(main):013:0> :bar.to_fring.object_id => -605617824 irb(main):014:0> :bar.to_fring.object_id => -605617824 Regards, Brian.
> I don''t like the idea of my code having to be *parsed* to add magic''parsed'' isn''t the right verb here. ParseTree isn''t opening up the file, reading in a string, and parsing it. It just traverses the internal node structure that Ruby has already built up. ParseTree tree does not have a method to simply return the parameters of a method (a constant time operation) - it traverses the structure of the entire method (linear in the size of the method - I guess). A custom extension to return the parameters would take a method object, and follow two node pointers before coming to a linked list of the parameter symbols (more or less - I think - I haven''t done it yet).> and I > wouldn''t be confident that it would work in all cases (e.g. what about if I > put controller actions in a module and mix them in? What if I define > controller actions dynamically at runtime, e.g. based on reflecting the > database?)All of these cases can be handled correctly. It''s not as complex as you''re thinking :) I will write the extension this week and then you can evaluate it. ry
On Mon, Sep 03, 2007 at 01:39:59PM +0200, ry dahl wrote:> > I don''t like the idea of my code having to be *parsed* to add magic > > ''parsed'' isn''t the right verb here. ParseTree isn''t opening up the > file, reading in a string, and parsing it. It just traverses the > internal node structure that Ruby has already built up.OK, I understand. I''d be happier if Ruby had named parameter passing as a _standard_ feature of the language. It''s been talked about for years :-) Since controller methods never take parameters normally, I guess that handling the case of controller(foo,bar) differently from controller() is fine. However I think the params hash should be kept exposed for those who want to use it. Regards, Brian.
Hi, On 2-Sep-07, at 10:49 AM, ry dahl wrote:> I would recommend keeping the params hash around for backwards > compatibility but with a depreciation warning.Another dissenting voice... I will not/cannot avoid the use of the params object in some of my applications. So, please, no deprecation. I don''t care if Merb supported controller parameters or not, in principle. I doubt I''d ever use them, I prefer to look at the params object as an input data thing that needs to be inspected rather carefully. On the other hand, Merb is still mostly light and easy to understand, and starts very quickly -- it would be sad to see this end. Cheers, Bob ---- Bob Hutchison -- tumblelog at http:// www.recursive.ca/so/ Recursive Design Inc. -- weblog at http://www.recursive.ca/ hutch http://www.recursive.ca/ -- works on http://www.raconteur.info/ cms-for-static-content/home/
Here is an extension which allows one to inspect the arguments of a method. To use it do this: require ''method_args'' m = my_object.method(:my_method) m.args http://s3.amazonaws.com/four.livejournal/20070904/method_args-0.0.1.zip http://s3.amazonaws.com/four.livejournal/20070904/method_args-0.0.1.gem So - now that we have a quick simple extension, what would people say about arguments to actions? ry
On Tue, Sep 04, 2007 at 11:54:38PM +0200, ry dahl wrote:> Here is an extension which allows one to inspect the arguments of a > method. To use it do this: > require ''method_args'' > m = my_object.method(:my_method) > m.args > > http://s3.amazonaws.com/four.livejournal/20070904/method_args-0.0.1.zip > http://s3.amazonaws.com/four.livejournal/20070904/method_args-0.0.1.gem > > So - now that we have a quick simple extension, what would people say > about arguments to actions?$ sudo gem install method_args-0.0.1.gem Password: ERROR: While executing gem ... (RuntimeError) Error instaling method_args-0.0.1.gem: method_args requires Ruby version >= 1.8.6 $ ruby -v ruby 1.8.4 (2005-12-24) [i486-linux] Most distros don''t have 1.8.6 included as standard yet (this machine is Ubuntu-6.06.1). So if method_args really needs 1.8.6, I think its audience will be limited for the time being. Regards, Brian.
Hi Brian, Luis, Sorry for the confusion - it actually doesn''t depend on 1.8.6, I just didn''t test it on others. Seems to work down to 1.8.4 and it is almost working for 1.9. It also would conceivably work for lower versions (one just needs to test it out). Luis, I don''t know anything about Visual C, but if Mongrel is compiling with it certainly this should. Look at the extconf.rb, there is nothing to it. I''ve updated a few things in the extension: lowered the required ruby version and added support for splat arguments. I won''t be posting here anymore about this extension (it''s getting its own RubyForge project) but please check out the revision: http://s3.amazonaws.com/four.livejournal/20070905/method_args-0.0.2.gem http://s3.amazonaws.com/four.livejournal/20070905/method_args-0.0.2.zip Try it out and then go sit outside in the cool grass, under the warm sun, and dream about how nice it would be to use arguments instead of params. We could even keep params around (at no extra speed cost and not depreciated) for those who enjoy typing. def show(id) @product = Product.find(id) render end The extension is a mere 160 lines of C code. It runs quickly and it seems to work rather well. Bob Hutchison wrote:> Another dissenting voice... I will not/cannot avoid the use of the > params object in some of my applications. So, please, no deprecation. > I don''t care if Merb supported controller parameters or not, in > principle. I doubt I''d ever use them, I prefer to look at the params > object as an input data thing that needs to be inspected rather > carefully. On the other hand, Merb is still mostly light and easy to > understand, and starts very quickly -- it would be sad to see this end.Bob, in what way are you using params? Why can''t you avoid it? I think you are not thinking about this correctly. ry
On Wed, Sep 05, 2007 at 04:13:20PM +0200, ry dahl wrote:> http://s3.amazonaws.com/four.livejournal/20070905/method_args-0.0.2.gem > http://s3.amazonaws.com/four.livejournal/20070905/method_args-0.0.2.zip > > Try it out and then go sit outside in the cool grass, under the warm > sun, and dream about how nice it would be to use arguments instead of > params. We could even keep params around (at no extra speed cost and > not depreciated) for those who enjoy typing. > > def show(id) > @product = Product.find(id) > render > end > > The extension is a mere 160 lines of C code. It runs quickly and it > seems to work rather well.Yes, this is very cool. I''ve just posted it to ruby-talk :-) A few comments/thoughts: (1) I don''t see why Method#args should raise an exception for a method which takes no arguments. Why not just return an empty array? #args? can remain but would be equivalent to #args.size > 0 (2) Would it be better to use symbols rather than strings? Ruby-1.9 now does this for method names, see http://eigenclass.org/hiki.rb?Changes+in+Ruby+1.9#l32 However in practice what we''re talking about is local_variables. Under 1.8 this returns an array of strings, and I see no suggestion that this will change. So on second thoughts, forget this. (3) Would it be worth reflecting whether each argument is optional individually, or should we just rely on existing Method#arity? irb(main):018:0> class X irb(main):019:1> def hello(foo, bar, baz=nil, *rest) irb(main):020:2> end irb(main):021:1> end => nil irb(main):022:0> meth = x.method(:hello) => #<Method: X#hello> irb(main):023:0> meth.args => ["foo", "bar", "baz", "*rest"] irb(main):024:0> meth.arity => -3 # a bit awkward to interpret It seems that Ruby-1.9 makes life much more complicated here (ugh): http://eigenclass.org/hiki.rb?Changes+in+Ruby+1.9#l15 (4) For efficiency, maybe it''s worth implementing the ''calling'' side of this within the C extension as well. That is, take a hash, flatten the elements and send them to the receiver in the correct order. A question arises as to what happens if the hash contains keys which are not matched by the receiver. One option is to pass a hash of the left-over elements in the splat receiver, e.g. def foo(id, page=nil, *rest) puts "id=#{id.inspect}" puts "page=#{page.inspect}" puts "rest=#{rest.inspect}" end method(:foo).callvar( :id=>123, :foo=>1, :bar=>2 ) # more convenient? sendvar( :foo, :id=>123, :foo=>1, :bar=>2 ) # Result: # id=123 # page=nil # rest={:foo=>1, :bar=>2} Without a splat receiver perhaps an exception should be raised: def bar(id, page=nil) puts "id=#{id.inspect}" puts "page=#{page.inspect}" end method(:bar).callvar( :id=>123, :foo=>1, :bar=>2 ) # raises ArgumentError, no argument called :foo This _might_ be useful to application developers (i.e. if a page posts a value but you forgot to declare it in the controller method args). On the other hand it might be annoying, e.g. because you''re not interested in the value of Submit buttons, hidden fields containing cookies etc. Regards, Brian.
Hi, On 5-Sep-07, at 10:13 AM, ry dahl wrote:> Bob Hutchison wrote: >> Another dissenting voice... I will not/cannot avoid the use of the >> params object in some of my applications. So, please, no deprecation. >> I don''t care if Merb supported controller parameters or not, in >> principle. I doubt I''d ever use them, I prefer to look at the params >> object as an input data thing that needs to be inspected rather >> carefully. On the other hand, Merb is still mostly light and easy to >> understand, and starts very quickly -- it would be sad to see this >> end. > > Bob, in what way are you using params? Why can''t you avoid it? I think > you are not thinking about this correctly.Well, I''ll give you an example. One of my applications is a course management system that administers and marks quizzes. The quiz is supplied as data to the program and the program generates the form. There is a single action in the controller that handles the test marking and updates the student''s ''transcript''. Cheers, Bob ---- Bob Hutchison -- tumblelog at http:// www.recursive.ca/so/ Recursive Design Inc. -- weblog at http://www.recursive.ca/ hutch http://www.recursive.ca/ -- works on http://www.raconteur.info/ cms-for-static-content/home/
> > Bob Hutchison wrote: > >> Another dissenting voice... I will not/cannot avoid the use of the > >> params object in some of my applications. So, please, no deprecation. > >> I don''t care if Merb supported controller parameters or not, in > >> principle. I doubt I''d ever use them, I prefer to look at the params > >> object as an input data thing that needs to be inspected rather > >> carefully. On the other hand, Merb is still mostly light and easy to > >> understand, and starts very quickly -- it would be sad to see this > >> end. > > > > Bob, in what way are you using params? Why can''t you avoid it? I think > > you are not thinking about this correctly. > > Well, I''ll give you an example. One of my applications is a course > management system that administers and marks quizzes. The quiz is > supplied as data to the program and the program generates the form. > There is a single action in the controller that handles the test > marking and updates the student''s ''transcript''.With action arguments one is still able to pass hash structures. For example, if you have an unknown number of quiz questions, then perhaps you would send quiz_questions[sex]=radio(male,female)&quiz_questions[age]=intenger_select(0..50) (I''m inventing some syntax for form creation here. :) Then the action would look like def quiz_create(quiz_questions) ... end The point is that you can pass hashes still in as arguments. Because of this, there isn''t anything you can''t do with params that you cannot do with action args. ry
On Sep 6, 2007, at 4:21 PM, ry dahl wrote:>>> Bob Hutchison wrote: >>>> Another dissenting voice... I will not/cannot avoid the use of the >>>> params object in some of my applications. So, please, no >>>> deprecation. >>>> I don''t care if Merb supported controller parameters or not, in >>>> principle. I doubt I''d ever use them, I prefer to look at the >>>> params >>>> object as an input data thing that needs to be inspected rather >>>> carefully. On the other hand, Merb is still mostly light and >>>> easy to >>>> understand, and starts very quickly -- it would be sad to see this >>>> end. >>> >>> Bob, in what way are you using params? Why can''t you avoid it? I >>> think >>> you are not thinking about this correctly. >> >> Well, I''ll give you an example. One of my applications is a course >> management system that administers and marks quizzes. The quiz is >> supplied as data to the program and the program generates the form. >> There is a single action in the controller that handles the test >> marking and updates the student''s ''transcript''. > > With action arguments one is still able to pass hash structures. For > example, if you have an unknown number of quiz questions, then perhaps > you would send > > quiz_questions[sex]=radio(male,female)&quiz_questions[age] > =intenger_select(0..50) > > (I''m inventing some syntax for form creation here. :) > > Then the action would look like > > def quiz_create(quiz_questions) > ... > end > > The point is that you can pass hashes still in as arguments. Because > of this, there isn''t anything you can''t do with params that you cannot > do with action args. > > ryPlus even if we did allow action args in, params would not go away and you could just not give your actions arguments and use the oparams hash just like normal. So this is an additive feature and does not change the way you use params at all. Cheers- -- Ezra Zygmuntowicz -- Founder & Ruby Hacker -- ez at engineyard.com -- Engine Yard, Serious Rails Hosting -- (866) 518-YARD (9273)
Hi, On 6-Sep-07, at 7:23 PM, Ezra Zygmuntowicz wrote:> > On Sep 6, 2007, at 4:21 PM, ry dahl wrote: > >>>> Bob Hutchison wrote: >>>>> Another dissenting voice... I will not/cannot avoid the use of the >>>>> params object in some of my applications. So, please, no >>>>> deprecation. >>>>> I don''t care if Merb supported controller parameters or not, in >>>>> principle. I doubt I''d ever use them, I prefer to look at the >>>>> params >>>>> object as an input data thing that needs to be inspected rather >>>>> carefully. On the other hand, Merb is still mostly light and >>>>> easy to >>>>> understand, and starts very quickly -- it would be sad to see this >>>>> end. >>>> >>>> Bob, in what way are you using params? Why can''t you avoid it? I >>>> think >>>> you are not thinking about this correctly. >>> >>> Well, I''ll give you an example. One of my applications is a course >>> management system that administers and marks quizzes. The quiz is >>> supplied as data to the program and the program generates the form. >>> There is a single action in the controller that handles the test >>> marking and updates the student''s ''transcript''. >> >> With action arguments one is still able to pass hash structures. For >> example, if you have an unknown number of quiz questions, then >> perhaps >> you would send >> >> quiz_questions[sex]=radio(male,female)&quiz_questions[age] >> =intenger_select(0..50) >> >> (I''m inventing some syntax for form creation here. :) >> >> Then the action would look like >> >> def quiz_create(quiz_questions) >> ... >> end >> >> The point is that you can pass hashes still in as arguments. Because >> of this, there isn''t anything you can''t do with params that you >> cannot >> do with action args. >> >> ry > > > Plus even if we did allow action args in, params would not go away > and you could just not give your actions arguments and use the > oparams hash just like normal. So this is an additive feature and > does not change the way you use params at all.That''s fine. I was objecting to the deprecation of params that was suggested. Cheers, Bob> > Cheers- > -- Ezra Zygmuntowicz-- Founder & Ruby Hacker > -- ez at engineyard.com > -- Engine Yard, Serious Rails Hosting > -- (866) 518-YARD (9273) > >---- Bob Hutchison -- tumblelog at http:// www.recursive.ca/so/ Recursive Design Inc. -- weblog at http://www.recursive.ca/ hutch http://www.recursive.ca/ -- works on http://www.raconteur.info/ cms-for-static-content/home/