Fw: Re: [Catalyst] Model--best practice help

Dr. Jennifer Nussbaum bg271828 at yahoo.com
Mon Oct 6 19:27:59 BST 2008


J. Shirley forwarded the accidetnally-offlist post to the list, but this was my response to him, about Controller v. Model stuff. Wanted to make sure its part of the discussion too.

Jen


--- On Mon, 10/6/08, Dr. Jennifer Nussbaum <bg271828 at yahoo.com> wrote:

> From: Dr. Jennifer Nussbaum <bg271828 at yahoo.com>
> Subject: Re: [Catalyst] Model--best practice help
> To: "J. Shirley" <jshirley at gmail.com>
> Date: Monday, October 6, 2008, 11:13 AM
> --- On Mon, 10/6/08, J. Shirley <jshirley at gmail.com>
> wrote:
> 
> > From: J. Shirley <jshirley at gmail.com>
> > Subject: Re: [Catalyst] Model--best practice help
> > To: bg271828 at yahoo.com
> > Date: Monday, October 6, 2008, 9:35 AM
> > On Mon, Oct 6, 2008 at 9:08 AM, Dr. Jennifer Nussbaum
> > <bg271828 at yahoo.com> wrote:
> > > (things trimmed, and also you replied to me
> personally
> > but not the list, dont know if that was intentional)
> > >
> > >
> > >
> > > --- On Mon, 10/6/08, J. Shirley
> > <jshirley at gmail.com> wrote:
> > >
> > >>
> > >> > Jen
> > >>
> > >> My example -was- simple multiple inheritance.
> 
> > That is what
> > >> the
> > >> multiple packages in "use base"
> does.
> > >>
> > >> >> use base
> qw/Catalyst::Model::DBIC::Schema
> > >> MyApp::Model::Book/;
> > >
> > > i understand that this was MI, but my point was
> that
> > if i still have to call the "Cat" model
> class one
> > way, and the schema model class the other
> > > way, it doesnt really help. What is need is to
> call a
> > single model, regardless of what im doing.
> > >
> > > Putting it another way, it shouldnt matter to the
> > *Cat* programmer whether a function is in the DBIC
> schema
> > (like "search" or "find", or even
> > something
> > > else thats customized in the schema class), or is
> in
> > the Cat model class. The programmer should just be
> able to
> > call $c->model('Book') (or anything
> > > else that's regular).
> > >
> > 
> > [Full Stop]
> > 
> > If you want this, you can't use
> > Catalyst::Model::DBIC::Schema at all.
> > It generates a model class for every schema class.
> > 
> > When you call $c->model('Book') what do you
> want
> > to get back?  What is
> > MyApp::Model::Book?  What do you want it to be?  Do
> you
> > want it to be
> > a MyApp::Model::DBIC::Book class (or whatever your
> > Model::DBIC::Schema
> > generates as the name)?
> 
> What id like is a model that inherits from the
> Schema-generated class, so that i can call a method from
> either class without worrying about whitch
> its in. 
> 
> Thats what i do with my Controllers alredy: i have a
> Controller Base class that i inherit from, and i put
> "add", "view", "edit", etc. in
> 
> there. Then in my specific Controller classes i can either
> put nothing ("view" is simple, it can default to
> the base class), or put in overrides
> and then call SUPER to get to the Base.
> 
> > 
> > >>
> > >> Eden posted a very simple Moose example to
> get you
> > going
> > >> down that
> > >> path.  If you modified your
> > lib/MyApp/Model/MyApp.pm to
> > >> inherit from
> > >> other classes (cat specific or not) then the
> > methods from
> > >> those would
> > >> be accessible via
> > >> $c->model('MyApp')->whatever. 
> > That's the
> > >> method I
> > >> showed.
> > >
> > > i understand that Edens example was simple and
> clear,
> > and i do appreciate
> > > it. But it does still involve learning something
> about
> > Moose, or in
> > > some cases convincing one's bosses that a
> project
> > needs an entirely new OO layer to make it work.
> > >
> > >> Basically at this point, without knowing your
> > exact
> > >> codeframework
> > >> you're only going to get these vague
> Multiple
> > >> Inheritance 101 answers.
> > >>  Just with or without Moose :)
> > >
> > > I appreciate the time youve spent on this, but i
> dont
> > think its necessary to show my whole codebase. Let me
> try
> > once more explain what i want to
> > > do, with a more specific example, then:
> > >
> > > Suppose i have a library application with the
> setup as
> > described before, that is a DBIC schema group of
> classes set
> > up and a MyApp::Model area.
> > >
> > > I want to write a method called
> > get_books_by_purchase_date($foo), where
> > > $foo is some parameters taken from a Cat search
> form.
> > In other words
> > > this function is clearly related to Cat, and not
> to
> > the database layer,
> > > because it needs to do something related to my
> Cat
> > app, and i wouldnt
> > > call it from an app thats not running on Cat.
> > >
> > 
> > If $foo is processed, I don't see why that
> isn't a
> > resultset method, tbh.
> > 
> >
> $schema->resultset('Book')->get_books_by_purchase_date($criteria);
> >
> $c->model('Schema::Book')->get_books_by_purchase_date($criteria);
> > 
> > What is Catalyst specific is generating the search
> > criteria, right?
> > Could you explain -why- you wouldn't call it from
> an
> > application that
> > isn't Catalyst-based?  It seems that is would be a
> > useful method on
> > the resultset later, and just an artificial
> restriction
> > that it is
> > Catalyst-based (but again, don't know the role)
> 
> Hmm. Perhaps that wasnt the best example. But one method in
> my real world might be this:
> 
> I have users. Users, who only interact through the Cat app,
> have access to specific things in a way that i cant do by
> using the auth framework alone (say, some users can only
> view books
> published after 1950, others can view books published in
> America, ect.).
> So, i want to have a get_books_by_user() method that will
> return results based on these factors. This only matters for
> Cat users, it's not really
> a function of the database of books, so i want it to be
> "part" of my
> Cat app, not just bolted on from the database schema.
> 
> But i guess one of the main things is that as i said in my
> original post i have a lot of confusion between Controller
> and Model, that is, i do
> things in my Models that should be in my Controllers.
> (Like, i might say get_books($c) in my Controller, with
> get_books in my Model--i started
> doing this early because "get_books" seemed like
> a database query instead of "business logic", so
> my Model then looks at query params, ect.) Now
> i realize that this should be in my Controller.
> 
> So i guess that once i move these things into my
> Controller, i wont really need this "Cat-specific"
> model that ive been using now, so i can have 
> everything in my controller and if neccessary put some
> ResultSet methods
> into my Schema model class.
> 
> > 
> > > Where do i put this function? If i put it in
> > MyApp::Model::Books, then i
> > > have to remember that it's
> >
> $c->model('Books')->get_books_by_purchase_date($foo),
> > but it's
> > >
> $c->model('MyAppDB::Books')->find($id).
> > That's a pain, especially if my real
> > > example is actually more complicated, and i want
> to
> > (for instance) have the
> > > base of a chain that sets the model in the stash,
> and
> > then in later parts of the chain
> > > do something based on the model, but i cant do
> these
> > because for a given
> > > table i have two different models depending on
> whether
> > im using a
> > > DBIC method or my own method.
> > >
> > > That is about the clearest i can be. If ive been
> > misunderstanding you all along, i apologize.
> > >
> > 
> > Well, aside from not understand -why- you want to do
> it,
> > the answer is
> > probably "Programming".  Right now you are
> using
> > Catalyst::Model::DBIC::Schema which simply creates a
> map of
> > your
> > schema classes to a model class.  What you want is to
> > decorate the
> > model class that is generated and add additional
> methods to
> > it.  Not
> > to harp on Moose, but... Moose would make this -much-
> > easier.
> > 
> > To start with, you'll want to read the source for
> > Catalyst::Model::DBIC::Schema, specifically just
> "sub
> > new { }" --
> > there you will see how the model classes are
> instantiated.
> > 
> > The meat of it is just:
> >     foreach my $moniker ($self->schema->sources)
> {
> >         my $classname =
> "${class}::$moniker";
> >         *{"${classname}::ACCEPT_CONTEXT"} =
> sub {
> >             shift;
> >            
> > shift->model($model_name)->resultset($moniker);
> >         }
> >     }
> > 
> > What this does is creates a Model::$Name that is
> simply a
> > ResultSet.
> > At this point, what you -could- do, is set the
> resultset
> > class to
> > something Catalyst specific.  That would give you
> methods
> > on
> > $c->model("Schema::$Name").
> > 
> > So, something like:
> > sub {
> >     shift;
> >     my $schema =
> shift->model($model_name)->schema;
> >     my $source = $schema->source( $moniker );
> >    
> >
> $source->resultset_class("MyApp::Custom::ResultSet");
> >     $source->resultset;
> > }
> > 
> > Now, every MyApp::Model::DBIC::* class would have the
> > resultset
> > methods.  You could only apply this on certain
> monikers
> > (moniker would
> > be 'Book', etc).
> > 
> > (I'm sure Eden or Matt can hop in here and do
> something
> > better while I
> > go put on my pointy hair)
> > 
> > > Thank you again for your time, which i really do
> > appreciate.
> > >
> > > Jen
> > >
> > >
> > 
> > np, happy to help.
> 
> I think it should do two things first: refactor things into
> my Controllers as i describe above, and take a look at Moose
> :-) I guess its the future anyway.... (What happens to Moose
> when Perl 6 comes along?)
> 
> Thanks again,
> 
> Jen


      



More information about the Catalyst mailing list