我面临以下问题:
我有一个模型“餐厅”,我想在导航栏中创建一个“编辑餐厅”链接。我尝试在导航栏中插入这个li:
<li><%= link_to "Edit Listing", edit_restaurant_path(@restaurant.id) %></li>
但是通过这样做我在完全相同的行上得到了这个错误:
NoMethodError : undefined method `id' for nil:NilClass
我猜:id没有正确传递
以下是我的其他相应文件:
restaurant_controler.rb
class RestaurantsController < ApplicationController
before_action :set_restaurant, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!, except: [:search, :index, :show]
before_action :check_user, except: [:search, :index, :show]
def search
if params[:search].present?
@restaurants = Restaurant.search(params[:search])
else
@restaurants = Restaurant.all
end
end
# GET /restaurants
# GET /restaurants.json
def index
@restaurants = Restaurant.all
end
# GET /restaurants/1
# GET /restaurants/1.json
def show
@reviews = Review.where(restaurant_id: @restaurant.id).order("created_at DESC")
if @reviews.blank?
@avg_rating = 0
else
@avg_rating = @reviews.average(:rating).round(2)
end
end
# GET /restaurants/new
def new
@restaurant = Restaurant.new
end
# GET /restaurants/1/edit
def edit
@restaurant = Restaurant.find(params[:id])
end
# POST /restaurants
# POST /restaurants.json
def create
@restaurant = Restaurant.new(restaurant_params)
respond_to do |format|
if @restaurant.save
format.html { redirect_to @restaurant, notice: 'Restaurant was successfully created.' }
format.json { render action: 'show', status: :created, location: @restaurant }
else
format.html { render action: 'new' }
format.json { render json: @restaurant.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /restaurants/1
# PATCH/PUT /restaurants/1.json
def update
respond_to do |format|
if @restaurant.update(restaurant_params)
format.html { redirect_to @restaurant, notice: 'Restaurant was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: @restaurant.errors, status: :unprocessable_entity }
end
end
end
# DELETE /restaurants/1
# DELETE /restaurants/1.json
def destroy
@restaurant.destroy
respond_to do |format|
format.html { redirect_to restaurants_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_restaurant
@restaurant = Restaurant.find(params[:id])
end
def check_user
unless current_user.admin?
redirect_to root_url,
alert: "Sorry, only admins can do that!"
end
end
# Never trust parameters from the scary internet, only allow the white list through.
def restaurant_params
params.require(:restaurant).permit(:name, :adress, :phone, :website, :image, :description)
end
end
导航栏:
<nav class="navbar navbar-default" role="navigation">
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<%= link_to "ListingsDemo", root_path, class: "navbar-brand" %>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
<li><%= link_to "About", pages_about_path %></li>
<li><%= link_to "Contact", pages_contact_path %></li>
</ul>
<p>
<%= form_tag search_restaurants_path, method: :get, class: "navbar-form navbar-left" do %>
<%= text_field_tag :search, params[:search], class: "form-control" %>
<%= submit_tag "Search", name: nil, class: "btn btn-default" %>
<% end %>
</p>
<ul class="nav navbar-nav navbar-right">
<% if user_signed_in? %>
<li><%= link_to "Edit Profile", edit_user_registration_path %></li>
<li><%= link_to "Edit Listing", edit_restaurant_path(@restaurant.id) %></li>
<li><%= link_to "Sign Out", destroy_user_session_path, method: :delete %></li>
<% else %>
<li><%= link_to "Sign In", new_user_session_path %></li>
<li><%= link_to "Sign Up", new_user_registration_path %></li>
<% end %>
</ul>
</div><!-- /.navbar-collapse -->
</div><!-- /.container-fluid -->
</nav>
的routes.rb
Yelpdemo::Application.routes.draw do
resources :messages
devise_for :admin_users, ActiveAdmin::Devise.config
ActiveAdmin.routes(self)
devise_for :users
resources :restauarants do
collection do
get 'search'
end
resources :reviews, except: [:show, :index]
end
get "pages/about"
get 'pages/contact', to: redirect('/messages/new')
root 'restaurants#index'
end
Restaurans / index.html.erb
<table class="table table-responsive table-hover table-condensed">
<thead>
<tr>
<th>Name</th>
<th>Adress</th>
<th>Phone</th>
<th>Website</th>
<% if user_signed_in? && current_user.admin? %>
<th colspan="2"></th>
<% end %>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<% @restaurants.each do |restaurant| %>
<tr>
<td><%= link_to restaurant.name, restaurant %></td>
<td><%= restaurant.adress %></td>
<td><%= restaurant.phone %></td>
<td><%= link_to restaurant.website, restaurant.website %></td>
<% if user_signed_in? && current_user.admin? %>
<td><%= link_to 'Edit', edit_restaurant_path(restaurant), class: 'btn btn-link' %></td>
<td><%= link_to 'Destroy', restaurant, method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn btn-link' %></td>
<% end %>
</tr>
<% end %>
</tbody>
</table>
<br>
<% if user_signed_in? && current_user.admin? %>
<%= link_to 'New Restaurant', new_restaurant_path, class: 'btn btn-link' %>
<% end %>
<%= image_tag "https://s3-eu-west-1.amazonaws.com/listingsdemo/happy_footer.png" %>
答案 0 :(得分:1)
<强>餐厅强>
您遇到的问题不是id
方法没有被传递 - 而是您的@restaurant
对象尚未被声明。
当我查看您的代码时,我注意到您提到错误在您的导航栏中。这引起了我的担忧,因为您视图的 navbar 元素表明它会持续存在多个视图
如果是这种情况,您需要确保为每个操作声明了@restaurant
变量:
#app/controllers/application_controller.rb
Class ApplicationController < ActionController::Base
before_action :set_restaurant
private
def set_restaurant
@restaurant = Restaurant.find 1 #-> you need to identify the restaurant
end
end
答案 1 :(得分:0)
您始终会在index
和search
操作中收到此错误消息。因为你在这个方法中得到餐馆对象的列表而不是餐馆的单个对象。在索引操作的情况下,您将获得@restaurant
nil。在索引和搜索操作的情况下,您必须从导航栏中删除此操作/链接。希望这能帮到你!
答案 2 :(得分:0)
您在哪个视图/路线中点击导航栏链接?没有信息,但看起来你的@restaurant变量是零,所以你实际上没有从控制器传递给视图。
另一件事是 - 一般来说,您可以将erb中的路径称为
edit_restaurant_path(@restaurant)
(不需要'.id')