Forum: Ruby on Rails logic inside a view file

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Craig W. (Guest)
on 2006-03-20 23:30
(Received via mailing list)
I am quite certain I have heard it said not to put business logic inside
view code but I have a report that I want to display 3 different
possibilities of text based upon the value of a column. Would I just
take the same type of if/then logic that I would use in a controller and
put it inside erb <%= %> stuff?

Craig
Tom M. (Guest)
on 2006-03-20 23:41
(Received via mailing list)
No!

Use a helper instead.

--
-- Tom M.
Tom L. (Guest)
on 2006-03-20 23:46
(Received via mailing list)
On 3/20/06, Craig W. <removed_email_address@domain.invalid> wrote:
> I am quite certain I have heard it said not to put business logic inside
> view code but I have a report that I want to display 3 different
> possibilities of text based upon the value of a column. Would I just
> take the same type of if/then logic that I would use in a controller and
> put it inside erb <%= %> stuff?

For the Rails projects I've seen and managed, it seems that the line
between 'controller' and 'view' code is this: querying the database or
modifying variables is only done in controllers. Beyond that, any
logic for modifying the page is fair game for your view. Of course,
this is only my opinion, and there is nothing stopping you (outside
method availability) from putting any sort of code you want in your
views.

Over time you will get a better idea of when some code will become
difficult to maintain. As a rule of thumb, if you find yourself
putting the same code in multiple places, you'll probably want to
abstract that using partials, helpers, controller parent classes, or
something else.

Good luck with your decisions.

> Craig

Sincerely,

Tom L.
http://AllTom.com/
http://GadgetLife.org/
Craig W. (Guest)
on 2006-03-21 01:28
(Received via mailing list)
On Mon, 2006-03-20 at 16:46 -0500, Tom L. wrote:
> logic for modifying the page is fair game for your view. Of course,
> Good luck with your decisions.
>
> > Craig
>
> Sincerely,
>
> Tom L.
----
On Mon, 2006-03-20 at 13:40 -0800, Tom M. wrote:

> No!
>
> Use a helper instead.
>
----
Two Tom's, two entirely different answers.

;-)

thanks...I pretty much made my decision for now as it's a simple task
(or it seems to me to be a simple task), to just insert the quickie into
the view code - especially since it only evaluates values from an
existing hash.

Craig
Jeremy H. (Guest)
on 2006-03-21 04:59
(Received via mailing list)
Good decision. We need to stop feeling guilty about putting
conditionals in views just because its the same thing we did in ASP &
PHP. Ruby is a good language for making simple conditional statements,
what difference does it make if its eRuby? Tom's advice is good imho.
If you want to really insulate the view maybe look at Liquid templates
but be sure you know why you are doing - "the architect says" is not
really a reason.

On 3/20/06, Craig W. <removed_email_address@domain.invalid> wrote:
> > modifying variables is only done in controllers. Beyond that, any
> >
> > No!
> Craig
>
> _______________________________________________
> Rails mailing list
> removed_email_address@domain.invalid
> http://lists.rubyonrails.org/mailman/listinfo/rails
>


--
Jeremy H.
http://www.jeremyhuffman.com
Craig W. (Guest)
on 2006-03-21 05:23
(Received via mailing list)
On Mon, 2006-03-20 at 21:59 -0500, Jeremy H. wrote:
> Good decision. We need to stop feeling guilty about putting
> conditionals in views just because its the same thing we did in ASP &
> PHP. Ruby is a good language for making simple conditional statements,
> what difference does it make if its eRuby? Tom's advice is good imho.
> If you want to really insulate the view maybe look at Liquid templates
> but be sure you know why you are doing - "the architect says" is not
> really a reason.
----
I did - it's done, it works, it's ugly  ;-)

