需要帮助来理解`has_and_belongs_to_many`

数据库中有三个表:

  1. 用户(非空)
  2. 时间表(非空)
  3. schedules_users(

用户模型:

class User < ActiveRecord::Base [...] has_and_belongs_to_many :schedules#has_many :schedules [...] end 

时间表模型:

 class Schedule < ActiveRecord::Base has_and_belongs_to_many :users#belongs_to :user end 

welcome-controller 🙁我希望按日期和时间对日程安排进行排序)

 class WelcomeController < ApplicationController def index if(current_user) @user_schedules = current_user.schedules @user_schedules_date = @user_schedules.order(:date_time).group_by { |sched| sched.date_time.beginning_of_day } end end end 

@user_schedules = current_user.schedules这不正确,不是吗?

SQL输出:

 Started GET "/" for 127.0.0.1 at 2014-07-30 11:24:09 +0200 Processing by WelcomeController#index as HTML User Load (1.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = 12 LIMIT 1 Schedule Load (1.0ms) SELECT "schedules".* FROM "schedules" INNER JOIN "schedules_users" ON "schedules"."id" = "schedules_users"."schedule_id" WHERE "schedules_users"."user_id" = $1 ORDER BY "schedules"."date_time" ASC [["user_id", 12]] Rendered welcome/index.html.erb within layouts/application (0.0ms) Completed 200 OK in 47ms (Views: 43.0ms | ActiveRecord: 2.0ms) 

欢迎观看:

 

视图/ HTML输出:

 

数据库: (schedules_users)
在此处输入图像描述

描述:
如您所见,我将关系从has_manybelongs_to更改为has_and_belongs_to_many
没有错误或exception。
一切都应该是正确的
(我不知道welcome-controller中的sort命令是否正确)
SQL输出看起来也正确。

如何将数据添加到schedules_users-table?

如何访问schedules_users-table中添加的数据?
我需要一个名为ScheduleUsers的新模型,还是……?
我不明白它atm。
如果有人能帮助我会很好。
谢谢。



编辑:(解决方案[Rich Peck])
时间表控制器:

 # encoding: UTF-8 class ScheduleController < ApplicationController def add if (current_user.nil?) redirect_to "/" else if (@schedule_add.nil?) @schedule_add = Schedule.new end end end def add_now @schedule_add = Schedule.new(schedule_params) if @schedule_add.valid? @schedule_add.save current_user.schedules < "add" end end def edit if (current_user.nil?) redirect_to "/" else if current_user.schedules.nil? redirect_to "/" else begin #try @schedule_edit = current_user.schedules.find(params[:id]) rescue #catch if @schedule_edit.nil? flash[:notice] = 'Der Termin konnte nicht gefunden werden.' redirect_to :root end end end end end def edit_now @schedule_edit = current_user.schedules.find(params[:id]) if @schedule_edit.nil? flash[:notice] = 'Der Termin konnte nicht gefunden werden.' redirect_to :root else @schedule_edit.update(schedule_params) if @schedule_edit.valid? @schedule_edit.save flash[:notice] = 'Der Termin '+@schedule_edit.titel+' wurde bearbeitet.' redirect_to :root else render :action => "edit" end end end def delete if (current_user.nil?) redirect_to "/" else if current_user.schedules.nil? redirect_to "/" else begin #try @schedule_delete = current_user.schedules.find(params[:id]) rescue #catch if @schedule_delete.nil? flash[:notice] = 'Der Termin konnte nicht gefunden werden.' redirect_to :root end end end end end def delete_now begin #try @schedule_delete = current_user.schedules.find(params[:id]) rescue #catch if @schedule_delete.nil? flash[:notice] = 'Der Termin konnte nicht gefunden werden.' redirect_to :root end end if @schedule_delete.nil? flash[:notice] = 'Der Termin konnte nicht gefunden werden.' redirect_to :root else @schedule_delete.delete #SHOULD DELETE RELATIONSHIP IN THE JOIN-TABLE, BUT DIDNT flash[:notice] = 'Der Termin '+@schedule_delete.titel+' wurde gelöscht.' redirect_to :root end end def invite end # --------------------------------------------------------------------------- private #allowed parameters to pass through to the model def schedule_params params.require(:schedule).permit(:id, :titel, :location, :date_time) end end 

