baron816
baron816

Reputation: 701

Rails 4 Passing instance variables to view OOP

I've been looking at the Rails-style-guide and it says that I should not share more than two instance variables from my controller with the view. I've been sharing a lot more than two instance variables with my view because

  1. I need to create new instances for partials, and
  2. I don't want long chained method calls in my views.

For example, I have a Group show view, which passes in @group, @users (which is all the users in the group), @notifications (the notifications for the user that are available everywhere in a dropdown), @activities, @messages (for the message board), and @message (the new message that can be generated.

That way my view looks like this:

<% @activities.each do |activity| %>

Should I instead just pass @group (eager loading it's users, messages, etc) and have calls in my view that look like this?:

<% @group.activities.future_activites.each do |activity| %> ...

Thanks.

Upvotes: 0

Views: 407

Answers (1)

Unixmonkey
Unixmonkey

Reputation: 18784

Here's a great technique for reducing the number of objects you make available from your controller to your view:

https://robots.thoughtbot.com/sandi-metz-rules-for-developers#only-instantiate-one-object-in-the-controller

Long story short, try to create a class or object that has methods to encapsulate the information you want to share.

From your example, I could see doing something like this:

app/facades/group_show.rb

class GroupShow
  attr_reader :group

  def initialize(group)
    self.group = group
  end

  def future_activities
    group.activities.future_activities
  end
end

app/controllers/groups_controller.rb

def show
  group = Group.find(params[:id])
  @facade = GroupShow.new(group)
end

app/views/groups/show.html.erb

<% @facade.future_activities.each do |activity| %>

Or, for a simpler version of this (especially since activities are already part of your @group object, you can add a delegate method directly to your group model like this:

app/models/group.rb

def future_activities
  activities.future_activities
end

And access like this:

app/views/groups/show.html.erb

<% @group.future_activities.each do |activity| %>

Upvotes: 1

Related Questions