Ruby on Rails关联User与Guest模型:显示创建者问题排查
问题解决:Guest记录关联录入用户显示错误
问题描述
我拥有User.rb和Guest.rb两个模型,应用中由用户负责录入Guest信息。视图内有一个展示全部Guest的表格,期望每一行Guest都显示录入该信息的用户。目前所有Guest旁均显示当前登录用户,请求协助解决该问题。
现有代码
控制器代码(GuestsController)
def new @guest = Guest.new end def create @guest = Guest.new(guest_params) if @guest.save redirect_to guests_path else render 'new' end end def index @guests = Guest.all @user = current_user end def show @guest = Guest.find(params[:id]) @user = current_user end def edit @guest = Guest.find(params[:id]) end def update @guest = Guest.find(params[:id]) if @guest.update(guest_params) flash[:success] = "Profile updated" redirect_to @guest else render 'edit' end end def destroy Guest.find(params[:id]).destroy flash[:success] = "User deleted" redirect_to guests_url end private def guest_params params.require(:guest).permit(:experience,:interaction,:mood,:guest_name,:room_num,:arrival_date,:departure_date,:opportunity_string,:employee,:notes,:opportunity) end
模型代码
Guest.rb
has_and_belongs_to_many :users end
User.rb
# Include default devise modules. Others available are: # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable devise :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable has_and_belongs_to_many :guests end
视图代码(guests/index.html.erb)
<style> body{background-color:white;} </style> <h1 class="text-center mt-3">Guests</h1> <div class="container-fluid" style="overflow-x: auto; mb-3"> <table class="table table-bordered text-center "> <thead> <tr style="background-color:#CFD2CF;font-size:1.4vw"> <th>GUEST</th> <th>EXPERIENCE</th> <th>ROOM</th> <th>ARRIVAL</th> <th>DEPARTURE</th> <th>OPPORTUNITY</th> <th>EMPLOYEE</th> <th>DEPARTMENT</th> </tr> </thead> <tbody> <% @guests.each do |guest| %> <tr style="background-color:<%=guest.mood%>"> <td> <%= link_to guest.guest_name, "/guests/#{guest.id}" %></td> <td><%= guest.experience %></td> <td><%= guest.room_num %></td> <td><%= guest.arrival_date %></td> <td><%= guest.departure_date %></td> <td ><%= @user.current_user%></td> <td><%= %></td> <td><%= guest.interaction %></td> </tr> <% end %> </tbody> </table> </div>
Schema代码
create_table "guests", force: :cascade do |t| t.string "experience" t.string "interaction" t.string "mood" t.string "guest_name" t.string "room_num" t.string "arrival_date" t.string "departure_date" t.string "opportunity_string" t.string "employee" t.string "notes" t.datetime "created_at", precision: 6, null: false t.datetime "updated_at", precision: 6, null: false t.integer "user_id", null: false t.index ["user_id"], name: "index_guests_on_user_id" end create_table "users", force: :cascade do |t| t.string "email", default: "", null: false t.string "encrypted_password", default: "", null: false t.string "reset_password_token" t.datetime "reset_password_sent_at" t.datetime "remember_created_at" t.datetime "created_at", precision: 6, null: false t.datetime "updated_at", precision: 6, null: false t.boolean "superadmin_role", default: false t.boolean "supervisor_role", default: false t.boolean "user_role", default: true t.string "name" t.index ["email"], name: "index_users_on_email", unique: true t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true end add_foreign_key "guests", "users"
解决方案
1. 修正模型关联关系
从Schema可以看到,guests表有user_id外键且设置为非空,说明一个Guest只能属于一个User,一个User可以创建多个Guest,是一对多关系,而非当前的多对多(has_and_belongs_to_many)。修改模型:
Guest.rb
belongs_to :user end
User.rb
# Include default devise modules. Others available are: # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable devise :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable has_many :guests end
2. 确保新建Guest时关联当前用户
修改create方法,将当前登录用户绑定到新建的Guest上,否则user_id字段无法填充(Schema要求非空):
def create # 用current_user关联新建Guest,自动设置user_id @guest = current_user.guests.new(guest_params) if @guest.save redirect_to guests_path else render 'new' end end
3. 修正视图显示逻辑
视图中错误地使用了@user.current_user(而且@user本身就是current_user),应该通过guest.user获取该Guest的录入用户,然后显示其名称或邮箱:
修改视图中对应行:
<td ><%= guest.user.name %></td>
如果想显示邮箱则改为:
<td ><%= guest.user.email %></td>
同时可以删除index方法中的@user = current_user,因为视图不再需要这个变量。
4. 可选:预加载关联优化性能
为了避免N+1查询问题,在index方法中预加载user关联:
def index @guests = Guest.all.includes(:user) end
验证效果
完成以上修改后,重新启动服务器,录入新的Guest记录,表格中每行Guest的“EMPLOYEE”列会显示录入该记录的用户信息,而非当前登录用户。
内容的提问来源于stack exchange,提问作者Ari Ticas
相关产品推荐
相关产品推荐

