Ruby on rails Rails中奇怪的路由行为

Ruby on rails Rails中奇怪的路由行为,ruby-on-rails,ruby,ruby-on-rails-4,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"> &l

我使用的是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>
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
在没有人事记录的情况下(例如,如果我正在做插入),所有这些都非常有效。但是,如果我尝试使用相同的表单/操作更新记录(因为无论是插入还是更新,视图和操作都完全相同),则单击“提交”时会出现错误:

没有与[PATCH]“/account/book”匹配的路由


这毫无意义。我的观点完全相同。我只是使用了所有这些代码来创建记录,因此路由显然存在(因为它调用/account/book)。现在我想更新,但突然路线不匹配?而且它甚至从不进入代码,因为它不调用控制器操作。这对我来说毫无意义。希望有人能帮忙。

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

match ':controller(/:action(/:id))', :via => [:get, :post]
我只需要将此更改为:

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

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

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

match ':controller(/:action(/:id))', :via => [:get, :post]
我只需要将此更改为:

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

现在,它可以处理更新(即修补/放置)

当我查看您的代码时,我感到有些畏缩,下面是我应该如何做的:

#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
这将允许您调用以下命令:

@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 %>
#app/views/bookings/new.html.erb

查看您的代码时,我吓了一跳,下面是我应该怎么做的:

#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
这将允许您调用以下命令:

@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 %>
#app/views/bookings/new.html.erb

当您要更新实体时,是否在请求的同时提供ID?routes.rb文件是什么样子的?由于请求(补丁)的类型,更新不起作用,可能不是因为其他原因。您在更新实体时是否随请求一起提供ID?routes.rb文件是什么样子的?更新不起作用是因为请求类型(补丁),可能不是因为其他原因。这段代码不是很好-让我写一个答案给你一些想法这段代码不是很好-让我写一个答案给你一些想法,这样我就明白你说的了。但是,即使我这样组织它,如果没有我对route.config所做的更改,它会工作吗?潜在的问题是,路由仅配置为查找get和post谓词,而此调用使用的是补丁谓词,因此未配置路由。即使我按照您的建议重新组织了控制器,我也必须在route.config的答案中添加代码吗?如果您只是想让它与
put/patch
一起工作,您可以使用
via
属性来定义它们。但问题远不止于此;正如回答中提到的。我理解的更深:)我只是不确定如果我按照你的建议重新组织所有内容,是否会出现同样的错误,或者重组是否会因为Rails的设计方式而导致所有内容都正常工作。在我使用过的其他MVC框架中,您通常需要在创建路线时明确表示。呵呵,是的,这就是我试图解释“Rails”范例的原因——许多来自其他MVC框架的人不知道Rails是如何创建的。这有点像社会主义,如果你想保持传统,那么它是有效的,如果你做你自己的事情,你必须理解这个系统以保持简洁。所以我明白你的意思。但是,即使我这样组织它,如果没有我对route.config所做的更改,它会工作吗?潜在的问题是,路由仅配置为查找get和post谓词,而此调用使用的是补丁谓词,因此未配置路由。即使我按照您的建议重新组织了控制器,我也必须在route.config的答案中添加代码吗?如果您只是想让它与
put/patch
一起工作,您可以使用
via
属性来定义它们。但问题远不止于此;正如回答中提到的。我理解的更深:)我只是不确定如果我按照你的建议重新组织所有内容,是否会出现同样的错误,或者重组是否会因为Rails的设计方式而导致所有内容都正常工作。在我使用过的其他MVC框架中,您通常需要在创建路线时明确表示。呵呵,是的,这就是我试图解释“Rails”范例的原因——许多来自其他MVC框架的人不知道Rails是如何创建的。这有点像社会主义,如果你想保持传统,它就起作用,如果你做你自己的事情,你就必须理解这个体系以保持简洁。