Forum: Radiant CMS Facets branch extensibiliy extended

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Dc893f8ae12045dc71048a0c6a56fc01?d=identicon&s=25 Jacob Burkhart (igotimac)
on 2007-02-14 15:20
Hey Sean,

(and anybody else interested in facets)

I've further refactored facets, and refined my TinyMCE extension (whick
takes advantage of that refactoring).

Instead of:
    admin.page.edit_partials.add "preview/preview_button", :region =>
:buttons

I've made it:
    Radiant::EditorUI.editors.default.add "preview/preview_button",
:region => :buttons

My TinyMCE is added via:
    Radiant::EditorUI.editors.add(TinymceEditorUI.new)

Where TinymceEditorUI is a subclass of Radiant::EditorUI::DefaultEditor


I've zipped up the entire thing and made it available at:

http://jotapajaro.com/dump/facetsv2.zip


Please check it out, let me know what you think. Let me know if you
think I'm going in the right direction. Let me know if you have any
questions.

What's the best way to get in touch with the Radiant core team directly?
I'd like to discuss my ideas.

thanks,
Jacob
Dc893f8ae12045dc71048a0c6a56fc01?d=identicon&s=25 Jacob Burkhart (igotimac)
on 2007-02-14 15:29
> I've made it:
>     Radiant::EditorUI.editors.default.add "preview/preview_button",
> :region => :buttons
>
> My TinyMCE is added via:
>     Radiant::EditorUI.editors.add(TinymceEditorUI.new)


And now that I've got that working.  (You page preview extension works
properly)  I could probably change it to:

admin.editors.default.add "preview/preview_button",  :region => :buttons

and:

admin.editors.add(TinymceEditorUI.new)


I just had to make it a seperate class because I was getting confused
with PageAdmin being defined inside of AdminUI.  I've defined a seperate
file editor_ui.rb that sort of copies what admin_ui.rb does for admin
tabs to enable the user-selection of page editor.


I was also thinking I might make something like this work:

admin.editors.for_all_editors{ |editor|  editor.add
"preview/preview_button",  :region => :buttons }

Where we use a block so we can save the block until all extensions have
loaded and added whatever editors are going to be added.  And then once
it's all loaded we can execute all the blocks that were passed via
"for_all_editors".

With some exception catching. (In the above example if an editor has
already had it's :buttons region removed we can't add
"preview/preview_button" and we should just fail silenty, unless perhaps
there are no editors that this block executes successfully for)
8802b1fa1b53e2197beea9454244f847?d=identicon&s=25 Sean Cribbs (Guest)
on 2007-02-15 04:23
(Received via mailing list)
As I said, it's a basic start, and definitely not as stable as mental.
Could you provide me a diff of the changes to the core of 'facets'?
(pastie or private attachment preferable).  I'd like to review them and
work them into facets.

Sean
Dc893f8ae12045dc71048a0c6a56fc01?d=identicon&s=25 Jacob Burkhart (igotimac)
on 2007-02-18 21:40
Hey Sean,

Here you go... : )

http://pastie.caboo.se/41244

