John Napiorkowski wrote:
--- Tobias <[EMAIL PROTECTED]> wrote:

Hi everybody,

I'm writing a forum application with DBIx::Class and
Catalyst. Every post in a
forum is stored using two tables (for performance
reasons):

  * posts - (DBIC class "Forum::Post")
    contains basic data for every post
    has_one relationship with Forum::PostText

  * post_texts - (DBIC class "Forum::PostText")
    contains just the texts
    belongs_to Forum::Post

I'm wondering what's the best way to encapsulate
this because I don't want to
make calls to several DBIx::Class classes everywhere
I want to insert a new
post (i.e. in Catalyst controllers). Should I just
create a third class outside
the Schema namespace which utilizes all neccessary
DBIx::Class classes for
inserting a new post to hide the underlying
separation into two tables from
the rest of the application? What I want is to call
_ONE_ method in my
Catalyst controllers to insert a new post into the
database. The controller
shouldn't worry if the data gets stored in one, two
or ten tables.

Maybe there's some sort of DBIx::Class magic to do
this without having to
add an extra layer myself?

Thanks for any suggestions!

--Tobias

I think there are two (or two and a half) ways of
dealing with this that I've seen kicked around are:

1) Add some methods to your DBIx::Class files.  For
example you can write a method called create_post that
would be attached to the post class that would insert
into both tables for you.

I've heard this method called the "ActiveRecord"
pattern, since you are combining your physical model
(the object that maps to a table) with a business
model (that encapsulates your business rules).

2) Create a custom Catalyst Model that offers methods
for your business rules and creates it's own DBIx
class objects as part of it's instantiation.

2.5) like 2) but instead of the object being a
catalyst model you make it a plain Perl object (or use
a OO framework like Moose) and then have a very simple
Catalyst model instantiate it for you.

I tend to do 1) because it's easy and makes it so that
your business rules are not just inside catalyst (you
can use them for CRONS, etc).  I would like 2.5 for
the same reason but I'm not sure about the best
approach.  I'm hoping someone with a better grasp of
MVC best practices eventually releases an example :) For example I can see if you really get Moose you
could create a business object rule that all your
business classes you and then you are sure of the way
it would work.  This is the generally the approach
that J2EE uses; they have a bean object that uses an
interface for this, I think.

I think 1) is okay for rules that work primarily on a
single table or on tables that are related.  But
ideally you should have a separate domain object for
each class of business rule, or at least that is what
I am gathering from my reading of the way MVC is
handled in other frameworks.  This way you get better
reusability and can compose your objects best.  I
think it would also fit into the work being done on
Reaction (although please don't quote me on this, I am
still reading and re-reading reaction source) because
if you have a business object with a defined interface
that would make it easier to hook it to the UI model
through Moose's reflection.  Sounds great, wish I know
how to make it work :)

Will be watching this thread with interest.

--john



Solution 2.5 works very well for me:

- access to business model logic outside of Catalyst
- easy access from within Catalyst (integrated with ACCEPT_CONTEXT)
- it wouldn't be too hard to switch out the data model (DBIx::Class)

After a discussion on this list concerning the differentiation between data model and business/domain model this seemed like the consensus.

Cheers,
Brian

_______________________________________________
List: http://lists.rawmode.org/cgi-bin/mailman/listinfo/dbix-class
Wiki: http://dbix-class.shadowcatsystems.co.uk/
IRC: irc.perl.org#dbix-class
SVN: http://dev.catalyst.perl.org/repos/bast/trunk/DBIx-Class/
Searchable Archive: http://www.mail-archive.com/[email protected]/

Reply via email to