<%= (facility.pltype == "PAH" ? "&nbsp; PAH (11:59 PM) &nbsp;" :
(facility.pltype == "16 Hour" ? "&nbsp; 16 Hour (11:59 PM) &nbsp;" :
"&nbsp; Bed Check (11:59 PM) &nbsp;")) %>

I didn't indent it with the rest of the html code to make it stand out
like the proverbial sore thumb.

Simple, effective ugly...like I like my women  ;-)

just kidding

Craig
Justin F. (Guest)
on 2006-03-21 06:05
(Received via mailing list)
Craig W. wrote:

> <%= (facility.pltype == "PAH" ? "&nbsp; PAH (11:59 PM) &nbsp;" :
> (facility.pltype == "16 Hour" ? "&nbsp; 16 Hour (11:59 PM) &nbsp;" :
> "&nbsp; Bed Check (11:59 PM) &nbsp;")) %>

There is common text between those three cases: you could move it out of
the dynamic expression:

&nbsp; <%= ... %> (11:59 PM) &nbsp;

What is the value of facility.pltype when you want "Bed Check" to be
displayed? It would be nice if it was just "Bed Check":

&nbsp; <%= facility.pltype %> (11:59 PM) &nbsp;

A helper method is valuable (a) to take logic out of the view, and (b)
to allow the logic to be re-used in different views, without
duplication.

E.g.

In application_helper.rb (or whatever more specific helper is
appropriate):

   def display_pltype(pltype)
     pltype == "PAH" || pltype == "16 Hour" ? pltype : "Bed Check"
   end

In template:

&nbsp; <%= display_pltype(facility.pltype) %> (11:59 PM) &nbsp;

...Rails lets you keep your views clean with very little extra work (and
it should pay back in terms of maintainability)

It's your choice!

   Justin
Craig W. (Guest)
on 2006-03-21 06:39
(Received via mailing list)
On Tue, 2006-03-21 at 04:05 +0000, Justin F. wrote:
>
> What is the value of facility.pltype when you want "Bed Check" to be
> displayed? It would be nice if it was just "Bed Check":
>
> &nbsp; <%= facility.pltype %> (11:59 PM) &nbsp;
----
yeah but it isn't. There are a number of other pltypes...it's just those
particular 2 don't perform bed checks.
----
>    end
>
> In template:
>
> &nbsp; <%= display_pltype(facility.pltype) %> (11:59 PM) &nbsp;
>
> ...Rails lets you keep your views clean with very little extra work (and
> it should pay back in terms of maintainability)
>
> It's your choice!
----
Thanks for taking the time to explain that. I am somewhat new to all
this and that is very imaginative and I think I understand it and will
likely change to using it.

The next phase is to clean up all of the sloppy code that I did to get
this far...as I have seen that using some of these types of ruby
snippets are really effective and I've got a lot of 'WET' ( WET != DRY )
type code in my controllers but I didn't want to get bogged down with
the higher quality usage of things I wasn't on top of - especially when
I started with this 6 weeks ago (the first two controllers/models that I
did are probably dripping WET).

I presume if I just put this into my facility class...I could just
simply refer to in my template with
<% Facility.display_pltype(facility.pltype) %>

and while it is more typing than your suggestion, it does keep things in
it's place.

I guess the thing I don't understand is...why would this go into a model
or a helper? What is the criteria? (other than arbitrary)...btw, this
code runs from my 'reports' controller.

Thanks again

Craig
Justin F. (Guest)
on 2006-03-21 09:50
(Received via mailing list)
Craig W. wrote:
>>
>> What is the value of facility.pltype when you want "Bed Check" to be
>> displayed? It would be nice if it was just "Bed Check":
>>
>> &nbsp; <%= facility.pltype %> (11:59 PM) &nbsp;
> ----
> yeah but it isn't. There are a number of other pltypes...it's just those
> particular 2 don't perform bed checks.

OK. My helper, below, didn't make that assumption.

