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 <[EMAIL PROTECTED]> wrote: > From: Dr. Jennifer Nussbaum <[EMAIL PROTECTED]> > Subject: Re: [Catalyst] Model--best practice help > To: "J. Shirley" <[EMAIL PROTECTED]> > Date: Monday, October 6, 2008, 11:13 AM > --- On Mon, 10/6/08, J. Shirley <[EMAIL PROTECTED]> > wrote: > > > From: J. Shirley <[EMAIL PROTECTED]> > > Subject: Re: [Catalyst] Model--best practice help > > To: [EMAIL PROTECTED] > > Date: Monday, October 6, 2008, 9:35 AM > > On Mon, Oct 6, 2008 at 9:08 AM, Dr. Jennifer Nussbaum > > <[EMAIL PROTECTED]> 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 > > <[EMAIL PROTECTED]> 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 _______________________________________________ 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/