MVC and modules. Views telling models to behave

I was thinking today, it would be nice if a view could tell a model how
to
format it’s data for that particular view.

Kind of like, the view is bestowing instant, and temporary knowledge on
the
model for the duration of the views run.

It seemed to me that this would be more objecty than say a helper that
formats a string
format_my_string( my_string )

Instead, in my view. Lets assume I have a Building class that has a
phone_number field

At the top of my view then

<% Building.include PhoneNumberFormat %>

The PhoneNumberFormat module could overwrite the getter methods of
phone_number, fax_number etc to provide me with some nice formatting.
Presumably I could also pass some parameters somewhere (not quite sure
yet)
so that I could tell the PhoneNumberFormat what kind of format I want.

Then my building objects, when I call
<%= @building.phone_number -%>
instead of
<%= format_my_phone_number( @building.phone_number ) -%>
to get the format that I want

Is this a nasty abuse of MVC?

Thanx for any pointers

Daniel N wrote:

Instead, in my view. Lets assume I have a Building class that has a

Then my building objects, when I call
<%= @building.phone_number -%>
instead of
<%= format_my_phone_number( @building.phone_number ) -%>
to get the format that I want

Is this a nasty abuse of MVC?

Yes!

In MVC, the model provides its data in neutral form and the view decides
how to present it. This is a clean separation of concerns (and
separation of concerns is one of the cornerstones of object
orientation).

In your proposal, the model has to cater for a variety of ways of
returning each of its attributes (these would all have to be able to
vary independently) and the view has to know how to program the model to
give the attribute values in the form you want.

Then what happens when you want a new format, that hadn’t been
anticipated by the model? You have to:

  • add the new formatting capability to the model

  • add the ability to switch to that format in the model

  • do that switching in the view.

Bear in mind that there’s practically no limit to the different ways in
which data may be presented (graphical as well as textual), and it
should be crystal clear that putting the knowledge of how to do this in
the model is a recipe for disaster.

regards

Justin F.

Thanx for the feedback. I’ve responded below.

Cheers

On 10/26/06, Justin F. [email protected] wrote:

how to present it. This is a clean separation of concerns (and
separation of concerns is one of the cornerstones of object orientation).

In your proposal, the model has to cater for a variety of ways of
returning each of its attributes (these would all have to be able to
vary independently) and the view has to know how to program the model to
give the attribute values in the form you want.

This would be via the include statement

<% Building.include PhoneNumberFormat %>

The model knows nothing of formatting until the very last instant. Then
immediately forgets at the end of the response cycle. Since the view is
last, this is effectively; immediately forgets.

Then what happens when you want a new format, that hadn’t been

anticipated by the model? You have to:

  • add the new formatting capability to the model

Add a new format to the mixin module, not the model

  • add the ability to switch to that format in the model

The view would control which module is mixed in at runtime. This
doesn’t
need to be done in the model at all as far as I can tell.

  • do that switching in the view.

Bear in mind that there’s practically no limit to the different ways in
which data may be presented (graphical as well as textual), and it
should be crystal clear that putting the knowledge of how to do this in
the model is a recipe for disaster.

Perhaps your right. I was thinking along the lines of a form builder.
I
can (& I believe should) have a form defined in a view something like

<% form_for :user, :builder => MyBuilder do |f| %>
<%= f.text_field :name %>
<%= f.text_field :email %>
<%= f.password_field :password %>
<%= f.password_field :password_confirmation %>
<% end %>

I can have the builder generate whatever I like. I can even select the
builder programatically if I want.
I can have that form rendered as a table, or as divs, spans whatever.
All I
need to do is build the builder the way I want. Then all my forms
across
the site are consistant.

My thinking was along the lines of this. If you have a DateFormatter
module
and you could tell it to format all dates of a model a particular way.

Again the syntax is not correct at the moment but something like this
inside
a view or in the views helper.

<% MyModel.include DateFormatter do %>
<% date_fields :all, “%d %m %y” %>
<% end %>

I’m not sure how any of the issues that you raised are a problem. Not
saying they’re not… Just I don’t understand how they are yet.

On 10/19/06, Daniel N [email protected] wrote:

Instead, in my view. Lets assume I have a Building class that has a

I just did this for fun, so don’t take this as a recommendation to
actually start using it or something :slight_smile:

class Person
attr_reader :phone

def initialize(phone)
@phone = phone
end
end

module PhoneFormatter
def self.extended(o)
(class << o; self; end).instance_eval do
alias_method :old_phone, :phone
define_method(:phone) {
old_phone.gsub(/([0-9]{1,3})([0-9]{3})([0-9]{4}$)/,"(\1) \2-\3")}
end
end
end

irb(main):017:0> p = Person.new “5555551234”
=> #<Person:0x323eb0 @phone=“5555551234”>
irb(main):018:0> p.phone
=> “5555551234”
irb(main):019:0> p.extend PhoneFormatter
=> #<Person:0x323eb0 @phone=“5555551234”>
irb(main):020:0> p.phone
=> “(555) 555-1234”
irb(main):021:0> p.old_phone
=> “5555551234”