>>    end
> Thanks for taking the time to explain that. I am somewhat new to all
> this and that is very imaginative and I think I understand it and will
> likely change to using it.
>
> The next phase is to clean up all of the sloppy code that I did to get
> this far...as I have seen that using some of these types of ruby
> snippets are really effective and I've got a lot of 'WET' ( WET != DRY )
> type code in my controllers but I didn't want to get bogged down with
> the higher quality usage of things I wasn't on top of - especially when
> I started with this 6 weeks ago (the first two controllers/models that I
> did are probably dripping WET).

Fine. Don't leave it too long - the WET stuff is probably already
slowing you down, and it's good to get into the habit of refactoring as
you go, rather than saving it up for a quieter time (which may never
happen).

> I presume if I just put this into my facility class...I could just
> simply refer to in my template with
> <% Facility.display_pltype(facility.pltype) %>
>
> and while it is more typing than your suggestion, it does keep things in
> it's place.

Indeed. Less typing if you make it an instance method of Facility:

   def display_pltype
     pltype == "PAH" || pltype == "16 Hour" ? pltype : "Bed Check"
   end

   <%= facility.display_pltype %>

...but this raises the question you ask below:
>
> I guess the thing I don't understand is...why would this go into a model
> or a helper? What is the criteria? (other than arbitrary)...btw, this
> code runs from my 'reports' controller.

OK, so if you use a helper method it would probably go in your
reports_helper.

It is a matter of judgement - is this really business logic, or does it
relate to how you present the underlying model. It appears to me that it
may be a bit of both.

Sorry not to reply in more detail - have to go to work!

regards

   Justin
Craig W. (Guest)
on 2006-03-21 10:28
(Received via mailing list)
On Tue, 2006-03-21 at 07:50 +0000, Justin F. wrote:
> Craig W. wrote:

> >> What is the value of facility.pltype when you want "Bed Check" to be
> >> displayed? It would be nice if it was just "Bed Check":
> >>
> >> &nbsp; <%= facility.pltype %> (11:59 PM) &nbsp;
> > ----
> > yeah but it isn't. There are a number of other pltypes...it's just those
> > particular 2 don't perform bed checks.
>
> OK. My helper, below, didn't make that assumption.
----
I did notice - that's why it was so obvious to me that I should probably
incorporate it.
----
> >>      pltype == "PAH" || pltype == "16 Hour" ? pltype : "Bed Check"
> > ----
> > did are probably dripping WET).
>
> Fine. Don't leave it too long - the WET stuff is probably already
> slowing you down, and it's good to get into the habit of refactoring as
> you go, rather than saving it up for a quieter time (which may never
> happen).
----
well - I feel as though I should defend myself...I have taken this from
0 to a fairly well defined application in 6 weeks and it is my first
project but clearly, what I knew 6 weeks ago was decidedly less than 4
weeks ago, two weeks ago and obviously today. The first task was getting
it done - regardless of all the things I didn't understand at the
time...I assumed that I would catch on along the way and I sort of
catching on.

I am quite sure that there is stuff slowing me down...like my stupidity
tonight with svn and deleting a folder that I wanted to keep. But the
code seriously needs cleanup and that is a big priority after I
propogate the current branch because this branch has all of the reports
needed for them to fully replace the other methodology that this rails
application is replacing.
----
>    def display_pltype
>      pltype == "PAH" || pltype == "16 Hour" ? pltype : "Bed Check"
>    end
>
>    <%= facility.display_pltype %>
>
> ...but this raises the question you ask below:
----
well - I should state that I was a little afraid of using
'facility.display_pltype' directly since we are directly within an
iteration with a hash named 'facility' and this could be a bit
confusing. To me...it's a method defined within the facility but I
haven't found a reason to put stuff in helpers yet.
----
> may be a bit of both.
>
> Sorry not to reply in more detail - have to go to work!
----
Thanks for your excellent illustrations for me. I do appreciate it.

Craig
Tom M. (Guest)
on 2006-03-21 10:30
(Received via mailing list)
Craig W. wrote:

