kel.o
kel.o

Reputation: 139

Render a partial that uses helper methods to determine view

What Currently Works:

In my BookingsController#Index method, I have this

def index
    @user = current_user
    if @user.user_type == 'host'
      @bookings = Booking.where(host_id:@user.id, status: "#{params[:status]}")
    else @user.user_type == 'cleaner'
      @bookings = Booking.where(cleaner_id:@user.id, status: "#{params[:status]}")
    end
  end

This sets the current user and determines which @bookings to display depending on the user_id and params.

In the views, in my index.html.erb file, I render bookings <%= render @bookings %> which i defined in the booking#index. I have a _booking.html.erb partial that gets rendered... Inside the _booking.html.erb partial, I am able to successfully return booking details , like this for instance,

<div id='booking-time'><b>Unit Name:</b> <%= booking.unit.name %></div>

will return the unit name. it recognizes the local variable booking and the fields that belong to it.

I'd Like to Refactor:

I want to refactor this and render a partial <%= render 'bookings/booking' %> in my index.html.erb file. This partial will render different helper methods that each route to different partials.

Currently my _booking.html.erb file has a bunch of conditional logic that is better suited for a helper... I've tried a bunch of different ways to accomplish this to no avail, usually due to undefined variables..what's an elegant way to accomplish this?

What I've Tried:

Here's a method from my bookings_helper.rb` file:

  def incoming_to_cleaner_partial_path(bookings)
    return unless booking.status=='pending' && current_user.user_type =='cleaner' && booking.requested_by_id != current_user.id
      'bookings/booking_requests/incoming_to_cleaner'
  end

I added logic to these methods to determine which partials to render.

in my modified _booking.html.erb file, I call these methods, I pass them a @bookings instance variable param.

<%= render incoming_to_cleaner_partial_path(@bookings) %>

I've also tried this without params.. Neither work..

lastly, I've tried calling a method determine_bookings_to_show inside the helper methods. This method contains the same logic from the controller...

def incoming_to_cleaner_partial_path
    determine_bookings_to_show
    return unless booking.status=='pending' && current_user.user_type =='cleaner' && booking.requested_by_id != current_user.id
      'bookings/booking_requests/incoming_to_cleaner'
  end

private

def determine_bookings_to_show
    @user = current_user
    if @user.user_type == 'host'
      @bookings = Booking.where(host_id:@user.id, status: "#{params[:status]}")
    else @user.user_type == 'cleaner'
      @bookings = Booking.where(cleaner_id:@user.id, status: "#{params[:status]}")
    end
  end

My main issue is i'm having scope troubles with these partials...

Upvotes: 1

Views: 995

Answers (1)

Jared Beck
Jared Beck

Reputation: 17528

.. in my index [I want to] render different partials [depending on attributes of the booking] ..

I have used render(locals:) for this in the past.

# index.html.erb
@bookings.each do |b|
  render_booking(b)
end

# bookings_helper.rb
def render_booking(booking)
  if booking.status == 'pending'
    render partial: 'path/to/bookings/_pending', locals: { booking: booking }
  elsif booking.foobar?
    render partial: 'path/to/bookings/_foobar', locals: { booking: booking }
  else
    # etc.
  end
end

Conditionals like this can get complicated, but until then, I think this is an appropriate, practical use of a helper method.

# bookings/_pending.html.erb
<h1>Pending Booking <%= booking.id %></h1>

You will likely need to pass other locals:. I'd avoid using any instance variables in your partials.

Upvotes: 1

Related Questions