在我的Ruby on Rails应用程序中,我试图显示预订用户的first_name和last_name。
在预订/ index.html.erb上我有这个:
<% @bookings.each do |booking| %>
<tr>
<td><%= booking.user.first_name %> <%#= booking.user.last_name %></td>
<td><%= booking.showing.film.title %></td>
<td><%= booking.showing.show_date %></td>
<td><%= booking.showing.show_time.strftime("%H:%M") %></td>
<td></td>
<td><%= booking.seat.row_letter %><%= booking.seat.number %></td>
<td style="padding-right:65px">
<%#= link_to 'Edit', edit_user_path(user) %>
<%#= link_to 'Show', user_path(user) %>
<%#= link_to 'Destroy', user_path(user), method: :delete, data: { confirm: 'Are you sure?' } %>
</td>
</tr>
<% end %>
booking.showing.film.title
和下面的代码有效但booking.user.first_name
我收到了错误:
NoMethodError in Bookings#index
undefined method `first_name' for nil:NilClass
但我认为我的模型设置正确,user.rb:
has_many :bookings
bookings.rb:
belongs_to :user
bookings_controller:
class BookingsController < ApplicationController
before_action :set_booking, only: [:show, :edit, :update, :destroy]
# GET /bookings
# GET /bookings.json
def index
@bookings = Booking.all
end
# GET /bookings/1
# GET /bookings/1.json
def show
end
# GET /bookings/new
def new
@booking = Booking.new
end
# GET /bookings/1/edit
def edit
end
# POST /bookings
# POST /bookings.json
def create
@booking = Booking.new(booking_params)
respond_to do |format|
if @booking.save
format.html { redirect_to @booking, notice: 'Booking was successfully created.' }
format.json { render :show, status: :created, location: @booking }
else
format.html { render :new }
format.json { render json: @booking.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /bookings/1
# PATCH/PUT /bookings/1.json
def update
respond_to do |format|
if @booking.update(booking_params)
format.html { redirect_to @booking, notice: 'Booking was successfully updated.' }
format.json { render :show, status: :ok, location: @booking }
else
format.html { render :edit }
format.json { render json: @booking.errors, status: :unprocessable_entity }
end
end
end
# DELETE /bookings/1
# DELETE /bookings/1.json
def destroy
@booking.destroy
respond_to do |format|
format.html { redirect_to bookings_url, notice: 'Booking was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_booking
@booking = Booking.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def booking_params
params.require(:booking).permit(:showing_id, :user_id, :seat_id)
end
end
我错过了什么吗?属性名称和表名称是正确的。
答案 0 :(得分:1)
使用多个点违反了Law of Demeter
,被视为错误做法。要遵循Demeter法则,您可delegate
user
模型的名称,并在user
类中创建实例方法以返回全名,
预订课程
class Booking < ActiveRecord::Base
belongs_to :user
delegate :full_name, to: :user, prefix: true, allow_nil: true
end
用户类
class User < ActiveRecord::Base
has_many :bookings
def full_name
"#{first_name} #{last_name}"
end
end
视图
<td><%= booking.user_full_name %></td>
如果用户是nil
,此功能将正常返回,而不会抱怨没有用户。
委托方法调用总是更好(不要特意将delegate
视为关键字),而不是调用那么多点,例如,booking.showing.film.title
,有很多事情可以去错误的是,如果预订或显示或电影更改了任何属性,您需要继续迭代所有视图并每次修复每个视图,而不是尝试创建一个名为booking.film_title
的集中函数,然后你只需要将它保存在一个地方。
答案 1 :(得分:0)
因为user
为零,所以booking.user
会抛出错误
只需尝试此booking.try(:user).try(:first_name)
<% @bookings.each do |booking| %>
<tr>
<td><%= booking.try(:user).try(:first_name) %> <%= booking.try(:user).try(:last_name) %></td>
<td><%= booking.showing.film.title %></td>
<td><%= booking.showing.show_date %></td>
<td><%= booking.showing.show_time.strftime("%H:%M") %></td>
<td></td>
<td><%= booking.seat.row_letter %><%= booking.seat.number %></td>
<td style="padding-right:65px">
<%#= link_to 'Edit', edit_user_path(user) %>
<%#= link_to 'Show', user_path(user) %>
<%#= link_to 'Destroy', user_path(user), method: :delete, data: { confirm: 'Are you sure?' } %>
</td>
</tr>
<% end %>
有关点击try
的零处理的详细信息答案 2 :(得分:0)
您有正确的设置关联。
但问题是,您在创建user_id
记录时添加了booking
。
<% @bookings.each do |booking| %>
<tr>
<td><%= booking.user.try(:first_name) %> <%#= booking.user.try(:last_name) %></td>
<td><%= booking.showing.film.title %></td>
<td><%= booking.showing.show_date %></td>
<td><%= booking.showing.show_time.strftime("%H:%M") %></td>
<td></td>
<td><%= booking.seat.row_letter %><%= booking.seat.number %></td>
<td style="padding-right:65px">
<%#= link_to 'Edit', edit_user_path(user) %>
<%#= link_to 'Show', user_path(user) %>
<%#= link_to 'Destroy', user_path(user), method: :delete, data: { confirm: 'Are you sure?' } %>
</td>
</tr>
<% end %>
使用方法try
将确保不会发生错误
booking.user.try(:first_name) # display user first name if exist
booking.user.try(:last_name) # display user last name if exist
打开rails c
并检查您的booking
记录中没有user_id