First, I want to thank everyone at SO. I've been getting a lot of help from you guys the last couple days and it's much appreciated!
I have another problem on my hands:
Background/Goal:
I have a Tour, Day, and Reservation model. In my Tour controller, I can create a tour and manually enter in days that the tour is available on. I then want to access each tours reservation page (tours/1/reservation/new) and display the tour information along with the tour designated days.
My question are:
1) What do I need to put in my reservations controller and view in order for me to access each tours designated days in a select tag?
2) Is there a Rails way to turn the inputted days of the week into a dynamic form where it displays the designated day and their dates?
For an example: Tour #1 is available on Mondays and Tuesdays (every week) (these are manually entered in days when I create the tour). How can I turn those days into a dynamic form where Rails displays the date of every Monday and Tuesday in each month? (I will probably post another question for this, just wondering since it's somewhat related.)
Deep explanations are always appreciated, as I'm a bit clueless. :( Thank you again!
UPDATE:
The days of each tour are NOT being displayed on the reservations page IF they're in a form_helper or even something as simple as me applying a bootstrap dropdown-menu class to the surrounding element.
This works: (shows days)
<ul>
<% @tour.days.all.each do |day| %>
<li>
<%= day.name %>
</li>
<% end %>
</ul>
This DOES NOT:
<ul class='dropdown-menu'>
<% @tour.days.all.each do |day| %>
<li>
<%= day.name %>
</li>
<% end %>
</ul>
NOR this:
<% @tour.days.each do |day| %>
<%= f.fields_for :day do |builder| %>
<%= builder.label :id, 'Days available:' %><br />
<%= builder.select :id, options_from_collection_for_select(day, 'id', 'name') %>
<% end %>
<% end %>
I'm completely stumped.
Models:
class Tour < ActiveRecord::Base
has_many :days, dependent: :destroy
has_many :reservations
accepts_nested_attributes_for :days, allow_destroy: true, :reject_if => lambda { |a| a[:name].blank? }, :allow_destroy => true
end
class Reservation < ActiveRecord::Base
belongs_to :tour
belongs_to :day
accepts_nested_attributes_for :days, allow_destroy: true, :reject_if => lambda { |a| a[:name].blank? }, :allow_destroy => true
end
class Day < ActiveRecord::Base
belongs_to :tour
has_many :reservations, dependent: :destroy
accepts_nested_attributes_for :reservations, allow_destroy: true, :reject_if => lambda { |a| a[:name].blank? }, :allow_destroy => true
end
Migrations:
class CreateTours < ActiveRecord::Migration
def change
create_table :tours do |t|
t.string :name
t.integer :amount
t.timestamps
end
end
end
class CreateDays < ActiveRecord::Migration
def change
create_table :days do |t|
t.string :name
t.integer :tour_id
t.timestamps
end
end
end
class CreateReservations < ActiveRecord::Migration
def change
create_table :reservations do |t|
t.integer :passengers
t.integer :tour_id
t.integer :day_id
t.timestamps
end
end
end
Views:
TOUR
<div class="container">
<div class="row">
<div class="col-md-12">
<h2>Add a new tour</h2>
<%= bootstrap_form_for(@tour) do |f| %>
<%= f.text_field :name %>
<%= f.fields_for :days do |builder| %>
<%= builder.label :name, 'Days of Tour:' %>
<%= builder.text_field :name, label: 'Days of Tour:' %>
<%= builder.check_box :_destroy %>
<%= builder.label :_destroy, 'Remove day' %>
<% end %>
<%= f.text_field :amount %>
<%= f.text_field :time %>
<%= f.submit 'Add this tour' %>
<% end %>
</div>
</div>
</div>
RESERVATION
</script>
<div class="container">
<div class="row">
<div class="col-md-9">
<h2>
<%= @tour.name %>
</h2>
</div>
<div class="col-md-3">
<p>
<%= @tour.amount %>
</p>
<%= 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.fields_for :days do |builder| %>
<%= builder.label :name, 'Days available:' %><br />
<%= builder.text_field :name %>
<% end %>
<fieldset class="credit_card">
<span class="payment-errors"></span>
</fieldset>
<div class="control-group">
<%= label_tag :card_number, 'Credit card number:', class: 'control-label' %>
<div class="controls">
<%= text_field_tag :card_number, nil, name: nil, class: 'span3', data: {stripe: 'number'} %>
</div>
</div>
<div class="control-group">
<%= label_tag :security_code, 'Security code:', class: 'control-label' %>
<div class="controls">
<%= text_field_tag :security_code, nil, name: nil, class: 'span3', data: {stripe: 'cvc'} %>
</div>
</div>
<div class="control-group">
<%= label_tag :exp_date, 'Expiration:', class: 'control-label' %>
<div class="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'}) %>
</div>
</div>
<fieldset class="actions control-group">
<div class="controls">
<%= f.submit 'Sign up' %>
</div>
</fieldset>
<% end %>
</div>
</div>
</div>
Controllers:
class ReservationsController < ApplicationController
def index
end
def new
@reservation = Reservation.new
@tour = Tour.find(params[:tour_id])
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(:date, :passengers, days_attributes: [:id, :name, :_destroy])
end end
class ToursController < ApplicationController
def index
@tours = Tour.all
end
def new
@tour = Tour.new
7.times { @tour.days.build }
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_attributes: [:id, :name, :_destroy])
end
end
Routes:
Rails.application.routes.draw do
resources :tours do
resources :reservations
end
end
reservations_params, add this code::day_ids => []. I'm guessing this is why the association is not binding you select the days