The PhoneFormatter module is pretty simple, but I’ll explain it if you
don’t know the metaprogramming going on. When anything extends PF,
the extended method gets called and is passed the object (usually a
class) that was extended with PF. In this case, however, we’re
extending a Person object rather than the class itself. So then we
get the metaclass of the person object, make an alias to keep the old
phone method, and then define a new phone method that applies some
formatting to the number returned from the old phone method.

In a nutshell, we’re defining a couple singleton methods on p. So it
won’t affect any other instances of Person.

As I said, I just did that for fun. The main drawback I can
immediately see is that it doesn’t follow Rails conventions. To be
honest though I don’t see a whole lot of upside to it…maybe if you
had several methods you wanted to format differently I guess, you
could just knock em off in one fell extend rather than calling a bunch
of helpers.

Maybe someone else would be willing to discuss the pros and cons of my
approach (which I’ve never used, and don’t intend to). I just decided
to experiment, and I need my sleep :slight_smile:

Pat

It seem that what you are after is some kind of presenter object. Take
a look at this article:

http://jayfields.blogspot.com/2006/09/rails-model-view-controller-presenter.html

On 10/26/06, Pat M. [email protected] wrote:

def initialize(phone)
end
=> “(555) 555-1234”
formatting to the number returned from the old phone method.

In a nutshell, we’re defining a couple singleton methods on p. So it
won’t affect any other instances of Person.

Wow… Thanx for the effort. I see that the extended method in the
documentation is not yet documented so this is indeed good to see it in
action.

As I said, I just did that for fun. The main drawback I can

immediately see is that it doesn’t follow Rails conventions. To be
honest though I don’t see a whole lot of upside to it…maybe if you
had several methods you wanted to format differently I guess, you
could just knock em off in one fell extend rather than calling a bunch
of helpers.

I guess one of the main things that I’m thinking of is locale specific
formatting. Dates, currency, Time, Phone numbers etc. The upside being
mainly consistency across a view, and DRYness for choosing what that
format
is. Specific formatting requirements wouldn’t need to be scattered
throughout code.

Mainly though it’s just a thought that I was having that I wanted to get
some perspective on.

Maybe someone else would be willing to discuss the pros and cons of my

approach (which I’ve never used, and don’t intend to). I just decided
to experiment, and I need my sleep :slight_smile:

I guess the only reason that I have been able to think of that this
might
not be a good idea, is when some method expects plain responses from a
model, but recieves the formatted version instead. An adjacent method
in
the model for example, or in a different model/controller/helper/module
may
blow up in this situation.

Thanx for the feedback. I’ve responded below.

Cheers

Sorri if this is a double post. I got a message to say that it wasn’t
delivered.

On 10/26/06, Justin F. [email protected] wrote:

how to present it. This is a clean separation of concerns (and
separation of concerns is one of the cornerstones of object orientation).

In your proposal, the model has to cater for a variety of ways of
returning each of its attributes (these would all have to be able to
vary independently) and the view has to know how to program the model to
give the attribute values in the form you want.

This would be via the include statement

<% Building.include PhoneNumberFormat %>

The model knows nothing of formatting until the very last instant. Then
immediately forgets at the end of the response cycle. Since the view is
last, this is effectively; immediately forgets.

Then what happens when you want a new format, that hadn’t been

anticipated by the model? You have to:

  • add the new formatting capability to the model

Add a new format to the mixin module, not the model

  • add the ability to switch to that format in the model

The view would control which module is mixed in at runtime. This
doesn’t
need to be done in the model at all as far as I can tell.

  • do that switching in the view.

Bear in mind that there’s practically no limit to the different ways in
which data may be presented (graphical as well as textual), and it
should be crystal clear that putting the knowledge of how to do this in
the model is a recipe for disaster.

Perhaps your right. I was thinking along the lines of a form builder.
I
can (& I believe should) have a form defined in a view something like

<% form_for :user, :builder => MyBuilder do |f| %>
<%= f.text_field :name %>
<%= f.text_field :email %>
<%= f.password_field :password %>
<%= f.password_field :password_confirmation %>
<% end %>

I can have the builder generate whatever I like. I can even select the
builder programatically if I want.
I can have that form rendered as a table, or as divs, spans whatever.
All I
need to do is build the builder the way I want. Then all my forms
across
the site are consistant.

My thinking was along the lines of this. If you have a DateFormatter
module
and you could tell it to format all dates of a model a particular way.

Again the syntax is not correct at the moment but something like this
inside
a view or in the views helper.

<% MyModel.include DateFormatter do %>
<% date_fields :all, “%d %m %y” %>
<% end %>

I’m not sure how any of the issues that you raised are a problem. Not
saying they’re not… Just I don’t understand how they are yet.

On 10/26/06, [email protected] [email protected] wrote:

It seem that what you are after is some kind of presenter object. Take
a look at this article:

http://jayfields.blogspot.com/2006/09/rails-model-view-controller-presenter.html

Thanx for the link… It was interesting.

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs