I have 2 tables users and videos. I create another table (video_users)
to link them with easiness of rails.
On the view when user 1 clic play button to view video 1, user_id and
video_id are load automatically on table videos_users.
When user clic again, the same thing append on new record.
Example:
This is what happend on database:
user_id video_id
1 1
1 1
How can I have something like this?
user_id video_id number_view
1 1 2
Model User:
class User < ActiveRecord::Base
has_many :video_users
has_many :videos, through: :video_users
end
Model Video:
class Video < ActiveRecord::Base
has_many :video_users
has_many :users, through: :video_users
end
Model VideoUser
class VideoUser < ActiveRecord::Base
belongs_to :video
belongs_to :user
end
Migration video_users:
class CreateVideoUsers < ActiveRecord::Migration
def change
create_table :video_users do |t|
t.references :video, index: true
t.references :user, index: true
t.timestamps
end
end
end
When i tried to create column number_view, i have some error:
SQLite3::SQLException: no such table: videos_users: ALTER TABLE
“videos_users” ADD “number_view” integer DEFAULT 1
It looks like your join table is named “video_users” so within the
migration in which you try to create the column “number_view” you should
specify that name instead of “videos_users”.
On top of that I suggest you to specify the default value of 0 for
“number_view”:
t.integer :number_view, default: 0
so that you can simply increment that field and avoid the line:
video_user.number_view ||= 0
As a side note, it would be better to name join tables with the
convention
of putting the names alphabetically ordered and in the plural form. This
means that you could’ve named your join table “users_videos” because
“users” comes before “videos” and each of them is specified in the
plural
form.
Ho fatto tutto quello che hai detto. Grazie di cuore.
Funziona!
Però il record viene sempre creato e non va bene cosi.
La situazione è questa nel db:
L’user clicca per la prima volta:
user_id video_id number_view
1 1 1
Lo stesso user clicca sullo stesso video per la seconda volta:
user_id video_id number_view
1 1 2 --> Effetto del secondo click
1 1 0 --> Rails lo fa automaticamente secondo i
legami tra le tavole User, Video e VideoUser
Quindi viene sempre creato un nuovo record con il valore di default di
number_view.
current_user è l’user corrente, try è un metodo per l’eccezione
Ecco il metodo watch_video che è scritto nel model user
Ecco il colpevole
def watch_video video
videos << video
end
User e Video sono legati da una relazione has_many :through (vedi
“La
Guida” [0]), che condivide molti dei concetti (e metodi) delle relazioni has_and_belongs_to_many. È una relazione N:M tra due entità, User e Video, e come tale richiede la presenza della tabella d’appoggio
(video_users, rappresentata esplicitamente in ActiveRecord tramite la
classe VideoUser).
Il motivo per cui non hai potuto optare per la relazione has_and_belongs_to_many e hai dovuto invece scegliere has_many :through
è perché nel caso di has_and_belongs_to_many non puoi aggiungere
attributi specifici al legame tra le due entità (come la colonna number_view nel tuo caso).
Ok, tutto molto bello fino a qui.
Come dicevo prima, questo tipo di relazioni condivide alcuni metodi
d’utilità che ti permettono di gestire i record delle tabelle a livello
Ruby.
All’interno del contesto di una variabile d’istanza di User, puoi
avere
accesso a tutti i record di tipo Video collegati ad essa tramite il
metodo videos, il quale ti fornisce l’astrazione di un normale Array
Ruby (più o meno, dato che non è proprio un oggetto della classe Array,
quanto invece un oggetto della classe
ActiveRecord_Associations_CollectionProxy) e ogni volta che aggiungi un
elemento a videos (tramite videos << oggetto), vengono eseguite
delle
callback ActiveRecord che aggiornano lo stato del database, creando un
corrispondente record nella join table video_users.
Quindi, dato che con iterate_number_view te già stai creando e/o
aggiornando i record necessari, non hai più bisogno del metodo watch_video