没有POST路由 - 嵌套资源导致混淆

时间:2017-04-15 20:13:01

标签: ruby-on-rails ruby

提交新餐厅表格时出现以下错误:     没有路线匹配[POST]“/ restaurants”

当我运行rake路线时没有[POST]路径。我得到以下内容:

user_restaurants GET    /users/:user_id/restaurants(.:format)             restaurants#index
                         POST   /users/:user_id/restaurants(.:format)             restaurants#create
     new_user_restaurant GET    /users/:user_id/restaurants/new(.:format)         restaurants#new
         edit_restaurant GET    /restaurants/:id/edit(.:format)                   restaurants#edit
              restaurant GET    /restaurants/:id(.:format)                        restaurants#show
                         PATCH  /restaurants/:id(.:format)                        restaurants#update
                         PUT    /restaurants/:id(.:format)                        restaurants#update
                         DELETE /restaurants/:id(.:format)                        restaurants#destroy

我的routes.rb:

devise_for :users
resources :users, :shallow => true do
  resources :restaurants do
    resources :reviews, except: [:index, :show] #create review paths
  end
end

我的user.rb:

has_many :reviews
has_many :restaurants

我的restaurant.rb:

has_many :reviews
belongs_to :category
belongs_to :user

我的restaurants_controller.rb:

before_action :set_user
before_action :authenticate_user!, only: [:create, :new, :edit, :update, 
:destroy]
before_action :check_if_owner?, only: [:edit, :update, :destroy]

def new
  @restaurant = Restaurant.new(user: @user) #create a new restaurant
end

def create
  @restaurant = current_user.restaurants.build(restaurant_params)
  @restaurant.user = @user
  @restaurant.save
  redirect_to @restaurant
end

private
  def set_user
    @user = User.find(params[:user_id])
  end  

  def restaurant_params
    params.require(:restaurant).permit(:name, :description, :category_id,
    :address1, :address2, :city, :state, :zipcode, :phone, :email, :image, 
    :user_id)
  end    

我的餐厅/ new.html.erb:

<%= form_for @restaurant do |f| %>

是否有更好的方法将餐厅与用户联系起来,以便餐馆老板可以编辑他们的页面?如果没有,我将如何解决错误?

<%= link_to "Create a Restaurant", 
new_user_restaurant_path(current_user.id), class: "btn btn-lg btn-primary"%>

2 个答案:

答案 0 :(得分:1)

你滥用嵌套。嵌套路线时,您应该只嵌套一层深度:

resources :restaurants, shallow: true do
  resources :reviews
end

resources :users do
  # ...
end

嵌套应该用于上下文 - 而不是身份验证/授权。

虽然您可以在用户restaurants下嵌套POST /users/:user_id/restaurants的创建操作,但只有在为其他用户创建餐厅时才有意义。

class RestaurantsController

  before_action :authenticate_user!, only: [:create, :new, :edit, :update, 
:destroy]
  before_action :check_if_owner?, only: [:edit, :update, :destroy]

  # POST /restaurants
  def create
    @restaurant = current_user.restaurants.new(restaurant_params)

    # ...
  end
end

这大大降低了复杂程度。如果要创建嵌套路由以显示用户的餐馆或评论,一个非常强大的模式是使用模块:

resources :reviews, except: [:new, :create]

resources :users do
  resources :reviews, only: [:index], module: :users
end
# app/controllers/reviews_controller.rb
class ReviewsController < ApplicationController
  # ...

  # GET /reviews
  def index
    @reviews = Review.all
  end
end

# app/controllers/users/reviews_controller.rb
class Users::ReviewsController < ApplicationController
  # GET /users/:user_id/reviews
  def index
    @user = User.includes(:reviews).find(params[:user_id])
    @reviews = @user.reviews
  end
end

这让我们可以根据上下文使用不同的控制器。用户评论与所有评论的资源非常不同。

在为餐馆创建评论时,您需要使用嵌套作为路径提供重要的背景。

resources :restaurants do
  resources :reviews, only: [:new, :create, :index], module: :users
end


# app/controllers/restaurants/reviews_controller.rb
class Restaurants::ReviewsController

  # GET /restaurants/:restaurant_id/reviews/new
  def new
    @restaurant = Restaurant.find(params[:Restaurant_id])
    @review = @restaurant.review.new
  end

  # POST /restaurants/:restaurant_id/reviews
  def create
    @restaurant = Restaurant.find(params[:Restaurant_id])
    @review = @restaurant.review.new(review_params) do |r|
      r.user = current_user
    end
    # ...
  end

  # GET /restaurants/:restaurant_id/reviews
  def index
    @restaurant = Restaurant.includes(:reviews).find(params[:Restaurant_id])
    @reviews = @restaurant.reviews
  end
end
# app/views/reviews/_form.html.erb
<%= form_for(resource) do %>
  # ...
<% end %>

# app/views/restaurants/reviews/new.html.erb
<%= render partial: 'reviews/form', resource: [@review.restaurant, @review] %>

 # app/views/reviews/edit.html.erb
<%= render partial: 'reviews/form', resource: @review %>

答案 1 :(得分:0)

尝试在表单中更改此内容:

<%= form_for [@user, @restaurant] do |f| %>

您可以在此处阅读http://guides.rubyonrails.org/form_helpers.html#relying-on-record-identification