(also at: http://jotapajaro.com/dump/facets.diff)

I implemented the "for_all_editors" I was talking about aboce...

Here's the example of usage from page preview extension;

+    Radiant::ExtensionLoader::do_after_activate_extensions do
+      Radiant::PageEditorUI.each_editor{ |editor| editor.add
"preview/preview_button", :region => :buttons }
+    end


Let me know if you have any questions,
I'm eager to see the changes I'm now relying on "officialy supported"

Jacob


------

And for anybody else who's interested the latest version of my changes
along with TinyMCE and FCKEditor extensions is available at
http://jotapajaro.com/dump/facetsv4.zip
Dc893f8ae12045dc71048a0c6a56fc01?d=identicon&s=25 Jacob Burkhart (igotimac)
on 2007-02-22 05:06
Another dump of my "current" radiant setup is available for those who
are curious

http://jotapajaro.com/dump/facetsv5.zip


Waiting on Sean to react to my first round of facets changes before I
dump any more changes on him...


I welcome all critiques of my code.
1c1e3bdfe006a22214102fcd6434a012?d=identicon&s=25 Daniel Sheppard (Guest)
on 2007-02-22 05:58
(Received via mailing list)
I finally got the chance to have a quick look at your changes.

I've only looked at the code, not run it, but in summary it looks like
what you want is to have a variety of different interfaces with which to
edit a page - potentially you'd want to look at the same page using two
different editors? Is that an accurate description?

The reason for you doing this is so that you can use fck or tinymce to
edit page parts. I think that a much better mechanism for doing so would
be to implement an fck/tinymce filter for the page and then insert a
partial directly after the edit_page_parts partial that inserts
javascript to listen for changes to the filter on the part and adjusts
the textarea accordingly.

Even better I would think would be to have an extension that completely
replaces the edit_page_parts partial with one that implements fck or
tinymce - I don't really see a reason why you'd want to switch between
fck / tinymce / textile / markdown at runtime.

I find the interface for editing partials that's currently in facets is
much cleaner and easier to use than your implementation (though I am
biased because I helped with the design) - the integration of editors is
a very specific usecase, and while your interface makes that specific
task more straightforward, I think it complicates the simple usecases
unneccesarily.

Dan.
Dc893f8ae12045dc71048a0c6a56fc01?d=identicon&s=25 Jacob Burkhart (igotimac)
on 2007-02-22 15:29
How have I specifically hurt the simple use cases?  Is there some
compromise we could make that would still give me a hook to have
multiple editors?

My code may be a little less elegant, but I don't think it's obtrusive.


The editor you didn't see in my original submissions (but is in v5) is
the "content" editor.  This is an editor with some features cut out
which is specifically setup for a "content" person to use.  It's only
supposed to show the partials that use can edit, and it hides things
like layout and page type.  You can look at this editor in my v5
attachment.

I tried your suggested approach of having fck or tinyMCE load directly
into the current page structure.  The problem with this is that it's too
slow to use in practice.   Both WYSIWYG editors take significant time
and bandwidth to load, and reloading them each time you tab between page
parts was unacceptably slow.  Additionally, I couldn't get tinyMCE to
work in Safari within the TabControl currently being used.  It has to be
done the way I did it.  (One WYSIWYG loads and the contents of the parts
are swapped in and out of it by the tabs)

The other reason for making facets support multiple editors is for
compatability.  If there starts to be multiple extensions that alter the
page editor they can start to conflict.  The easiest way to avoid
conflict is for each to define it's own editor.  I think it makes
writting extension a little more elegant too because you define all of
your page editor modification in your class which subclasses
DefaultEditor instead of having to define these changes in "activate"

Looking to the future, imagine very specific page types. A "calendar"
page type for instance.  You don't want to edit the calendar page with
the current editor, you want to edit it with a customized editor from
the calendar extension.  And you don't want all your page editors to be
calendar page editors.  And your calendar editor should still re-use
components from the standard page editor, and still post to the
page_controller.  This is the more "long term vision" problem I am
attempting to solve.

I'd like to further extend my work so that handle_new_or_edit_post in
PageController makes a call to some method of the editor_ui as a hook
for doing saving or whatever on whatever your editor has added to the
page. (In my case it's page_attributes, and currently I'm just
overriding handle_new_or_edit_post)

In my latest version of facets, it's possible to set
flash[:content_editor_ui]. If it is set, then it will use the editor
specified just for the current page edit.  (And revert back to whatever
editor you have saved in your session for other pages)

I realize that:
   Radiant::PageEditorUI.editors.default
isn't as elegant as:
   admin.page.edit_partials

I had envisioned doing something like:
   admin.page_editors.default
This would be more consistend with the currently accepted admin.tabs.
method of adding tabs, But my ability to understand and debug
dependencies loading failed me.

What else are you objecting to?

Please suggest how I can improve my code to support multiple editors
without complicating the simple usecases.


On a side note,
I've found Radiant::ExtensionLoader::do_after_activate_extensions do end
to be usefull for more than just setting up multiple page editors.  I've
found that getting dependencies to load in the proper order can be very
tricky, and this provides another hook for fiddling with the loading
order of things.  (In my case, I had to load my extensions to
PageController in this block or I would get loading problems)
1c1e3bdfe006a22214102fcd6434a012?d=identicon&s=25 Daniel Sheppard (Guest)
on 2007-02-23 00:35
(Received via mailing list)
> How have I specifically hurt the simple use cases?  Is there some
> compromise we could make that would still give me a hook to have
> multiple editors?
>
> My code may be a little less elegant, but I don't think it's
> obtrusive.

I think it's mainly because I can't see the thought processes behind
most of what you've done. Hopefully I'll get some time this weekend to
sit down and try and replicate your integration of the wysiwyg editors
and see if I can find the same problems with the current facets code.

I'm in total agreement on needing to have different interfaces for
different page types - but I would see the flow of page creation being:

New Page --> Select Page Type --> Display specific editor

Rather than have a selection of editors available directly on a page.

I've currently worked around this in my 'groggy' extension by overriding
the new method to change the page type on creation if it's a child of a
certain page and then wrapping my partials in if statements. It's
workable, but not extensable or easy.

> I'd like to further extend my work so that handle_new_or_edit_post in
> PageController makes a call to some method of the editor_ui as a hook
> for doing saving or whatever on whatever your editor has added to the
> page. (In my case it's page_attributes, and currently I'm just
> overriding handle_new_or_edit_post)

I originally saw this as a need when I first started working on my
admin_page_parts extension, but then realised that I could do everything
that I wanted with adding extra methods to the page to accept the new
attributes (by getting them through page.attributes = params[:page]),
and dumped all the code for it because my extensions never found a
usecase for it and it complicated things unnecessarily. Do you have an
example of where you've found it useful?

Dan.
8802b1fa1b53e2197beea9454244f847?d=identicon&s=25 Sean Cribbs (Guest)
on 2007-02-23 00:39
(Received via mailing list)
Daniel et al,

Let me know if you want to look at working on facets this weekend.  I
would like to complete it and prep it for merging with mental, pending
core team review, of course.

Sean
7f85ce9d3a9ef1e91534fa9e911fccb1?d=identicon&s=25 Adam Salter (Guest)
on 2007-02-23 01:54
(Received via mailing list)
I know this is a little late (email from last month)... but in regard
to caching, isn't the major problem with implementing sessions in
Radiant that the headers are cached as well? This seems to be over
optimisation... Just cache the page text and let the headers be
generated. Surely there isn't that large a hit in performance, and
the advantage of using individual user sessions is great. Or make it
an option at least, since most user ACL type systems require sessions...
Dc893f8ae12045dc71048a0c6a56fc01?d=identicon&s=25 Jacob Burkhart (igotimac)
on 2007-02-23 01:59
My use case for needing more than just a hook on page.attributes= is for
when page has_many

My extension adds:
      has_many :page_attributes, :class_name => 'PageAttribute',
:dependent => :destroy

I need to capture each page_attribute that was added or deleted, similar
to the way page parts are managed. (But as I said, I've just overriden
handle_new_or_edit_post for now..)


Also, I think I can understand not wanting to add
_edit_select_editor.rhtml to the core.  As long as you maintain the
usage of page_helper's:

  def editor_ui
    if(flash[:page_editor_ui])
      to_return = Radiant::PageEditorUI.editors[flash[:page_editor_ui]]
    end
    unless to_return and to_return != nil
      to_return =
Radiant::PageEditorUI.editors[session[:page_editor_ui]]
    end
    if to_return.nil?
      Radiant::PageEditorUI.editors.default
    else
      to_return
    end
  end


I can always make _edit_select_editor a part of my extension and add to
every editor during extension loading.

And most extensions can set flash[:page_editor_ui] for "simple" usecase.
1c1e3bdfe006a22214102fcd6434a012?d=identicon&s=25 Daniel Sheppard (Guest)
on 2007-02-23 02:19
(Received via mailing list)
> to the way page parts are managed. (But as I said, I've just
> overriden
> handle_new_or_edit_post for now..)

Now I remember. I had the same problem with attachments - though in that
case when I changed around my interface to be more like sean's it was no
longer a problem (removal and creation were done with an ajax calls) -
this has the problem that removals from the list take affect before the
user hits 'save', but there's probably a decent workaround for that.

perhaps:

  before_save :remove_page_attributes

  def removed_page_attributes_id=(ids)
    @removed_attributes = ids
  end

  private
    def remove_page_attributes
      page_attributes = page_attributes.select {|x|
!@removed_attributes.include?(x.id) } if @removed_attributes
    end

And have javascript in your view so that a hidden
page[removed_attribute] input is added whenever an attribute is removed.

Not tested, but seems plausable.

Dan.
1c1e3bdfe006a22214102fcd6434a012?d=identicon&s=25 Daniel Sheppard (Guest)
on 2007-02-23 03:54
(Received via mailing list)
> I know this is a little late (email from last month)... but
> in regard
> to caching, isn't the major problem with implementing sessions in
> Radiant that the headers are cached as well? This seems to be over
> optimisation... Just cache the page text and let the headers be
> generated. Surely there isn't that large a hit in performance, and
> the advantage of using individual user sessions is great. Or make it
> an option at least, since most user ACL type systems require
> sessions...

To serve a page currently, the following steps are performed:

a) check for the existance of /cache/<url>.yml
b) check for the validity of /cache/<url>.yml
  if file exists and is valid:
    c) send /cache/<url>.data

  else
    d) Call Page.find_by_url to find the page
    e) call the page.headers method to set the page headers
    f) call the page.render method to render the page
