user139078
user139078

Reputation: 411

Does accessing the database in views via view-models or view-helpers break the MVC paradigm?

I believe all of the following break the MVC paradigm but wanted to double check if this was the case. In all cases the view is directly accessing data rather than having the data being passed in. From my understanding of MVC, it should never do that. The controller should get all the data that is necessary to render the view as to not couple the view and model directly. Is my understanding correct?

  1. Accessing the database through a view helper

    # in app/helpers/view_helper.hrb
    def some_view_helper(person_id)
      @person = Person.find(person_id)
    end
    
  2. Accessing another web server through a view helper

    # in app/helpers/view_helper.hrb
    def another_view_helper(person_id)
      # makes http request over the wire to get json back
      @json = WebService.get_person(person_id)
    end
    
  3. Accessing the database through a view model

    # in apps/controller/person_controller.rb
    def show
      @person = Person.find(params[:id])
      @page_model = PageModel.new(@person)
    end
    
    #in app/views/persons/show.html.erb
    <% @page_model.friends.each do |friend| %>
      ...
    <% end %>
    
    #in app/models/person.rb
    class Person < ActiveRecord::Base
      has_many :friends
    end
    
    #in app/models/page_models/page_model.rb
    def initialize(person)
      @person = person
    end
    
    def friends
      @person.friends
    end
    
  4. Accessing web server to get data through a view model

    # in apps/controller/person_controller.rb
    def show
      @person = Person.find(params[:id])
      @page_model = PageModel.new(@person)
    end
    
    #in app/views/persons/show.html.erb
    <% @page_model.friends.each do |friend| %>
       ...
    <% end %>
    
    #in app/models/page_models/page_model.rb
    def initialize(person)
      @person = person
    end
    
    def friends
      WebService.get_friends_for_person(person_id)
    end
    

Upvotes: 1

Views: 1272

Answers (1)

rkb
rkb

Reputation: 3542

For 1 and 2, you could just set an instance variable (@person) in the controller.

For 3, your view code isn't so bad, but why have a separate page model? You can also load the friends up front in the controller:

# in apps/controller/person_controller.rb
def show
  @person = Person.find(params[:id], :include => :friends)
  @friends = @person.friends
end

Example 4 is a bit worse, since you're doing external web service calls in a view. Don't do that.

This article has a good example of what an ideal clean view would look like: http://warpspire.com/posts/mustache-style-erb/

Upvotes: 1

Related Questions