Rails中奇怪的路由行为

时间:2015-09-30 21:01:08

标签: ruby-on-rails ruby ruby-on-rails-4

我使用的是rails 4.2。我创建了一个表单,提交给我的控制器中的特定操作。这是表单代码和控制器定义的开头:

view.html.erb

<div id="account-booking" class="tab-pane">
  <%= form_for @booking_info, url: { action: 'book' } do |b| %>
      <fieldset class="group column-1">
        <legend>Booking Preference for <%= Rails.configuration.x.app_settings.year %></legend>

        <div class="group column-full radio-list">
          <%= label_tag('Select Room Type') %>
          <% @available_rooms.each do |rt| %>
              <div class="radio-item">
                <!--
                <%= b.radio_button :room_type_id, rt.id, :class => 'rb_room_type inline', :onclick => fetch_room_info_path(:id => rt.id), :remote => true %>
                <%= b.radio_button :room_type_id, rt.id, :class => 'rb_room_type inline', :onclick => 'render_room_info('+ rt.id.to_s + ');' %>
                -->
                <%= b.radio_button :room_type_id, rt.id, :class => 'rb_room_type inline' %>
                <%= content_tag :span, rt.name  %>
                <a data-toggle="tooltip" data-placement="right" title="<%= rt.description %>">
                  <%= image_tag "tooltip.png", :class=>"tooltip-icon" %>
                </a>
              </div>
          <% end %>

          <%= b.label :roommate_preference, 'Roommate Preference' %>
          <%= b.text_area :roommate_preference, :class => 'form-control' %>

          <div class="account-checkbox-options">
            <%= b.label :is_flexible, class: 'checkbox inline' do %>
                <%= b.check_box :is_flexible %>
                I am flexible with regards to my room choice.
            <% end %>
          </div>
        </div>

        <!--
        <div id="estimated-due" class="group column-2">

        </div>
        -->
      </fieldset>

      <fieldset class="group column-2 account-preferences">
        <legend>Your Room Information for <%= Rails.configuration.x.app_settings.year %></legend>
        <div class="group column-1">
          <div class="group column-full add-tabbing">
            <%= label_tag('Selected Room:') %>
            <span><%= @booking_info.room_type.blank? ? '<No Room Selected>' : @booking_info.room_type.name  %></span>
          </div>

          <div class="group column-full add-tabbing">
            <%= label_tag('Assigned Room:') %>
            <span><%= @booking_info.assigned_type.blank? ? '<No Room Assigned>' : @booking_info.assigned_type.name  %></span>
          </div>
        </div>
        <div class="group column-2">
          <div class="group column-full add-tabbing">
            <%= label_tag('Total Due:') %>
            <span ><%= number_to_currency(@booking_info.total_due.blank? ? 0.00 : @booking_info.total_due) %></span>
          </div>
          <div class="group column-full add-tabbing">
            <%= label_tag('Current Balance:') %>
            <span><%= number_to_currency(@booking_info.outstanding_balance.blank? ? 0.00 : @booking_info.outstanding_balance) %></span>
          </div>
        </div>
        <% unless @booking_info.assigned_type.blank? %>
            <div class="group column-full">
              <h2>Assigned Room Information</h2>
            </div>
        <% end %>
      </fieldset>

      <div class="account-buttons">
        <%= b.submit 'Submit', class: 'btn btn-danger' %>
        <%= link_to 'Cancel', '/pages/home', class: 'link-button-cancel' %>
      </div>

  <% end %>
</div>

account_controller.rb

def book
    @booking = PersonRoom.new(booking_params)
    @requested_room = RoomType.find(params[:person_room][:room_type_id])
    @booking.room_type = @requested_room

    if update_booking @booking
      redirect_to :controller => 'account', :action => 'view'
    else
      render('view')
    end
 end

当没有PersonRoom记录时(如果我正在进行插入),所有这些都可以很好地工作。但是,如果我尝试更新记录,使用相同的表单/操作(因为无论我是否插入或更新,视图和操作都完全相同),当我点击&时,我收到错误#34;提交&#34;:

没有路线匹配[PATCH]&#34; / account / book&#34;

这没有任何意义。我在完全相同的页面上。我刚刚使用了所有这些代码来创建记录,因此路径显然存在(因为它调用/ account / book)。现在我想更新,但突然之间路线不匹配?它甚至从未打破过代码,因为它没有调用控制器动作。这对我来说毫无意义。希望有人可以提供帮助。

2 个答案:

答案 0 :(得分:0)

我发现了问题。这真是太愚蠢了。我在route.config中有以下行:

match ':controller(/:action(/:id))', :via => [:get, :post]

我只需将其更改为:

match ':controller(/:action(/:id))', :via => [:get, :post, :patch, :put, :delete]

现在它处理更新(即补丁/放置)

答案 1 :(得分:0)

在查看您的代码时我畏缩了,这是我如何做到的:

#config/routes.rb
resources :rooms do
   resources :bookings #-> url.com/rooms/:room_id/bookings/new
end

#app/controllers/bookings_controller.rb
class BookingsController < ApplicationController
   before_action :set_room
   def new
      @booking = room.bookings.new
   end

   def create
      @booking = room.bookings.new booking_params
      @booking.save
   end

   def update
      @booking = room.bookings.update booking_params
   end

   private

   def set_room
      @room = Room.find params[:room_id]
   end

   def booking_params
      params.require(:booking).permit(:x, :y, :z)
   end
end

此设置与Rails(IE resourceful routes)非常标准:

  

浏览器通过使用URL请求来自Rails的页面   特定的HTTP方法,例如GET,POST,PATCH,PUT和DELETE。每   method是对资源执行操作的请求。一个   资源路由将许多相关请求映射到a中的操作   单控制器。

遵守这一原则可能会解决你的“怪异”问题。路由错误是由于它们与Rails系统的其他方面的凝聚力。

例如:

#app/controllers/accounts_controller.rb
class AccountsController < ApplicationController
   #-> this shouldn't have a "book" action unless necessary. Your case is not necessary
end

-

你遇到的问题是你没有遵守Rails&#39;保持系统面向对象的惯例。

这一点的重要性是巨大的; Rails旨在使CRUD (create read update destroy)数据对象尽可能简单。这些对象是根据&#34; models&#34;中的数据库数据构建的:

enter image description here

我经常使用这张图片 - 它显示了Rails应该如何工作。您可以在控制器中操作的Models中构建对象。视图向用户显示了所有内容。

因此,当您查看代码时,我会尽量保持简单:

#app/models/room.rb
class Room < ActiveRecord::Base
   has_many :bookings
   has_many :users, through: :bookings
   belongs_to :type
end

#app/models/booking.rb
class Booking < ActiveRecord::Base
   belongs_to :room
   belongs_to :user
end

#app/models/user.rb
class User < ActiveRecord::Base
   has_many :bookings
   has_many :rooms, through: :bookings
end

这将允许您拨打以下电话:

@room = Room.find 1
@room.bookings #-> collection of bookings per room

您还可以为视图执行以下(简单)操作:

#app/views/bookings/new.html.erb
<%= form_for @booking do |f| %>
   <%= f.text_field :x %>
   <%= f.text_field :y %>
   <%= f.text_field :z %>
   <%= f.submit %>
<% end %>
相关问题