content


A quick experiment to see the performance impact of making a
Page.find_by_url call on every request - using my current database
containing a few hundred pages, I'll pick a random deep page.

With the current caching mechanism, running:

ab2 -n 1000 -c 2
'http://localhost/articles/2006/04/13/2006-melbourn...
y-festival-reviews/levelland/'

I ran it first using the current radiant caching mechanism, and then
again modifying the site_controller to always do a Page.find_by_url
regardless of whether the page is cached or not.

Original cache : 160 requests / second
Modified cache :   4 requests / second

So, "Surely there isn't that large a hit in performance".... unless two
orders of magnitude doesn't constitute a large hit for you, I hope you
see why the cache behaves as it does.


Dan.
Dc893f8ae12045dc71048a0c6a56fc01?d=identicon&s=25 Jacob Burkhart (igotimac)
on 2007-02-23 20:14
If you guys would like to keep up with my "usecase" for the facets
changes I proposed, you can now take a look at:

http://dev.eyebeam.org/projects/radiant-partatts/browse


Thank you to Jaime for setting this up.

Hopefully this will eventually morph into a the repository for Just the
partatts extension.  (And supplemental TinyMCE and FCKEditor extensions)

Currently, it maintains a full version of radiant (modified facets) as
well.


I am more interested in making the Radiant a powerful platform, than I
am in simply getting my changes checked in to core.  If you guys can
come up with a better API for supporting multiple page editors, I'll be
happy to port my extension over to use it.

