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:

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?

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 Forder

Thanx for the feedback. I’ve responded below.

Cheers

Daniel N wrote:

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.

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.

Daniel N wrote:

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.

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.

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.

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

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.

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 link… It was interesting.