views:

209

answers:

1

I have in my model:

def presenter
   @presenter ||= ProfilePresenter.new(self)
   @presenter
end

The ProfilePresenter is a class that has methods like, get_link(), get_img_url(size), get_sex(), get_relationship_status() and other methods that have not to do with the model, not even with the controller but is used multiple times in the view.

So now i use them by doing this:

Profile.presenter.get_link
# or
Profile.presenter.get_img_url('thumb') # returns the path of the image. is not used to make a db query

Sincerelly i think i missed out the real concept of presenters.. but this is what m trying to archive, how can be called this?

+5  A: 

Normally this sort of thing is handled via helper methods, such as:

def profile_link(profile)
  profile.link ? content_tag(:a, h(profile.name), :href => profile.link) : 'No profile'
end

It is unfortunate you cannot layer in Presenter-style helper methods that extend a Model at view time. They need to be called in a procedural manner with a parameter, kind of anti-OO.

The Presenter approach is not fully supported in the Rails MVC area because it needs to bind to a view in order to have access to the various helper methods required to properly render content, plus information about the session that may impact the presentation.

A more robust approach might be to do something like this:

class ProfilePresenter
  def initialize(view, profile)
    @profile = profile
    @view = view

    yield(self) if (block_given?)
  end

  def link
    @profile.link ? @view.content_tag(:a, @view.h(profile.name), :href => @profile.link) : 'No profile'
  end

  def method_missing(*args)
    @profile.send(*args)
  end
end

This would show up in your view as something like:

<% ProfilePresenter.new(self, @profile) do |profile| %>
<div><%= profile.link %>
<% end %>

You can simplify calling this by making a helper method that does something mildly crazy like:

def presenter_for(model)
  "#{model.class}Presenter".constantize.new(self, model) do |presenter|
    yield(presenter) if (block_given?)
  end
end

This means you have a much simpler call:

<% presenter_for(@profile) do |profile| %>
<div><%= profile.link %>
<% end %>
tadman
This is a very nice approach. Clean. Are you using something like this now?
nathanvda
Is not easier to just use: "@profile.presenter.get_url" and it's ready to go? or it might be more compressed like: "@profile.pr.get_url". That because i dont use so much just in loops but other things so the use would be: "presenter_for(@profile).get_url"
Totty
@nathanvda I've used approaches like this with wrappers before, though even they didn't follow the Presenter pattern as closely. This is a technique for bridging the Model and View worlds.
tadman
Well, in silverlight you would use MVVP; and up until now i didn't see a real need to use a Presenter. But using a solution like this instead of helpers could be much cleaner. Feels more OO indeed. Very nice.
nathanvda