Using my API as a base, and improving it. Is also a possibility I
encourage.


Also... perhaps we should come up with a convention for extension
including static files.  It's no big deal to have to copy the fckeditor
javacripts into public to get the extension to work, but perhaps there
should be an official standard.

public/extensions/<extension-name>/etc...

for example.


Jacob
Ff2c500b4f2690c6e60d580f6b3caf78?d=identicon&s=25 David Minor (Guest)
on 2007-02-23 20:32
(Received via mailing list)
On Feb 23, 2007, at 1:14 PM, Jacob Burkhart wrote:

> If you guys would like to keep up with my "usecase" for the facets
> changes I proposed, you can now take a look at:
>
> http://dev.eyebeam.org/projects/radiant-partatts/browse
>
>
> Thank you to Jaime for setting this up.
>

Jacob,

Is there a public URL to check that out?

I found this link referenced for svn https://dev.eyebeam.org/svn/
radiant-partatts but it requires svn user to authenticate.

dm
Aeaf22d9d8ef478d320be90158bcd39e?d=identicon&s=25 Jamie M. Wilkinson (Guest)
on 2007-02-25 20:03
(Received via mailing list)
> Jacob,
>
> Is there a public URL to check that out?
>
> I found this link referenced for svn https://dev.eyebeam.org/svn/
> radiant-partatts but it requires svn user to authenticate.