routes.rb中:

 Calendar::Application.routes.draw do root 'welcome#index' get "welcome/index" => "welcome#index" get "auth/sign_up" => "auth#sign_up" get "auth/sign_in" => "auth#sign_in" get "auth/sign_out" => "auth#sign_out" get "auth/settings" => "auth#settings" get "auth/pwd_forgot" => "auth#pwd_forgot" get "auth/pwd_reset" => "auth#pwd_reset" post "auth/sign_in" => "auth#login" post "auth/sign_up" => "auth#register" put "auth/settings" => "auth#save_settings" put "auth/pwd_forgot" => "auth#send_pwd_reset_instructions" put "auth/pwd_reset" => "auth#new_pwd" delete "auth/settings" => "auth#delete" #resources :users, only: :index #resources :users do # post :add, action: :add_schedule #-> domain.com/users/4/schedules/add # delete :remove, action: :remove_schedule #-> domain.com/users/4/schedules/remove #end get "schedule/add" => "schedule#add" post "schedule/add" => "schedule#add_now" get "schedule/invite" => "schedule#invite" #get "schedule/edit" => "schedule#edit" #get "schedule/edit/:id" => "schedule#edit" get '/schedule/edit/:id', to: 'schedule#edit', as: 'schedule/edit' put "schedule/edit/:id" => "schedule#edit_now" #PUT oder POST ? #get "schedule/delete" => "schedule#delete" get '/schedule/delete/:id', to: 'schedule#delete', as: 'schedule/delete' delete "schedule/delete/:id" => "schedule#delete_now" end 

欢迎观看:

 

'schedule', :action => 'edit', :id => schedule.id} %>

'schedule', :action => 'delete', :id => schedule.id} %>

如果我添加一个计划,一切正常。 编辑也工作正常。
如果我删除了一个计划,它将不会删除Join-Table中的关系。
任何想法为什么? – >解决方案: @schedule_delete.DESTROY而不是@schedule_delete.delete 。 因此删除/销毁时间表也可以正常工作。

所以一切正常。
谢谢您的帮助!

让我解释一下has_and_belongs_to_many给你

HABTM基本上是ActiveRecord为您提供join table一种方式 – 您的关联使您能够通过连接表加载所需的关联数据。

has_many :through非常相似has_many :through ,HABTM提供了一种访问模型关联数据的简单方法,但由于它没有模型,因此您无法直接访问连接数据 (因为没有primary key可以加载它们) ):

在此处输入图像描述

它基本上采用了连接表的foreign_keys ,并允许您从任何一个依赖模型中提取相关数据。 你不能设置


如何将数据添加到schedules_users-table?

您必须使用collection ActiveRecord方法 ,特别是您必须确保能够将记录追加到schedulesusers关联:

 #config/routes.rb resources :users do post :add, action: :add_schedule #-> domain.com/users/4/schedules/add delete :remove, action: :remove_schedule #-> domain.com/users/4/schedules/remove end #app/controllers/users_controller.rb Class UsersController < ApplicationController before_action :set_schedule, only: [:add_schedule, :remove_schedule] def add_schedule @user.schedules << @schedule #-> has to be an ActiveRecord object end def remove_schedule @user.schedules.delete params[:schedule_id] end private def set_schedule @user = User.find params[:user_id] @schedule = Schedule.find params[:id] end end 

如何访问schedules_users-table中添加的数据?

您只能通过集合关联访问此数据:

 $ rails c $ @user = User.find 1 $ @user.schedules.each do |schedule| $ puts schedule #-> will output each schedule record $ end 

要从控制器访问,您将运行完全相同的命令

看起来很快,但对我来说看起来还不错。 但是,由于您已将模型从has_many更改为has_and_belongs_to_many,因此如果希望显示旧数据,则需要迁移数据。 现在您没有为您的用户提供任何计划,这是正确的,因为schedules_users表为空。 假设您的日程表中仍有user_id列,您可以执行类似迁移数据的操作:

 insert into schedules_users (select id as schedule_id, user_id from schedules where user_id is not null);