问题
There are three tables in the database:
- users (not empty)
- schedules (not empty)
- schedules_users (empty)
user-model:
class User < ActiveRecord::Base
[...]
has_and_belongs_to_many :schedules#has_many :schedules
[...]
end
schedule-model:
class Schedule < ActiveRecord::Base
has_and_belongs_to_many :users#belongs_to :user
end
welcome-controller: (where I want to sort the schedules by date and time)
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
this is not correct, isnt it?
SQL-output:
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)
welcome-view:
<div class="table-responsive">
<table class="table table-hover">
<tbody>
<% @user_schedules_date.sort.each do |date_time, schedules| %>
<tr class="thead success">
<th colspan="4" scope="col"><p><%= date_time.strftime("%A, %d.%m.%Y") %></p></th>
</tr>
<% for schedule in schedules %>
<tr>
<th scope="row"><p><%= schedule.titel %></p></th>
<td><p><%= schedule.date_time.strftime("%H:%M:%S") %></p></td>
<td><p><%= schedule.location %></p></td>
</tr>
<% end %>
<% end %>
</tbody>
</table>
</div>
view/html-output:
<div class="table-responsive">
<table class="table table-hover">
<tbody>
</tbody>
</table>
</div>
database: (schedules_users)
Description:
As you can see I changed the relationship from
has_many
& belongs_to
to has_and_belongs_to_many
.There is no error or exception.
Everything should be right
(I dont know whether the sort command in the welcome-controller is correct anymore).
The SQL-output looks also correct.
How can I add data to the schedules_users-table?
AND
How can I get access to the added data in the schedules_users-table?
Do I need a new model called ScheduleUsers, or... ?
I dont understand it atm.
Would be nice if anyone can help me.
Thanks.
EDIT: (Solution [Rich Peck])
schedule-controller:
# 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 << @schedule_add # ADD RELATIONSHIP TO THE JOIN-TABLE
#UserMailer.welcome_email(@user).deliver #BestätigungsEmail versenden
flash[:notice] = 'Ein neuer Termin wurde erstellt.'
redirect_to :root
else
render :action => "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
welcome-view:
<div class="table-responsive">
<table class="table table-hover">
<tbody>
<% @user_schedules_date.sort.each do |date_time, schedules| %>
<!-- Datum -->
<tr class="thead success">
<th colspan="4" scope="col"><p><%= date_time.strftime("%A, %d.%m.%Y") %></p></th>
</tr>
<!-- /Datum_Ende -->
<!-- Titel, Zeit und Ort -->
<% for schedule in schedules %>
<tr>
<th scope="row"><p><%= schedule.titel %></p></th>
<td><p><%= schedule.date_time.strftime("%H:%M:%S") %></p></td>
<td><p><%= schedule.location %></p></td>
<td>
<p><%= link_to 'Bearbeiten', {:controller => 'schedule', :action => 'edit', :id => schedule.id} %></p>
<p><%= link_to 'Diesen Termin löschen', {:controller => 'schedule', :action => 'delete', :id => schedule.id} %></p>
</td>
</tr>
<% end %>
<!-- Titel, Zeit und Ort -->
<% end %>
</tbody>
</table>
</div>
<% end %>
If I add a schedule everything works fine. Edit also works fine.
If I delete a schedule it won't delete the relationship in the Join-Table.
Any Idea why? -> Solution: @schedule_delete.DESTROY
instead of @schedule_delete.delete
. So deleting/destroying a schedule also works fine.
So everything works fine.
Thank you for your help!
回答1:
Let me explain has_and_belongs_to_many for you
HABTM is basically a way for ActiveRecord to give you a join table
- your association gives you the ability to load the associative data you require through your join table.
Much like has_many :through
, HABTM provides a simple way to access the associative data of your models, however as it does not have a model, you will not be able to access the join data directly (as there's no primary key to load them with):
It basically takes the foreign_keys of your join table, and allows you to pull the associated data from either of the dependent models for you. You can't set
How can I add data to the schedules_users-table?
You'll have to use the collection ActiveRecord methods, specifically you'll have to ensure you are able to append records to the schedules
or users
associations:
#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
--
How can I get access to the added data in the schedules_users-table?
You can only access this data through the collection associations:
$ rails c
$ @user = User.find 1
$ @user.schedules.each do |schedule|
$ puts schedule #-> will output each schedule record
$ end
To access from your controller, you'll run exactly the same commands
回答2:
Just looked quickly, but looks pretty ok to me. However, since you changed your models from has_many to has_and_belongs_to_many you need to migrate your data if you want your old data to show up. Now you are getting no schedules for your users, this is correct since the schedules_users table is empty. Assuming you still have the user_id column in your schedules table you could do something like to migrate the data:
insert into schedules_users
(select id as schedule_id, user_id from schedules where user_id is not null);
来源:https://stackoverflow.com/questions/25033822/need-help-to-understand-has-and-belongs-to-many