Apologies, I forgot to update the wiki to note that you should use
user/pass = tester/tester to checkout "anonymously." We use LDAP to
authenticate and it's unhappy with genuinely anonymous users.

<http://dev.eyebeam.org/projects/radiant-partatts/w...

@John-- should we move this branch-branch to radiantcms.org? I set
this up largely because it only takes 15 seconds

-jamie
543d7bc82d71765d0a7d70ac71fa7b53?d=identicon&s=25 Brian Capouch (Guest)
on 2007-02-25 20:21
(Received via mailing list)
Jamie M. Wilkinson wrote:
> user/pass = tester/tester to checkout "anonymously." We use LDAP to
> authenticate and it's unhappy with genuinely anonymous users.
>

I tried tester/tester for the user/pass, and got a 403 forbidden.

Worse, even after hitting the browser (Mozilla, recent) refresh button
several times, it doesn't offer me a login screen to use for trying
again.

??

Thx.

B.

--
This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.
Ff2c500b4f2690c6e60d580f6b3caf78?d=identicon&s=25 David Minor (Guest)
on 2007-02-25 20:30
(Received via mailing list)
On Feb 25, 2007, at 1:20 PM, Brian Capouch wrote:
>
Brian,

the user/pass is for an svn checkout from:
https://dev.eyebeam.org/svn/radiant-partatts

and I just did a co with the user/pass that worked fine.

dm
543d7bc82d71765d0a7d70ac71fa7b53?d=identicon&s=25 Brian Capouch (Guest)
on 2007-02-25 20:34
(Received via mailing list)
David Minor wrote:

>
>
> Brian,
>
> the user/pass is for an svn checkout from:
> https://dev.eyebeam.org/svn/radiant-partatts
>
> and I just did a co with the user/pass that worked fine.
>

<Blushing>

I mis-read his mail, and thought it was a Wiki.

Sorry for the noise.  I'll go back in my hole.

B.

--
This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.
7f85ce9d3a9ef1e91534fa9e911fccb1?d=identicon&s=25 Adam Salter (Guest)
on 2007-02-26 03:05
(Received via mailing list)
On 23/02/2007, at 1:51 PM, Daniel Sheppard wrote:

> a) check for the existance of /cache/<url>.yml
> b) check for the validity of /cache/<url>.yml
>   if file exists and is valid:
>     c) send /cache/<url>.data
>
>   else
>     d) Call Page.find_by_url to find the page
>     e) call the page.headers method to set the page headers
>     f) call the page.render method to render the page
> content
>

Daniel,
What I was suggesting wasn't that Page.find_by_url be called on every
page request.... The original email was about changes to the caching
mechanism...
My suggestion, working from your outline:
a) check for the existance of /cache/<url>.yml
b) check for the validity of /cache/<url>.yml
  if file exists and is valid:
    c) call the page.headers method to set the page headers
    d) send /cache/<url>.data

  else
    e) Call Page.find_by_url to find the page
    f) call the page.headers method to set the page headers
    g) call the page.render method to render the page content

I was saying that the headers could be sent on every request. This
allows ACLs to work for the main site pages... at the moment (as I
understand it) the headers - so this includes session info - are
cached and only update once per 5 minutes... This is unworkable if
you want conditional content -
  ie if user registered
  show registered_user_page
else
  show login_page

I certainly wasn't saying that page caching wasn't needed, and can
even see how powerful the radiant caching is since it essentially
turns the site into static content, once cached. But caching headers
doesn't seem workable in the long-term - or will need to be at least
an option in the caching mechanism in order to implement more dynamic
behaviour. Of course this then opens up the site to all kinds of
dynamic content and caching by page url would not work... since two
users could potentially have different pages with the same url... but
it at least allows session data to be used on a page by page basis...
Perhaps caching page parts would work?

