understanding MVC and relationships among them - any schema?

Hi,

I'm about 1 month into RoR but still haven't managed to google out
some schematic summary of the RoR philosophy (maybe I'm just rubbish
with google):

- which function/method goes where (M/C/helper), what is the rule to
decide
- how to call function from one to another (from M to C, between two
Ms, between two Cs, available to all Ms, etc.) and how to pass
parameters (when to use params[:whatever] and when the variable
itself). when to use self.function etc.
- in which case I need to pass @records/@record/records/record

I'm almost always able to google out the particular solution to the
particular problem but still don't fully understand the logic/
conventions behind. I haven't come across some complex summary, the
best I got so far is Agile Development book but that didn't fully
clarify it for me.

Thanks for any hints!

Hi,

I'm about 1 month into RoR but still haven't managed to google out
some schematic summary of the RoR philosophy (maybe I'm just rubbish
with google):

- which function/method goes where (M/C/helper), what is the rule to
decide
- how to call function from one to another (from M to C, between two
Ms, between two Cs, available to all Ms, etc.) and how to pass
parameters (when to use params[:whatever] and when the variable
itself). when to use self.function etc.
- in which case I need to pass @records/@record/records/record

These aren't really rails questions, they're ruby (and to an extent
just oop in general).
Find yourself a decent ruby book and have a browse through it (AWDR
has a quick bit about ruby as an appendix, but it's just a quick
intro). There's Programming Ruby (also known as the pickaxe), Ruby for
Rails, http://www.humblelittlerubybook.com/, etc...

Fred

Great ideas... but what I've found is that while I'm versed in oop in
general, (and in other languages), there seems to be this "wall" with
Rails. In that you know there must be a better way to do something,
so what is it and why? Do you just not trust your own coding style?

Do you know that there will be a view (but right now you are working
on the models) that will say "Give me all of the <object> played
during this game" - so do you leave that answer up to the view, the
controller, or the model? Or another model?
games.find_by_id(201).played_cards. Do that in the controller?
controller_foo.get_played_cards? If you do it in the controller you
can ensure the current user is _allowed_ to see that game, etc.

Questions like that only come up, I've found, with time and with
projects. Make stupid little rails projects to "prove out a concept"
and learn from your mistakes. If after a month of code, you find it
hard to access something and you keep repeating - then move that
something somewhere else. :slight_smile:

Yes, that's basic OOP in general - but for some reason the new "rails
framework" idea that people come across, while not really new, makes
them rethink (and think they _need_ to rethink) how they do things.

Frederick Cheung wrote:

These aren't really rails questions, they're ruby (and to an extent
just oop in general).

Ii believe that the initial question about "what goes where in MVC" is
pretty much Rails-centric - Ruby is an OOP language, Rails is an MVC
framework.

First of all, I will recommend that you buy the two "Recipes" books:
"Rails Recipes" and "Advanced Rails Recipes". They explain a lot of
"best practices" in Rails on specific problems, and through that also a
lot about what goes into the Model, Controller and View.

These are my rules-of-thumb - they go with the general concept of MVC:

Model

Carsten Gehling wrote:

This question sometimes arises: What if I need to do operation on
multiple data-models at a time?

