Joshua
Joshua

Reputation: 371

Checking whether a user owns incoming and outgoing service booking requests

Use case: A user creates a service and can have many services. A user can book the service of another user through a servicebooking. A user can accept/decline the booking for their service from another user.

I am trying to display the outgoing service bookings made by the current user for another users services by checking a servicebookings model and also check/display the incoming bookings made by other users for the current users services on a myservicebookings page.

Myservicebookings view is as follows:

<h1>My Service bookings</h1>
<% if @owns_s %>
<table>
  <tr>
    <th><%= sortable "date" %></th>
    <th><%= sortable "time" %></th>
    <th><%= sortable "service name" %></th>
  </tr>

  <h4>Incoming requests:</h4>

  <% @servicebookings.each do |servicebooking| %>
    <tr>
      <td><%= servicebooking.date %></td>
      <td><%= servicebooking.time %></td>
      <td><%= servicebooking.service_name %></td>
      <td><%= link_to "View this booking", servicebooking_path(servicebooking) %></td>
    </tr>
  <% end %>
</table>

<%else%>
<%= "You have no incoming service booking requests"%>
<%end%>

<% if @owns_sb %>
<table>
  <tr>
    <th><%= sortable "date" %></th>
    <th><%= sortable "time" %></th>
    <th><%= sortable "service name" %></th>
  </tr>

  <h4>Outgoing requests:</h4>

  <% @servicebookings.each do |servicebooking| %>
    <tr>
      <td><%= servicebooking.date %></td>
      <td><%= servicebooking.time %></td>
      <td><%= servicebooking.service_name %></td>
      <td><%= link_to "View this booking", servicebooking_path(servicebooking) %></td>
    </tr>
  <% end %>
</table>
<%else%>
<%= "You have made no outgoing service booking requests"%>
<%end%>
<%= will_paginate @servicebookings %>
<%= link_to "Homepage", :controller => "welcome", :action => "index" %>

In my servicebookings controller I have the following to check whether a user owns a service or a servicebooking, currently it just returns all the services and servicebookings instead of displaying only the services created by the current user that another user has booking(incoming requests) and instead of displaying the services booked by the current user(outgoing requests). Can anyone give some tips here?? Thanks in advance guys, much appreciated.

def myservicebookings
    @servicebookings = current_user.servicebookings.includes(:user).search(params[:search]).order(sort_column + " " + sort_direction).paginate(:per_page => 4, :page => params[:page])

    owns_servicebooking = current_user.servicebookings.detect do |sb| 
        sb.user == current_user 
    end
    owns_service = current_user.services.detect do |s| 
        s.user == current_user 
    end

    @owns_sb = owns_servicebooking
    @owns_s = owns_service

  end

Servicebooking model:

class Servicebooking < ActiveRecord::Base
  attr_accessible :service_id, :date, :time, :user_id, :service_name, :accept_booking
  belongs_to :user
  belongs_to :service

  def self.search(search)
  if search
    where('name LIKE ?', "%#{search}%")
  else
    scoped
  end
end
end

Services model:

class Service < ActiveRecord::Base
  attr_accessible :avatar, :avatar2, :avatar3, :avatar4, :name, :date_available, :time_available, :description, :price, :size, :company_name, :company_details
  has_attached_file :avatar, :default_url => "/images/:style/missing.png"
  has_attached_file :avatar2, :default_url => "/images/:style/missing.png"
  has_attached_file :avatar3, :default_url => "/images/:style/missing.png"
  has_attached_file :avatar4, :default_url => "/images/:style/missing.png"
  belongs_to :user
  belongs_to :event
  has_many :comments, dependent: :destroy
  has_many :servicebookings


  def self.search(search)
  if search
    where('name LIKE ?', "%#{search}%")
  else
    scoped
  end
end
end

Upvotes: 1

Views: 203

Answers (1)

Richard Peck
Richard Peck

Reputation: 76774

has_many :through

I think you'll benefit from the has_many :through association

Your ServiceBooking model seems to be a join model, which needs to reference booking_id and service_id

The way you've got the system set up currently is to pull directly from this model. I think you'll be better to use it in conjunction with your other models. You'll literally just have to adapt your code slightly to affect this change:

#app/models/Service.rb
Class Service < ActiveRecord::Base
    belongs_to :user

    has_many :service_bookings
    has_many :bookings, :through => :service_bookings
end

#app/models/Booking.rb
Class Booking < ActiveRecord::Base
    belongs_to :user

    has_many :service_bookings
    has_many :services, :through => :service_bookings
end

#app/models/ServiceBooking.rb
Class Service < ActiveRecord::Base
    belongs_to :service
    belongs_to :booking
end

This will allow you to pull the actual data from the relative models, rather than just relying on the ServiceBooking model

The beauty of this is that because you can add extra attributes to join models in Rails, you'll be able to include other fields, such as user_id, inbound and outbound


Your Code

I'd do it like this:

#config/routes.rb
resources :users do 
    resources :bookings
    resources :services
end

#app/controllers/users_controller.rb
def index
    user = User.find(params[:id])
    @bookings = user.bookings
    @services = user.services
end 

#app/controllers/bookings_controller.rb
def index
    user = User.find(params[:user_id])
    @bookings = user.bookings
end

#app/controllers/services_controller.rb
def index
    user = User.find(params[:user_id])
    @services = user.services
end

This will allow you to display the actual bookings / services for each user (all the services / bookings on the user index page; all relative records on bookings and services index actions)


Validation

If you follow these ideas, validation becomes somewhat more methodical

You can either use a before_create function on your ServiceBooking model (to check if the object matches the user_id), or you could perform some controller-based validation to see if the user_id is consistent

I should also mention that checking ownership of booking or service moves to the other models with this (I.E service belongs_to :user)

Upvotes: 1

Related Questions