Anyway this is all stuff that will have to be worked out if blogging
is going to be possible with Radiant...

Cheers,
Adam
1c1e3bdfe006a22214102fcd6434a012?d=identicon&s=25 Daniel Sheppard (Guest)
on 2007-02-26 04:00
(Received via mailing list)
What I was suggesting wasn't that Page.find_by_url be called on
every page request.... The original email was about changes to the
caching mechanism...
  My suggestion, working from your outline:
  a) check for the existance of /cache/<url>.yml
  b) check for the validity of /cache/<url>.yml
  if file exists and is valid:
  c) call the page.headers method to set the page headers
  d) send /cache/<url>.data


  else
  e) Call Page.find_by_url to find the page
  f) call the page.headers method to set the page headers
  g) call the page.render method to render the page content


There's a flaw in your logic - You can't call page.headers until after
you've called Page.find_by_url.

Dan.
7f85ce9d3a9ef1e91534fa9e911fccb1?d=identicon&s=25 Adam Salter (Guest)
on 2007-02-26 04:23
(Received via mailing list)
OK. Point taken. I was really just putting my two cents in on a
subject that's important to me personally... ie user variable content
and ACLs.

It would be nice to do something like (I haven't actually looked at
the code, my bad):
page = Page.new
page.headers
page.content = Cache.get_content('/cache/'+cache_file)
page.render

Anyway I'd better have a look at the code myself before I make a/more
of a fool of myself.

Cheers,
9d170533016cbe367f86a6d99437e3cf?d=identicon&s=25 Chris Parrish (Guest)
on 2007-02-26 05:31
I too have a need to implement a system that prevents displaying pages
unless the user is authenticated.  I will need levels of authentication
and have more than just a handful of users.

Smells like sessions to me but do I understand correctly that radiant's
caching prevents this?

I'm not even smart enough to know what would be required to make a user
authentication system play nicely with radiant.  Thoughts/suggestions?

-Chris
1c1e3bdfe006a22214102fcd6434a012?d=identicon&s=25 Daniel Sheppard (Guest)
on 2007-02-26 05:38
(Received via mailing list)
OK. Point taken. I was really just putting my two cents in on a
subject that's important to me personally... ie user variable content
and ACLs.

  It would be nice to do something like (I haven't actually looked
at the code, my bad):
  page = Page.new
  page.headers
  page.content = Cache.get_content('/cache/'+cache_file)
  page.render


  Anyway I'd better have a look at the code myself before I make
a/more of a fool of myself.


I wasn't trying to make a fool out of you - I completely understand what
you're trying to achieve, but asking the pages to handle authentication
isn't the way to go about it unless you're prepared to totally kill the
caching performance.

The way to implement this would probably be to introduce a filter to the
site controller that does ACL checks based on paths - check the ACL for
the path before doing anything else that site_controller does. Introduce
a new LoginPage type that is not cached that is responsible for setting
the authentication cookies. Rails doesn't give you as much control over
session creation as I'm used to in java servlets, so you'll have to take
over session control in your own code - You need to have your filter
check for the existance of a session, but not create one if it doesn't
exist.

Hmmmm... does rails give you access to the session cookie before it gets
sent off in the response? Perhaps the site_controller could be changed
to clear out that cookie if the request is going to be cached - giving a
warning / raising an exception if the session is not empty. You'd still
need a seperate layer of access control, that slots in before the cache
handler, but if you could use rails sessions instead of rolling your own
that would be useful. I'll have a little play.

Dan.
1c1e3bdfe006a22214102fcd6434a012?d=identicon&s=25 Daniel Sheppard (Guest)
on 2007-02-26 06:19
(Received via mailing list)
> Hmmmm... does rails give you access to the session cookie before it
> gets sent off in the response? Perhaps the site_controller could be
> changed to clear out that cookie if the request is going to be cached
-
> giving a warning / raising an exception if the session is not empty.
> You'd still need a seperate layer of access control, that slots in
> before the cache handler, but if you could use rails sessions instead
> of rolling your own that would be useful. I'll have a little play.

