Rendering a counter in the view. What's the proper way?

Hello there ppl.

I want to have a counter which will:

  • count the number of times that the ‘index’ controller action is
    called
    and store this in a cookie
  • will be displayed in the view only if the times visited is greater
    than 5
  • it must look like this: “You have visited this page 1 time” or “You
    have visited this page 2 times” (I know I can use the pluralize()
    method
    for that)

We always say that the views must know as little as possible regarding
the
logic & data of our apps, so I guess the ideal way is to just render it
through a <%= @counter %> piece of code. Right until here? I proceed,

in my ApplicationController I’ve added these methods regarding the
counter:

def increment_counter

if @times_visited > 5
  @counter = "You have visited this page " + pluralize(@times_visited,

" times")
end
end

The last method is what I’m interested in right now. It gives me a
*undefined
method `pluralize’ for #StoreController:0x007fdbab23c9c0 *error cause
I’m
trying to access a helper from a controller and not from a view. Correct
me
if I’m wrong.

So I could hard-code the IF statement into the view but this would break
the rules of MVC architecture, right? So what would be the best way to
do
this?

On 17 January 2012 16:24, Agis A. [email protected] wrote:

end
end

The last method is what I’m interested in right now. It gives me a undefined
method `pluralize’ for #StoreController:0x007fdbab23c9c0 error cause I’m
trying to access a helper from a controller and not from a view. Correct me
if I’m wrong.

So I could hard-code the IF statement into the view but this would break the
rules of MVC architecture, right? So what would be the best way to do this?

Where are you calling display_counter from? I would have expected it
to be from the view, in which case put the method display_counter in a
view helper not in the controller. Pass it the value @times_visited.
So in the view:
<%= display_counter @times_visited %>

Colin

No I’m calling it from the controller, should I call it from the view?
If I
try to call it from the view like this: counter_display I get

undefined local variable or method `show_counter’ for
#<#Class:0x007fdbab80c7b0:0x007fdbab813f10>

I’ve done it as you said, in the helper. So this is how it should be
done?
Is there a general rule for deciding whether a function like this should
go
into the controller or into the helper?

My code in the helper:

def display_counter

"You have visited this page " + pluralize(@times_visited, " time") if

@times_visited > 5
end

and then calling that function in the view. Would it be better if this
wasn’t a function but a simple variable like this?
@counter = “You have visited this page " + pluralize(@times_visited, "
time”) if @times_visited > 5

Thanks a bunch for your help so far!

On Jan 17, 2012, at 11:55 AM, Agis A. wrote:

I’ve done it as you said, in the helper. So this is how it should be done? Is
there a general rule for deciding whether a function like this should go into the
controller or into the helper?

My code in the helper:

def display_counter
“You have visited this page " + pluralize(@times_visited, " time”) if
@times_visited > 5
end

Try this:

def display_counter(times, limit = 5)
“You have visited this page #{pluralize(times,‘time’)}” if times >
limit
end

in the view:

<%= display_counter @times_visited %>

and then calling that function in the view. Would it be better if this wasn’t a
function but a simple variable like this?
@counter = “You have visited this page " + pluralize(@times_visited, " time”) if
@times_visited > 5

It depends on where you want to go to edit this code. It generates HTML,
so it (fairly categorically) should not be in the controller.

Walter

On 17 January 2012 16:38, Agis A. [email protected] wrote:

No I’m calling it from the controller, should I call it from the view? If I
try to call it from the view like this: counter_display I get

Please don’t top post, insert your reply into the previous message at
appropriate points. As you have done it here no-one reading this
knows what question you are answer “no” to. Thanks.

undefined local variable or method `show_counter’ for
#<#Class:0x007fdbab80c7b0:0x007fdbab813f10>

There seems to be some confusion over what the method is called. In
your original post you called it display_counter, above you have
called it counter_display, but the error message appears to be for
show_counter. Whatever you call it you have not noted my other point,
that it should be in a view helper not in the controller. In
addition, which I did not say, being a view helper it should return
the string to be displayed directly, so something like
def display_counter( visits )
“You have visited this page " + pluralize(@visits, " times”) if visits

5
end

Put it in application_helper.rb (not application_controller) if you
need it from views for multiple controllers, or the appropriate view
helper file if just for one controller.

Read up on view helpers if you need to.

Colin

This makes sense. But on the other side, if I put this method in the
helper
(as I did) then I’m embedding business login in the helper (if > 5), am
I
not?

It’s more a logical question. Is the “if visits are more than 5 display
the counter”
business logic or not? Which part of the framework should
be
responsible for deciding if to render the counter?

Well I did something like this now, just in order to let the controller
decide with how many visits the counter will appear.
*
*
Controller:

def increment_counter
session[:counter] ||= 0
session[:counter] += 1
@times_visited = session[:counter]
@min_times = 5
end

Helper:

  • *def display_counter
    “You have visited this page " + pluralize(@times_visited, " time”) if
    @times_visited > @min_times
    end

then on the view I just use <%= display_counter %>. Isn’t that better
than
before? Now the @min_times is defined in the controller, isn’t that the
best place for it to be decided? I guess I should write it in another
method like *counter_settings *but for now it’s ok I think.

On 17 January 2012 18:19, Agis A. [email protected] wrote:

end
then on the view I just use <%= display_counter %>. Isn’t that better than
before? Now the @min_times is defined in the controller, isn’t that the best
place for it to be decided? I guess I should write it in another method like
counter_settings but for now it’s ok I think.

I am not sure that is business logic. If it were it should be in a
model not the controller. Is it not the specification of the human
interface? There are always grey areas however, the real world does
not conform to the MVC concept so there will always be judgments to be
made. As long as the basic structure is ok then small details do not
really matter. Go with whatever you are most comfortable with.

Colin

On 17 January 2012 16:55, Agis A. [email protected] wrote:

and then calling that function in the view. Would it be better if this
wasn’t a function but a simple variable like this?
@counter =“You have visited this page " + pluralize(@times_visited, "
time”) if @times_visited > 5

I presume you mean to put this code in the controller. That is not
desirable because then you are formatting data for display in the
controller. The controller should make the data available to the view
(@times_visited in this case) and then the view decides how to format
it. So in answer to your question about a general rule the controller
makes the raw data available, the view formats it.

Colin