【问题标题】:Ruby on Rails associating a User to another models text fieldRuby on Rails 将用户关联到另一个模型文本字段
【发布时间】:2022-10-23 21:29:37
【问题描述】:

你好,我有 2 个模型 User.rb 和 Guest.rb。

在我的应用程序中,用户负责输入访客信息。我的视图中有一张桌子,可以显示所有客人。我希望每个客人行都显示输入了他们信息的用户。我在我的控制器方法中正确设置 current_user 方法时遇到了一些麻烦。目前,我正在抓取 current_usera 并在每位客人旁边输入它。非常感谢你。

控制器:

  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

  
  def guest_params
      params.require(:guest).permit(:experience,:interaction,:mood,:guest_name,:room_num,:arrival_date,:departure_date,:opportunity_string,:employee,:notes,:opportunity)
 end
end

楷模:

    has_and_belongs_to_many :users
    
end
  # 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

意见:

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>


架构:


  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"
end

【问题讨论】:

    标签: ruby-on-rails model associations


    【解决方案1】:

    有几件事会有所帮助:

    设计和current_user:

    Devise takes care of current_user for you,所以你应该可以在你的控制器和视图中调用current_user。

    @user.current_user 不是一种方法,除非您在 User 模型中创建了一个方法,我不建议您这样做。

    不要将@user 与current_user 混用

    可以设置@user = current_user,但我认为这是一种不好的做法,因为它会很快变得混乱

    @user 应该绑定到模型 User 并代表 current_user 正在与之交互的用户。

    例如,/users/1/edit 之类的 URL 应设置为 @user = User.find(1)。

    current_user 可能是正在编辑 @user 对象的其他人。

    HABTM 协会

    给定一个分配的@user,您可以调用@user.guests 来获取与该用户关联的所有客人。

    例如。对于创建以下 URL 的路由:/users/1/guests 那么你的控制器可以有这样的东西:

    # users_controller.rb
    
    class UsersController < ApplicationController
    
    ...
    
      def guests
        @user = User.find(params[:id])
        @guests = @user.guests
      end
    
    end
    

    反过来也是如此。对于像guests/1/users 这样的路线,您可以致电@guest.users。

    但...

    你真的想要一个HABTM吗?

    如果一个User 可以创建许多Guests,但一个Guest 永远不会与许多Users,那么这并不是真正的“拥有并属于许多”关系。您可能只想要一个简单的has_many belongs_to。

    当我考虑我的人际关系时,我经常重温this article 作为复习。

    您的架构在您的guest 模型上有一个user_id,这向我表明您希望能够说:“A User has_many guest. A Guest belongs_to a user.”

    但你不会真的说“一个客人可以属于许多用户”

    代码修复

    我的视图中有一张桌子,可以显示所有客人。

    对于所有客人,这将是 URL /guests,它应该映射到 GuestsController#index:

    # guests_controller.rb
    
    class GuestsController < ApplicationController
    
    ...
    
      def index
       @guests = Guest.all # or some scope like Guest.active
      end
    ...
    end
    

    对于与给定用户相关的客人,这将是 URL /users/:id/guests,应该映射到 UsersController#guests:

    # users_controller.rb
    
    class UsersController < ApplicationController
      before_action :set_user, only: %i[show edit update guests]
    ...
      def guests
       @user.guests
       ...
      end
    ...
    
      private
    
      # this method sets @user for all views defined in the `:only` hash of the `before_action` callback.
      def set_user
        @user = User.find(params[:id]
      end
    

    我希望每个客人行都显示输入了他们信息的用户。

    由于您在Guest 上有一个user_id 字段,如果您切换到has_many belongs_to 关系,那么您可以只调用用户:

    <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 ><%= guest.user%></td> <!-- guest.user instead of @user.current_user -->
          <td></td>
          <td><%= guest.interaction %></td>
         </tr>
      <% end %>
    </tbody>
    

    额外积分:使用 Includes 预加载关联

    此外,作为专业提示,调用guest.user 可能会变慢,因为每个guest 记录都需要调用User 表。

    Rails 针对这种情况提供了eager loading。

    将@guests = Guest.all 更改为@guest = Guest.includes(:user).all,Rails 将处理其余部分。

    【讨论】:

      猜你喜欢
      • 2021-08-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-05
      相关资源
      最近更新 更多