Phew. Just had a look at how rails does sessions. Not very pretty -
session handling is actually done by CGI::Session.

It would probably be possible to get rid of session :off and get the
same behaviour with:

    def show_uncached_page(url)
      @page = find_page(url)
      unless @page.nil?
        @page.process(request, response)
    if live? and @page.cache?
          @cache.cache_response(url, response)
        else
          response.instance_eval { @cgi.instance_eval {
@output_cookies.clear }}
        end
        @performed_render = true
      else
        render :template => 'site/not_found', :status => 404
      end
    rescue Page::MissingRootPageError
      redirect_to welcome_url
    end


But that's really messy. Don't like it one bit.

I'd suggest instead:

class ProtectedSiteController < SiteController
  def show_page
    url = params[:url] = "/protected/#{params[:url]}"
    if is_allowed(url)
      super
    else
      # do something else
    end
  end

  private
    def is_allowed(url)
      #test something
    end
  end
end

And in your extension:

  define_routes do |map|
    protected.connect '/protected/*url', :action => 'show_page',
:controller => 'protected'
  end


Give it a go.
1c1e3bdfe006a22214102fcd6434a012?d=identicon&s=25 Daniel Sheppard (Guest)
on 2007-02-26 07:03
(Received via mailing list)
Maybe I need to dump my assumptions for a moment. Knowing the page that
we're about to be rendering from the cache would be a useful thing. Why
can't we do it? Because the performance of Page.find_by_url sucks.

I talked a little bit about that suckage a while ago, and somebody
(Adam? Sean?) suggested having a table to directly find lookup a page
from it's url from the database. I was originally dismissive, but the
idea is starting to grow on me.

- Create a page_urls table
- Whenever the slug or type of a page changes, that page and all of its
children (recursively) would update the page_urls table with their
current url(s).

If a page isn't found using a direct lookup, a regular Page.find_by_url
call would be made, so that we can still maintain all the flexibility
that provides.

Advantages of this system are:

- faster to lookup pages by url (though I don't know if it will be fast
enough that I'd want it before the cache check)

- all children of a page could be discovered recursively through:
  PageUrl.find(:all, :include => :page, :conditions => 'url like ?',
"#{parent_url}%")

- old urls could be left in the table - automatically giving 'cool urls'
- unless another page comes to replace it or the page is no longer
published, a page is always available through it's old address. Old urls
would probably get a marker and redirect to the real urls of a page.


Disadvantages:

- Database isn't third normal form (the url is a calculated field, not
raw data), makes my inner database purist feel queasy.

- Long save times when slug/type changes



I should probably do some other things instead, but I might have a look
at this.



Dan.
8802b1fa1b53e2197beea9454244f847?d=identicon&s=25 Sean Cribbs (Guest)
on 2007-02-26 19:00
(Received via mailing list)
Right.  Caching the complete url in the database would help, but would
not work in all cases, i.e. virtual pages that represent multiple urls.
Perhaps we should try this and get some metrics?

Sean
1c1e3bdfe006a22214102fcd6434a012?d=identicon&s=25 Daniel Sheppard (Guest)
on 2007-02-26 23:45
(Received via mailing list)
> Right.  Caching the complete url in the database would help,
> but would
> not work in all cases, i.e. virtual pages that represent
> multiple urls.
> Perhaps we should try this and get some metrics?

I was thinking that there would be a Page#calculate_urls method that
would by default just return the result of Page#url but could be
overridden to return multiple urls (in the case where a page knows all
its urls) - otherwise there's the fallback to doing the tree search.

I just did one quick metric - on my system, with ~900 pages, doing an
update of the url cache for all pages 50 times took ~19 seconds - that's
~.4ms per page. Scaling up, that's 4 seconds if you modify a page with
10,000 children... I think that would be a reasonable response time...
so the disadvantage at that end seems reasonable - just need to find out
if the advantages are worth it.

Dan.
This topic is locked and can not be replied to.