> I guess the thing I don't understand is...why would this go into a
> model
> or a helper? What is the criteria? (other than arbitrary)...btw, this
> code runs from my 'reports' controller.

my 2 cents:

It belongs in a model if:

   1) It can provide data to other code in a way that will not change if
      the underlying representation changes. Other code should never
have
      intimate knowledge of underlying representation.

It belongs in a helper if:

   1) It needs to be shared amongst more than 1 controller
(authorization
      and authentication comes to mind)
   2) It relates to view code

As an example: Imagine we have a model that has a column, :type, and
that
column can contain 'M', 'C', or 'A', which represent MasterCard,
Visa, and
Amex, respectively.

Nothing outside the model should *ever* know about 'M', 'C', and 'A'!

Instead, in the model:

   def is_mastercard?
     type == 'M'
   end

   def is_visa?
     type == 'V'
   end

   def is_amex?
     type == 'A'
   end

And a helper:

   def card_name_for(card)
     return "MasterCard"    if card.is_mastercard?
     return "Visa"          if card.is_visa?
     return "Priceless :-)" if card.is_amex?
   end

And in the view:

<% for card in @cards -%>
   Type: <%= card_name_for(card) %>
<% end -%>

This gives you a great deal of isolation, and some useful
methods on the model that make the helper and (no doubt)
other code more readable, and allows for a complete
refactor of Card.type in the future without changing
anything else.

For instance, why store card type at all when it can be
derived from the card number itself? If you've written it
this way, you can drop the column, add the card number
differentiation logic to the is_*? model methods, and you're
done.

--
-- Tom M.
Craig W. (Guest)
on 2006-03-21 16:58
(Received via mailing list)
On Tue, 2006-03-21 at 00:30 -0800, Tom M. wrote:
>
>    2) It relates to view code
>
>    end
>
> For instance, why store card type at all when it can be
> derived from the card number itself? If you've written it
> this way, you can drop the column, add the card number
> differentiation logic to the is_*? model methods, and you're
> done.
---
makes sense to me - thanks - y'all are learnin' me good  ;-)

Craig
Justin F. (Guest)
on 2006-03-22 02:28
(Received via mailing list)
Tom M. wrote:
>   1) It can provide data to other code in a way that will not change if
> column can contain 'M', 'C', or 'A', which represent MasterCard, Visa, and
>   def is_visa?
>     return "MasterCard"    if card.is_mastercard?
> This gives you a great deal of isolation, and some useful
> methods on the model that make the helper and (no doubt)
> other code more readable, and allows for a complete
> refactor of Card.type in the future without changing
> anything else.
>
> For instance, why store card type at all when it can be
> derived from the card number itself? If you've written it
> this way, you can drop the column, add the card number
> differentiation logic to the is_*? model methods, and you're
> done.

Excellent example.

Coming back to Craig's implementation:

- pltype field values are not abstracted away from the
   presented form (e.g. "16 Hour")

- the business logic corresponding to Craig's statement that

   "There are a number of other pltypes...it's just those
    particular 2 ["PAH", "16 Hour"] don't perform bed checks."

   is not implemented in the model, but is left to be implemented
   in the view.

So I think my most pressing question would be "Can you put a name to the
thing that is being displayed as either 'PAH', '16 Hour', or 'Bed
Check'?"

To put that another way, if this was being displayed in label: value
format, what would the label be? I'm sure it wouldn't be
'display_pltype'!

The answer to that question would tell us how to name a new method on
the model.

regards

   Justin
Justin F. (Guest)
on 2006-03-22 02:40
(Received via mailing list)
Craig W. wrote:
> On Tue, 2006-03-21 at 07:50 +0000, Justin F. wrote:
>> Craig W. wrote:

>>> The next phase is to clean up all of the sloppy code that I did to get
>>> this far...as I have seen that using some of these types of ruby
>>> snippets are really effective and I've got a lot of 'WET' ( WET != DRY )
>>> type code in my controllers but I didn't want to get bogged down with
>>> the higher quality usage of things I wasn't on top of - especially when
>>> I started with this 6 weeks ago (the first two controllers/models that I
>>> did are probably dripping WET).

> time...I assumed that I would catch on along the way and I sort of
> catching on.

I didn't mean to sound critical - sorry if it came over that way.

>>    end
>>
>>    <%= facility.display_pltype %>
>>
>> ...but this raises the question you ask below:
> ----
> well - I should state that I was a little afraid of using
> 'facility.display_pltype' directly since we are directly within an
> iteration with a hash named 'facility' and this could be a bit
> confusing.

OK. If facility is a hash, then you would need to get the pltype using
facility['pltype'] (or facility[:pltype], if you prefer to use symbols
for hash keys).

This is a good illustration of how you gain flexibility by having your
view work directly against your models, rather than pulling the
information out of the models into hashes and giving those to the views.

(By the way, what does 'pltype' stand for?)

regards

   Justin
Craig W. (Guest)
on 2006-03-22 08:15
(Received via mailing list)
On Wed, 2006-03-22 at 00:40 +0000, Justin F. wrote:

> >>    end
> OK. If facility is a hash, then you would need to get the pltype using
> facility['pltype'] (or facility[:pltype], if you prefer to use symbols
> for hash keys).
>
> This is a good illustration of how you gain flexibility by having your
> view work directly against your models, rather than pulling the
> information out of the models into hashes and giving those to the views.
>
> (By the way, what does 'pltype' stand for?)
----
pltype has sort of morphed. The 'type' originally started in the
placement as it was inadequately described to me as being a property of
the placement - turns out, it is not really a property of the placement
but of the facility. 'pltype' stood for the type of program - this is a
place for partially and SMI's and the programs would be like
'PAH/Asissted Housing, or 24 Hour, etc.  The 'pl' came from the
misunderstanding that I had thinking it related to the 'placement' and
'type' is really the better term but as I came to discover, it was a
reserved word. So the whole nature of 'pltype' has roots in issues ;-)
Basically, it is about the type of care level that is provided.

Thanks

Craig
Craig W. (Guest)
on 2006-03-22 08:20
(Received via mailing list)
On Wed, 2006-03-22 at 00:28 +0000, Justin F. wrote:
> >
> > As an example: Imagine we have a model that has a column, :type, and that
> >
> >   def card_name_for(card)
> >
> > done.
>    "There are a number of other pltypes...it's just those
>
> The answer to that question would tell us how to name a new method on
> the model.
----
I think it is borderline but whether it gets any usage beyond this one
form would strike me as the reason to put it into a model or just leave
it in the view. The 'pltype' is for categorization for the governmental
agencies whereas the form itself, is simply a 'worksheet' for the staff
to report the daily log. Thus the point is the 'assisted living' type
clients wouldn't get a bed check and they don't want the implication on
the form itself that a bed check is expected or proper for that
particular facility.

Craig
Seth R. (Guest)
on 2006-03-22 09:14
(Received via mailing list)
On 3/20/06, Craig W. <removed_email_address@domain.invalid> wrote:
> I am quite certain I have heard it said not to put business logic inside
> view code but I have a report that I want to display 3 different
> possibilities of text based upon the value of a column. Would I just
> take the same type of if/then logic that I would use in a controller and
> put it inside erb <%= %> stuff?

So far I have been generally able to limit view templates to if-else
and iterating over collections occasionally with each().

The latter can of course often be awesomely addressed using render()
with the :collection option.

It's sensible if you're going to bother with MVC to really strive to
keep your templates as dumb as possible, it seems. Things are much
more pleasant to deal with.

Exceptions always occur, though, so use your best judgement. :)

--
Seth Thomas R.
http://sethrasmussen.com/
This topic is locked and can not be replied to.