0

I apologize that this is such a simplistic question, but I've been struggling with it for a while.

I have two related models - Tour & Reservation. "Tour" has a "days" attribute. I want to list the days in a select tag for the user to choose from in my "Reservation" view

I thought this might work:
(Reservations controller) @tour_days = Tour.where(:days => params[:days])

(Reservations #new) = f.select :days, @tours_days

However, I'm receiving the error undefined methoddays'
`

class Reservation < ActiveRecord::Base
  belongs_to :tour
end

class Tour < ActiveRecord::Base
  has_many :reservations
end

.

class ReservationsController < ApplicationController

 def index
  end

  def new
    @reservation = Reservation.new
    @tour = Tour.find(params[:tour_id])
    @tour_days = Tour.where(:days => params[:days])
  end

  def create
    @tour = Tour.find(params[:tour_id])

    if @reservation.update_attribute(:t_shirt, params[:t_shirt]) == true || @reservation.update_attribute(:hat, params[:hat]) == true
       @tour.amount = @tour.amount + 15
    else
       @tour.amount = @tour.amount
    end

    @reservation = Reservation.new(reservation_params)

    if @reservation.save
      Stripe.api_key = ENV["STRIPE_SECRET_KEY"]
      Stripe::Charge.create(
        :amount => @tour.amount, # amount in cents, again
        :currency => "usd",
        :card => params[:stripeToken]
      )
      flash[:success] = "Your reservation has been booked for #{@reservation.passengers} person(s). Please save this info."
      redirect_to new_tour_reservation_path(@tour)
    else
      render 'new'
    end
  end

  private

  def reservation_params
    params.require(:reservation).permit(:passengers, :t_shirt, :hat)
  end
end

.

class ToursController < ApplicationController
  def index
    @tours = Tour.all
  end

  def new
    @tour = Tour.new
  end

  def create
    @tour = Tour.new(tours_params)
    if @tour.save
      flash[:success] = "Tour #{@tour.name} has been successfully added."
      redirect_to new_tour_path
    else
      flash[:error] = "The tour #{@tour.name} was not successfully saved. Please try again"
      render 'new'
    end
  end

  def show
    @tour = Tour.find_by(id: params[:id])
    @reservation = Reservation.new
  end

  def edit
    @tour = Tour.find_by(id: params[:id])
  end

  def update
    @tour = Tour.find_by(id: params[:id])
    if @tour.update_attributes(tours_params)
      flash[:success] = "#{@tour.name} has been successfully updated."
      redirect_to tours_path
    else
      flash[:error] = "#{@tour.name} has not been updated. Please try again."
      render 'edit'
    end
  end

  def delete
    @tour = Tour.find_by(id: params[:id])
  end

  def destroy
    @tour = Tour.find_by(id: params[:id])
    if @tour.destroy
      flash[:success] = "The #{@tour.name} has been successfully deleted."
      redirect_to tours_path
    else

  flash[:error] = "The #{@tour.name} has not been deleted. Please try again."
      render 'edit'
    end
  end

  private

  def tours_params
    params.require(:tour).permit(:name, :amount, :days)
  end
end

.

= bootstrap_form_for([:tour, @reservation], html: { class: 'form-horizontal', id: 'payment-form'}) do |f|
    = f.alert_message 'Please fix the errors below:'
    = f.select :passengers, options_for_select( (1..10).map { |n| n %1 == 0 ? n.to_i : n } )
    = f.select :days, @tours_days
    %fieldset.credit_card
      %span.payment-errors
    .control-group
      = label_tag :card_number, 'Credit card number:', class: 'control-label'
      .controls
        = text_field_tag :card_number, nil, name: nil, class: 'span3', data: {stripe: 'number'}
    .control-group
      = label_tag :security_code, 'Security code:', class: 'control-label'
      .controls
        = text_field_tag :security_code, nil, name: nil, class: 'span3', data: {stripe: 'cvc'}
    .control-group
      = label_tag :exp_date, 'Expiration:', class: 'control-label'
      .controls
        = select_month(Date.today, {add_month_numbers: true},  class: 'span2', data: {stripe: 'exp-month'})
        = select_year(Date.today.year, {start_year: Date.today.year, end_year: Date.today.year + 4}, class: 'span1', data: {stripe: 'exp-year'})
    %fieldset.actions.control-group
      .controls
        = f.submit 'Sign up'
1
  • is this the reservations view? if it is I dont' u can call the days attribute here since it belongs to the tour model Commented May 16, 2014 at 3:35

1 Answer 1

2

consider using accepts_nested_attributes_for

Create another model to encapsulate the days. Then associate it with the Reservation model.

class Reservation < ActiveRecord::Base
  belongs_to :tour
  has_and_belongs_to_many :days
  accepts_nested_attributes_for :days, allow_destroy: true
end

class Day < ActiveRecord::Base
  has_and_belongs_to_many :reservations
end

The Day model will have one attribute: name which will hold the names of the seven days

class ReservationsController < ApplicationController
  def create 
    @reservation = Reservation.new(reservation_params)
    if @reservation.save
         redirect_to @save
    else
       render :new
    end
 end

  private

#add the `days_attributes` to the `reservations_params`

  def reservation_params
    params.require(:reservation).permit(:passengers, :t_shirt, :hat, days_attributes[:id, name])
  end
end

then in new.html.erb when you are creating reservations, you can get a drop down to select specific days. you can do something like:

f.select :days

if you opt to use nested_forms, you'd have to use boostrap_nested_form_for as the documentation suggests.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for your reply. I did end up using nested_attributes but without the HABTM association (as a reservation only belongs to one day). My goal is: Each tour is available on designated days(days are entered in when the tour is created). I want to display the days of each tour on its reservation page (tours/1/reservation/new, etc) I have created another question as this involves multiple models and multiple forms. stackoverflow.com/questions/23702601/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.