The answer is not the Controller but: Create a class for handling the
two or more models (this is called a "Service-class", and use this from
the Controller.

I forgot to mention, that there is an excellent example of this in
recipe 18 of "Advanced Rails Recipes" - do buy these books!!! :slight_smile:

- Carsten

pepa007: ignore my discussion below -- from what I can tell Carsten's rules are fairly generic in the Rails community, I'm raising more "advanced" ideas, and likely ones the Rails view of the world doesn't agree with, or I'm wrong :slight_smile:

One of my struggles with Rails is this notion of skinny controllers and fat models. I don't buy it. At least, not as a "rule" -- as a more than likely guideline, I'll agree it's what you consider first to see if it fits.

MVC in Rails seems to be treated like an exclusive 3-layer N-tier. IMO MVC describes 3 roles for classes/objects. Every class you write can generally be categorized as one of the three. That helps determine the general shape and contents of that class, and the label helps designers make decisions. Other than itself having internal N-tier-ish layering (e.g. data connectors) Rails discussions seem to ignore N-tier design in the applications.

MVC, IMO, does not dictate concepts like skinny controllers and fat models and thus some of the rules stated above. I can see where this comes from with a Rails controller pretty much intended specifically for handling the final step of request-specific routing, but the adoption of the notion that all other logic belongs in the model doesn't make sense to me. The domain-logic layer feels rather ignored to me in Rails. Ignored, or maybe just oversimplified.

I have models (stripped down data structures) which I reuse with different business logic. Sometimes, even different validation rules, so not entirely fond of having validations attached to models either--I prefer delegation for that role. Same for the business rules. Separation of data & rules dictates that business logic lives outside of the model.

Additionally, I have standardized user interfaces that abstract the UI control to where models are pretty much just plugins to an overall automated user input handling process (it's like a super fancy scaffolding). That process belongs neither in the model, nor in the first level of a Rails controller's method if we're going to use that just for HTTP handling--it is separate layer, but it is a controller in an MVC world (or maybe it's a abstracted model, but given where Rails draws the lines between HTTP and persistence, the code belongs in a Rails controller).

So, while for the majority of dead-simple web sites and simple web applications that are straight forward hand-to-mouth request to data handling, then I suppose these rules pretty much apply. But the idea that once a controller method starts to get to be 20 lines something probably belongs in the model--I don't buy that at all. The code may belong somewhere else, but to assume that it is always in the model (as it would rarely likely belong in the view), I think is misleading to sell it as an OOP rule of thumb.

Then again maybe all my code is junk, but I've had no problem extending, maintining, and reusing it over many applications and years -- all of which I see as the real purpose of OOP/MVC. Maybe I'm just over reacting to advice that's good to give 99% of beginners, but I find myself at odds with Rails design edicts from time to time, and no way to really hash it out with someone to see if I'm wrong or have a valid scenario that Rails didn't consider / opted not to care about.

-- gw

Greg Willits wrote:

- Calculated fields based on selected data

Controller
--------------
Everything that has to do with with HTTP requests and responses goes
into the Controller.
The controller is the only place, where you should handle "params",
"session", "cookie", etc.
If you find yourself with a controller method, that spans more than 20
lines, then some of it probably belongs in the View or Model.

pepa007: ignore my discussion below -- from what I can tell Carsten's
rules are fairly generic in the Rails community, I'm raising more
"advanced" ideas, and likely ones the Rails view of the world doesn't
agree with, or I'm wrong :slight_smile:

Ahh... I like a good discussion. :slight_smile: Well as long as your arguments are
good, your ideas don't need to match those of everyone else.

One of my struggles with Rails is this notion of skinny controllers
and fat models. I don't buy it. At least, not as a "rule" -- as a
more than likely guideline, I'll agree it's what you consider first
to see if it fits.

I made an error in my description of the controller. I wrote:

The controller is the only place, where you should handle "params",
"session", "cookie", etc.

But I did not mean, that this nessecarily is the ONLY things, that the
controller should handle.

The 20-lines "rule" should just be a gauge when you revise your code.
OOP idioms say that each method should be as simple as possible and not
fullfil more than one task. This also goes for methods in a controller.
Each method (action) should only handle one task - if you create too
many dependencies in a method, something is wrong with your design.

I don't know yet, if I hold with the "skinny controller" idea, neither
with "each controller should just contain CRUD operations". It might
impose too much constraint on your design and force you to invent
ressources that aren't really there.

MVC, IMO, does not dictate concepts like skinny controllers and fat
models and thus some of the rules stated above. I can see where this
comes from with a Rails controller pretty much intended specifically
for handling the final step of request-specific routing, but the
adoption of the notion that all other logic belongs in the model
doesn't make sense to me. The domain-logic layer feels rather ignored
to me in Rails. Ignored, or maybe just oversimplified.

I agree with you. The basic Rails introductions fail to discuss where to
put methods/code that interact with more than one datastructure at once.

Models are described as simply being classes on top of a database table.
So 3 tables => 3 model classes. With this scheme, people are tempted to
put domain-specific code into the controller, when they need to operate
on more than one table at a time.

I have models (stripped down data structures) which I reuse with
different business logic. Sometimes, even different validation rules,
so not entirely fond of having validations attached to models either--
I prefer delegation for that role. Same for the business rules.
Separation of data & rules dictates that business logic lives outside
of the model.

I don't think, that business logic should live outside the model. A
model IMHO is responsible for validating data that it accepts into its
data-layer.

The problem occurs when validation in one model is depending on another
model.

So, while for the majority of dead-simple web sites and simple web
applications that are straight forward hand-to-mouth request to data
handling, then I suppose these rules pretty much apply. But the idea
that once a controller method starts to get to be 20 lines something
probably belongs in the model--I don't buy that at all. The code may
belong somewhere else, but to assume that it is always in the model
(as it would rarely likely belong in the view), I think is misleading
to sell it as an OOP rule of thumb.

Again I agree. The code need not nessecarily be put into the model, but
most of the time it implies, that something is made unnessecarily
complex, and could be refactored out into "service" methods/classes.

Maybe I'm
just over reacting to advice that's good to give 99% of beginners,

My reply was exactly that - a beginners guide. :slight_smile:

but I find myself at odds with Rails design edicts from time to time,

That is why they call it "oppionated software". :wink:

I have also had my disagreements with Rails. Coming from the free world
of C/C++, PHP and Perl, I am not used to the straight-jacket approach,
that Rails forces. But I've found myself programming faster in Rails
than in any other of the aforementioned languages - even from my first
Rails project - so I have reluctantly accepted that it is "The Rails Way
or the Highway". A price I now gladly pay for the power I get.

- Carsten

Greg Willits wrote:

I have models (stripped down data structures) which I reuse with
different business logic. Sometimes, even different validation rules,
so not entirely fond of having validations attached to models either--
I prefer delegation for that role. Same for the business rules.
Separation of data & rules dictates that business logic lives outside
of the model.

I don't think, that business logic should live outside the model. A
model IMHO is responsible for validating data that it accepts into its
data-layer. The problem occurs when validation in one model is depending on another
model.

In my past work I've leaned towards validating "input" rather than a model. I had occasion to often reuse identical/nearly-identical data storage but with some different validations and business rules. So, I started to separate the two so that I could reuse a query ORM layer and the data models, and place the validations and business rules in a layer that preceded the data model in terms of where the real work was done.

In effect where,
   Rails is: model <-> controller,
   my stuff was: (model<->domain) <-> controller

I got used to validating inputs before ever putting them into the model. I don't like Rail's method of stuffing the model first, then validating it--the h() on output rather than eliminating the offensive data from the start. Bad data shouldn't even get into the model in memory IMO. So my validation system dealt with params as data objects where the rules had the ability to be defined as universal to all input sources, or specific to an input source.

This way when I build an application for "clubs" -- data structures like membership was generally very reusable with little or no change, and the rules differences were handled separately.

Again, might not be "right," but it's what my reading and environment lead me to do.

I think the "type" of applications I have built tend to have different concerns that those that bore the development of Rails -- so that's where I get most of my "hmmm, idunlikeit" reactions. Trying to figure out how to mesh the two has been a challenge.

Maybe I'm
just over reacting to advice that's good to give 99% of beginners,

My reply was exactly that - a beginners guide. :slight_smile:

Yeah, I know yours was, I was referring to the discussion & advice at large. It's all rather Steppford-ish in its uniformity--which is good for the beginning programmer I suppose. The flip side is that it's difficult to find someone willing to talk outside the rails way. It's pretty much, "but... why would you do that? Rails says..."

I have also had my disagreements with Rails. Coming from the free world
of C/C++, PHP and Perl, I am not used to the straight-jacket approach,
that Rails forces. But I've found myself programming faster in Rails
than in any other of the aforementioned languages - even from my first
Rails project - so I have reluctantly accepted that it is "The Rails Way
or the Highway". A price I now gladly pay for the power I get.

In my case, I had developed my own extensive framework starting in 2001 for these types of apps. Overall, I don't find Rails any more productive than my own framework. It has very similar coverage of purpose and tools to Rails (some variations on what is built-in). It's also very convention over configuration oriented, though it's more open to variations than Rails is. So, I got used to 100% "my-way" and I do find it a little hard to give up -- not quite used to this highway business yet :wink:

-- gw

Greg Willits wrote:

In effect where,
   Rails is: model <-> controller,
   my stuff was: (model<->domain) <-> controller

Actually I also miss more documentation about doing
model<->domain<->controller stuff in Rails.

You CAN do it, but it is IMHO one of the areas where Rails lack
conventions (which it otherwise has plenty of).

I got used to validating inputs before ever putting them into the
model. I don't like Rail's method of stuffing the model first, then
validating it--the h() on output rather than eliminating the
offensive data from the start. Bad data shouldn't even get into the
model in memory IMO.

Rails does it like that because the model is responsible for "taking
care of itself". It trusts nobody but itself to validate data before
saving it. But again, just because Rails does it, doesn't make it the
only valid practice.

Not that I want to draw out the discussion (though I like your
arguments), but one of the good things I like about Rails' "we only want
it done THIS way" is, that it makes it easier to enter an existing
project. Everything is in its "proper" way (at least proper from Rails
point of view). Coming from PHP (with its multitude of frameworks and
template engines) and Perl (with its famous "there is more than one way
to do it" quote), it's actually a relief for me to be told of one way to
do things.

Then again, I'm 36. Maybe I'm getting too old for this sh*t... :slight_smile:

- Carsten

Greg Willits wrote:

I got used to validating inputs before ever putting them into the
model. I don't like Rail's method of stuffing the model first, then
validating it

Rails does it like that because the model is responsible for "taking
care of itself". It trusts nobody but itself to validate data before
saving it.

Not that I want to draw out the discussion (though I like your
arguments), but one of the good things I like about [the Rails Way]
is, that it makes it easier to enter an existing project...
Coming from PHP ... and Perl ..., it's actually a relief
for me to be told of one way to do things.

Yeah, and I do admit, those are some of reasons I adopted Rails for some current projects. I just have to keep reminding myself of that.

Others = Ruby's promise--lacking now, but in 5 yrs it should be great, and generally the permeation of agile and pragmatic principles in the community. As much as I managed to accomplish on my own, I simply wasn't going to keep pace, and the Lasso language, as cool as it is, simply wasn't on the growth curve to attract enough high-end talent to draw from to help out. That and a project with Thoughtworks pushed me over the edge into giving Rails a go.

So, for now, it's onward...

Then again, I'm 36. Maybe I'm getting too old for this sh*t... :slight_smile:

I'm 44, and this is my third career. I've monkeyed with programming since 1982 (lots of work group apps from materials management to bottling engineering processes), got more serious and generally web focused since 2000, started OOP in 02, and 100% software and independent in 2003. So that's not a lot of time with OOP which is why even though I found things that worked for me, I realize I have much learning to do.

A lot of my coding has been to look at framework level issues--to use some working projects as the cases for developing frameworks to use in future projects. My target was to find that line that I now see as the insanity of J2EE (too big for my types of apps), and the narrow feld of vision of Rails. Rails is very close--I'd like just a little more elbow room at times. I suspect after I get more familiar with where and how to extend the framework, I'll be able to add those things I find important enough.

On top of that, I've spent my entire career researching, adapting, and creating new technologies, new systems, new processes: from designing and building complex industrial equipment for the big semiconductor companies to managing corporate marketing for a $60M company.

So at 44, I'm too old and too programmed to just accept someone else's way "just because" :slight_smile: It's a blessing, and a curse.

-- gw

Try this:

http://groups.google.com/group/rubyonrails-talk/browse_thread/thread/19bad38ebfb1f1e7/04fae07685018046?hl=en&lnk=gst&q=model+view+controller+"Sheldon+Hearn"#04fae07685018046

Still works really well for me.

Ciao,
Sheldon.

Sheldon Hearn wrote:

Try this:

http://groups.google.com/group/rubyonrails-talk/browse_thread/thread/19bad38ebfb1f1e7/04fae07685018046?hl=en&lnk=gst&q=model+view+controller+"Sheldon+Hearn"#04fae07685018046

Still works really well for me.

Good points in that post.

Some things that I miss in Rails, though, are helpers. There is a helper
system for the views, but not for the controllers or for the models.
Both of these can use "helper-classes" defined in /lib, but I miss a
formalised way of doing this (since Rails is so oppinionated).

- Carsten

Gentlemen,

Thanks so much for valuable tips!

Keep this discussion going, the only efficient way to shape best
practices is probably sharing and discussing them.