user10511957
user10511957

Reputation:

Rails - Retrieving Instance variable

I have the followings:

routes.rb

Rails.application.routes.draw do
  devise_for :users

  resource :user, only: [] do
    # this will route /user/bookings to Users::BookingsController
    resources :bookings, only: [:index], module: :users
  end

  resources :spaces, only: [:index, :new, :create, :show] do
    # shallow: true will prevent the member routes from being nested
    # it will also prevent resources :payments from being nested in `/spaces/`
    resources :bookings, shallow: true do
       resources :payments, only: :new, shallow: true
    end
  end


  root to: 'pages#home'
  get 'about', to: 'pages#about'
  get 'bookings/:id/payments/success', to: 'payments#success', as: :success

  mount StripeEvent::Engine, at: '/stripe-webhooks'
end

payments_controller.rb

class PaymentsController < ApplicationController
  def new
    @booking = current_user.bookings.find(params[:booking_id])

    @days = 1 + (@booking.check_out - @booking.check_in).to_i
    @service_fee = @booking.space.price * @days * 0.15
    @total_price = (@booking.space.price * @days) + @service_fee
  end

  def success
    @booking = current_user.bookings.find(params[:id])
  end
end

I am wondering why in #new I have to retrieve @booking using params[:booking_id] instead of params[:id].

Upvotes: 0

Views: 40

Answers (1)

Siim Liiser
Siim Liiser

Reputation: 4348

The resource you defined in the routes is payments, the controller is called PaymentsController, following standard patterns, the value in params[:id] should be the id of the payment, not the id of the booking.

In member actions (actions that deal with a single existing payment instance like show, edit, update and destroy), the id will be present in params.

In collection actions (actions that deal with the concept of payments, but not any specific existing one like index, new and create), there is no id since there is no payment.

Because you nested your payment routes under booking routes, collection actions will have access to booking_id.

To follow patters given by rails, the route you defined should be

get 'bookings/:booking_id/payments/success', to: 'payments#success', as: :success

or better yet put it where it belongs

resources :spaces, only: [:index, :new, :create, :show] do
  resources :bookings, shallow: true do
     resources :payments, only: :new, shallow: true do
       collection do
         get :success
       end
     end
  end
end

In either of those cases, the booking id will be available as params[:booking_id]

As for the 2nd question. All requests are completely independent from each other. Every time a request comes in to your controller, all information about previous ones is lost. If you would call new from success (not that I'm suggesting you do that) they would be available. But for the current case, they're not available because they haven't been set in the current request.

If you want to pass information between requests, you need to send them in as parameters.

Upvotes: 1

Related Questions