Search code examples
ruby-on-rails-4routesnested-resources

Forms, nested resources and routing errors Rails 4


Rails newbie here. I have created a basic website that tracks events during a shift. I have created the models and nested them. However, I do not understand the connections completely. When I create the nested event from a form linked to a shift I get the following error:

No route matches [POST] "/shifts/events" on url http://localhost:3000/shifts//events

should be http://localhost:3000/shifts/3/events/1 I think

_form.html.erb

<%= form_for shift_events_path(@shift) do |f| %>
<% if @event.errors.any? %>
<div id="error_explanation">
  <h2><%= pluralize(@event.errors.count, "error") %> prohibited </h2>

  <ul>
  <% @event.errors.full_messages.each do |msg| %>
    <li><%= msg %></li>
  <% end %>
  </ul>
</div>
<% end %>

<div class="field">
  <%= f.label :time_s %><br>
  <%= f.time_select :time_s %>
</div>
<div class="field">
  <%= f.label :time_f %><br>
  <%= f.time_select :time_f %>
</div>
<div class="field">
  <%= f.label :odometre %><br>
  <%= f.number_field :odometre %>
</div>
<div class="field">
  <%= f.label :location %><br>
  <%= f.text_field :location %>
</div>
<div class="field">
  <%= f.label :activity %><br>
  <%= f.text_field :activity %>
</div>
<div class="field">
  <%= f.label :description %><br>
  <%= f.text_area :description, rows: 4 %>
</div>
<div class="actions">
  <%= f.submit %>
</div>
<% end %>

roots.rb

resources :shifts do
  resources :events#, 
end

events_controller.eb

class EventsController < ApplicationController
before_filter :get_shift
before_action :set_event, only: [:show, :edit, :update, :destroy]

# GET /events
# GET /events.json
def index
  @events = @shift.events
end

# GET /events/1
# GET /events/1.json
def show
end

# GET /events/new
def new
  @event = @shift.events.build
end

# GET /events/1/edit
def edit
end

# POST /events
# POST /events.json
def create
  @event = @shift.events.build(event_params)

  respond_to do |format|
    if @event.save
      format.html { redirect_to shift_event_path, notice:
                                         'Event was successfully   created.' }
      format.json { render action: 'show', status: :created, location: @event }
    else
      format.html { render action: 'new' }
      format.json { render json: @event.errors, status: :unprocessable_entity }
    end
  end
end

# PATCH/PUT /events/1
# PATCH/PUT /events/1.json
def update
  respond_to do |format|
    if @event.update(event_params)
      format.html { redirect_to shift_event_path, notice: 
                                          'Event was successfully updated.' }
      format.json { head :no_content }
    else
      format.html { render action: 'edit' }
      format.json { render json: @event.errors, status: :unprocessable_entity }
    end
  end
end

# DELETE /events/1
# DELETE /events/1.json
def destroy
  @event.destroy
  respond_to do |format|
    format.html { redirect_to shift_event_path }
    format.json { head :no_content }
  end
end

private
  # Use callbacks to share common setup or constraints between actions.
  def set_event
    @event = @shift.events.find(params[:id])
  end

  def get_shift
    @shift = Shift.find(params[:shift_id])
  end

  # Never trust parameters from the scary internet, only allow the white list through.
  def event_params
    params.require(:event).permit(:time_s, :time_f, :odometre,
                           :location, :activity, :shift_id)
  end
end

routes

shift_events_path    GET    /shifts/:shift_id/events(.:format)   events#index
                     POST   /shifts/:shift_id/events(.:format)   events#create
new_shift_event_path GET    /shifts/:shift_id/events/new(.:format) events#new
edit_shift_event_path GET   /shifts/:shift_id/events/:id/edit(.:format) events#edit
shift_event_path     GET    /shifts/:shift_id/events/:id(.:format) events#show
                     PATCH  /shifts/:shift_id/events/:id(.:format) events#update
                     PUT    /shifts/:shift_id/events/:id(.:format) events#update
                     DELETE /shifts/:shift_id/events/:id(.:format) events#destroy
  shifts_path        GET    /shifts(.:format)                    shifts#index
                     POST   /shifts(.:format)                    shifts#create
new_shift_path       GET    /shifts/new(.:format)                shifts#new
edit_shift_path      GET    /shifts/:id/edit(.:format)           shifts#edit
shift_path           GET    /shifts/:id(.:format)                shifts#show
                     PATCH  /shifts/:id(.:format)                shifts#update
                     PUT    /shifts/:id(.:format)                shifts#update
                     DELETE /shifts/:id(.:format)                shifts#destroy
 root_path           GET    /                                    shifts#index 

I figure the form first line is wrong but I don't know what to change it to. Secondly, I think some the connections in the events controller are wrong. Any help would be appreciated.


Solution

  • Try this:

    <%= form_for [@shift, @event] do |f| %>
    

    Now you will post a particular event for a particular shift.