RE: [Catalyst] Dispatching based on path and host/domain
Write an Action Class. You can put whatever you want in the match() method. In your case, return 0 if grep { $c-req-host =~ /$_/ } @{$self-attributes-{Domain}||[]} I gave this a go (in principle it looks ideal), but the documentation on Catalyst::Action is pretty sparse and only talks about replacing the execute method. I'm assuming that if ActionClass-match() returns false the dispatcher assumes the method doesn't match, I gave that a quick test: package Catalyst::Action::Domain; use strict; use warnings; use base 'Catalyst::Action'; sub match { my $self = shift; my ($c) = @_; return 0; }; package MyAPP::Controller::Admin::Website1::Abstract sub index :Local { } sub edit :Local :ActionClass('Domain') { } http://mydomain.com/admin/website1/abstract/edit bounced me right back to the default controller, I was kind of expecting it to behave like NEXT in that it would fail to match http://mydomain.com/admin/website1/abstract/edit but would then match http://mydomain.com/admin/website1/abstract setting the first arg to 'edit'. Ah this may be specific to index as a not-really action it doesn't accept parameters the way I thought it did E.G. http://mydomain.com/admin/website1/abstract/iamnotamethod Does not dispatch to MyAPP::Controller::Admin::Website1::Abstract-index with ARGS being ('iamnotamethod') I think I answered my own question, but there's no harm in having the result in the archives no? (especially if I'm wrong) (Also, Did someone say that index was a hack? And that we should use base instead?) Dumping out the Action Object I can see: 'attributes' = { 'ActionClass' = [ 'Catalyst::Action::Domain' ], 'Path' = [ 'admin/website1/abstract/edit' ] } But I can't seem to find anywhere that this structure is set up, given the code in your Action example how would you go about setting the 'Domain' key in the attributes class from the Controller the Action is used in, apologies if this is a question with an obvious answer. Finally isn't $c-req-host the hostname of the connecting client? I ended up mangling $c-req-base at the moment though I'm not sure that's the best way to go. Really finally, has anyone thought of putting together a flowchart of the Classes/methods involved in a Catalyst request response if it's been done I'd love to look at it and if not if might be a good exercise for me. Thanks again for the really sterling help/suggestions. ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Dispatching based on path and host/domain
On Wed, Apr 23, 2008 at 12:22:36PM +0100, Curtis Fletcher wrote: Write an Action Class. You can put whatever you want in the match() method. In your case, return 0 if grep { $c-req-host =~ /$_/ } @{$self-attributes-{Domain}||[]} I gave this a go (in principle it looks ideal), but the documentation on Catalyst::Action is pretty sparse and only talks about replacing the execute method. I'm assuming that if ActionClass-match() returns false the dispatcher assumes the method doesn't match, I gave that a quick test: package Catalyst::Action::Domain; use strict; use warnings; use base 'Catalyst::Action'; sub match { my $self = shift; my ($c) = @_; return 0; }; package MyAPP::Controller::Admin::Website1::Abstract sub index :Local { } sub edit :Local :ActionClass('Domain') { } http://mydomain.com/admin/website1/abstract/edit bounced me right back to the default controller, I was kind of expecting it to behave like NEXT in that it would fail to match http://mydomain.com/admin/website1/abstract/edit but would then match http://mydomain.com/admin/website1/abstract setting the first arg to 'edit'. Ah this may be specific to index as a not-really action it doesn't accept parameters the way I thought it did E.G. http://mydomain.com/admin/website1/abstract/iamnotamethod Does not dispatch to MyAPP::Controller::Admin::Website1::Abstract-index with ARGS being ('iamnotamethod') I think I answered my own question, but there's no harm in having the result in the archives no? (especially if I'm wrong) (Also, Did someone say that index was a hack? And that we should use base instead?) index is basically a degenerate form of :Path :Args(0) If you'd wanted abstract/edit to match, you want :Path :Args(1) or no :Args restriction. Dumping out the Action Object I can see: 'attributes' = { 'ActionClass' = [ 'Catalyst::Action::Domain' ], 'Path' = [ 'admin/website1/abstract/edit' ] } But I can't seem to find anywhere that this structure is set up, given the code in your Action example how would you go about setting the 'Domain' key in the attributes class from the Controller the Action is used in, apologies if this is a question with an obvious answer. :Local is a shortcut for :Path($controller-path_prefix.'/'.$method_name) Those values came straight off the attributes - you'd set the Domain key just by using :Domain('foobar.com') exactly as you did in your original example (which is where I got the key name from :) Finally isn't $c-req-host the hostname of the connecting client? I ended up mangling $c-req-base at the moment though I'm not sure that's the best way to go. I meant $c-req-uri-host, sorry. Really finally, has anyone thought of putting together a flowchart of the Classes/methods involved in a Catalyst request response if it's been done I'd love to look at it and if not if might be a good exercise for me. http://dev.catalyst.perl.org/wiki/FlowChart shows the action dispatching order. Another one that maps out the relationships of the classes would rock; feel free to barrage me with questions (you get a free pass for stupid questions if you're writing docs or equivalent material :) -- Matt S Trout Need help with your Catalyst or DBIx::Class project? Technical Directorhttp://www.shadowcat.co.uk/catalyst/ Shadowcat Systems Ltd. Want a managed development or deployment platform? http://chainsawblues.vox.com/http://www.shadowcat.co.uk/servers/ ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Dispatching based on path and host/domain
On Wed, Apr 23, 2008 at 03:25:47PM +0100, Curtis Fletcher wrote: -Original Message- From: Matt S Trout [mailto:[EMAIL PROTECTED] Sent: 23 April 2008 14:34 To: The elegant MVC web framework Subject: Re: [Catalyst] Dispatching based on path and host/domain :Local is a shortcut for :Path($controller-path_prefix.'/'.$method_name) Those values came straight off the attributes - you'd set the Domain key just by using :Domain('foobar.com') exactly as you did in your original example (which is where I got the key name from :) And the light comes on because someone is finally home! I was thinking that :Local :Path etc were shortcuts to defining an ActionClass not attributes to the (mostly) default ActionClass. Bingo it all makes sense now. Many thanks. Right. The ActionClass affects how the action itself gets to make its choices. Things like :Path and :Chained indicate that whatever aciton object is constructed should be registered with a particular dispatch type. We just happen to only have one attribute namespace because that's how many perl has :) Digging around, is it a sane thing to have: __PACKAGE__-_action_class('Catalyst::Action::MyAction'); At the top of a controller if I want all of the methods to use the same non-default ActionClass? I'm nervous about using anything that starts with _ It starts with _ because you should never call it from -outside- the class. You're fine calling it on your own class. Doc patch to make this clear very welcome. On a related note: While I was looking for information about setting a default ActionClass I came across the ActionClass info in http://search.cpan.org/~mstrout/Catalyst-Manual-5.701004/lib/Catalyst/Ma nual/ExtendingCatalyst.pod I wish I'd found that at the start, maybe I'll put together a patch for the Catalyst::Action and Catalyst::Manual::Actions pod that points people back there for info about using match (does that sound like a good thing to do?) Yes please! -- Matt S Trout Need help with your Catalyst or DBIx::Class project? Technical Directorhttp://www.shadowcat.co.uk/catalyst/ Shadowcat Systems Ltd. Want a managed development or deployment platform? http://chainsawblues.vox.com/http://www.shadowcat.co.uk/servers/ ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
RE: [Catalyst] Dispatching based on path and host/domain
-Original Message- From: Matt Pitts [mailto:[EMAIL PROTECTED] Sent: 22 April 2008 03:06 To: The elegant MVC web framework Subject: RE: [Catalyst] Dispatching based on path and host/domain You've probably heard this before on the list, but... Ideally, you shouldn't have enough code in your Controllers to justify sharing the app across domains that need different functionality. The meat of the app should be in the Models, then you can just run multiple Cat apps - one with Cart controllers and one without - that use the same shared Models. Absolutely right, my controllers are much, much too heavy. This all came from learning as I went and I distinctly remember the point at which I gave up trying to put business logic in the model. At the time there seemed to be minimal if any examples that illustrated the model being anything other than an adaptor for DBIx::Class::Schema so I just figured I was mistaken in my attempt to do so. So could I ask, now I know a little more than I did then, Does everyone here subclass DBIx::Class::Resultset (a-la http://catalyst.perl.org/calendar/2007/16) for their business logic specific methods? (Well those that use DBIx::Class as their model anyway) Thanks for the Help Matt, it's certainly made me think. ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Dispatching based on path and host/domain
On Tue, Apr 22, 2008 at 10:22:55AM +0100, Curtis Fletcher wrote: -Original Message- From: Matt Pitts [mailto:[EMAIL PROTECTED] Sent: 22 April 2008 03:06 To: The elegant MVC web framework Subject: RE: [Catalyst] Dispatching based on path and host/domain You've probably heard this before on the list, but... Ideally, you shouldn't have enough code in your Controllers to justify sharing the app across domains that need different functionality. The meat of the app should be in the Models, then you can just run multiple Cat apps - one with Cart controllers and one without - that use the same shared Models. Disagree. Just because you want to minimise code in the controller doesn't mean you don't want to consider this to be the 'same app'. You're making a valid design point, but then jumping from there to an invalid one by ... well, handwaving so far as I can see. Absolutely right, my controllers are much, much too heavy. This all came from learning as I went and I distinctly remember the point at which I gave up trying to put business logic in the model. At the time there seemed to be minimal if any examples that illustrated the model being anything other than an adaptor for DBIx::Class::Schema so I just figured I was mistaken in my attempt to do so. So could I ask, now I know a little more than I did then, Does everyone here subclass DBIx::Class::Resultset (a-la http://catalyst.perl.org/calendar/2007/16) for their business logic specific methods? (Well those that use DBIx::Class as their model anyway) No, generally they don't. That's why they end up with controllers full of crap. Anybody trying to write -actual- MVC code with Catalyst+DBIC will have resultset classes though :) -- Matt S Trout Need help with your Catalyst or DBIx::Class project? Technical Directorhttp://www.shadowcat.co.uk/catalyst/ Shadowcat Systems Ltd. Want a managed development or deployment platform? http://chainsawblues.vox.com/http://www.shadowcat.co.uk/servers/ ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Dispatching based on path and host/domain
On Apr 22, 2008, at 9:14 AM, Matt S Trout wrote: The library provides come really common filtering facilities for my apps like active flag and valid_from/valid_to date ranges for records. That smells like there's a couple nice DBIC components in there trying to escape. I've been doing, I think, the same thing status, golive and takedown. I'd love to see it generalized if it can be. -Ashley ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
RE: [Catalyst] Dispatching based on path and host/domain
-Original Message- From: Curtis Fletcher [mailto:[EMAIL PROTECTED] Sent: Monday, April 21, 2008 7:08 PM To: catalyst@lists.scsys.co.uk Subject: [Catalyst] Dispatching based on path and host/domain Hi again guys. I've got a moderate sized Catalyst App in production now which I'm almost happy with :) It responds to one domain at the moment, and I'm pondering how to break out into two or more doing mostly the same thing on the same codebase and hopefully the same app instance. The app has a few usual controllers that handle specifics like the e-commerce, admin and soon, some database product access stuff. Any URI that fails to match a action defaults to the root controller and is then stripped and handled with a few calls to my model which builds the closest page from CMS style content. E.G. http://mydomain.com/cart/view Ends up calling the Local view method of myapp::Controller::Cart as you might expect but http://mydomain.com/businessunit1/product1/specialofferpage Ends up in the root controller and queries tables that holds dynamic URI-to-page content object mappings which then uses common code to render the page So for the CMS style data, if I add another domain mydomain2 to the apache config for my myapp and another field to the UriPage table for domain and I'm almost there. But I'm at a bit of a loss at to what to do about: http://mydomain2.com/cart/view Ending up at myapp::Controller::Cart-view because that domain isn't supposed to have the e-commerce bit. I've been pondering how to make this distinction, maybe there is something I could get the dispatcher to do like: package myapp::Controller::Cart; sub view : Local Domain('mydomain.com') { } Or something with the namespaces so that http://mydomain.com/cart/view got mapped to myapp::mydomain::Controller::Cart-view and http://mydomain2.com/search got mapped to myapp::mydomain2::Controller::Search still making sure that anything that didn't match still ended up in the root controller unmangled. What I think I'd like if to be able to do is opt a namespace out of a particular domain's dispatcher Something like: __PACKAGE__-config-{'opt_out'}- { 'mydomain2.com' = ['/cart',], 'mydomain.com' = ['/search',], } That way common actions still work on both domains. Worst comes to the worst I'll set config options that disable methods based on ENV variables then run two app instances on the same codebase but I'd prefer to avoid that. Is this approach even sane? any suggestions/pointers/thoughts are welcomed. You've probably heard this before on the list, but... Ideally, you shouldn't have enough code in your Controllers to justify sharing the app across domains that need different functionality. The meat of the app should be in the Models, then you can just run multiple Cat apps - one with Cart controllers and one without - that use the same shared Models. If you're thinking that you're stuck with what you've got think about the time it will take you to implement per-domain dispatching vs. the time to extract out functionality to a set of Models. Usually for me, fancy things like dispatching based on domain take much more time to implement than they appear, are more buggy and are harder to maintain. Ultimately, you'll end up with more maintainable applications if you keep the sharable functionality in the Models. If you're looking to share the app for other reasons (i.e. hosting costs) then I would look at it from a white-labeling perspective. Rather than have domain information in my Controllers, I would create the concept of sites inside the app and create a Plugin to interface the current site's config interface via something like $c-site. Then in my Cart controllers I might do something like MyApp::Controller::Cart; ... sub auto : Private { my ( $self, $c ) = @_; if ( ! $c-site-has_function('cart') ) { // something here to drop the request back to your best guess logic } } ... 1; You could even implement $c-site to use a Model to pull in site config info, which means changes on-the-fly. v/r -matt pitts ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/