RE: [Catalyst] Dispatching based on path and host/domain

2008-04-23 Thread Curtis Fletcher
 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

2008-04-23 Thread Matt S Trout
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

2008-04-23 Thread Matt S Trout
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

2008-04-22 Thread Curtis Fletcher
 -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

2008-04-22 Thread Matt S Trout
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

2008-04-22 Thread Ashley

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

2008-04-21 Thread Matt Pitts
 -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/