Ceci est la suite de la section sur la création d'extensions dans le chapitre 14 du didacticiel Rails.
La fonction de réponse a été exécutée jusqu'à la dernière fois. Le deuxième ajout de fonction consiste à créer une fonction de message.
Pour le tutoriel
Twitter prend en charge la possibilité d'envoyer des messages directs. Implémentons cette fonctionnalité dans un exemple d'application
Puisqu'il y en a, vérifiez la fonction de Twitter.
(Indice: vous aurez besoin d'un modèle de message et d'une expression régulière correspondant au nouveau micro-message).
Le modèle Message est-il une fonctionnalité Rails? Je vais chercher sur le net.
Tout d'abord, vérifiez la fonction de Twitter.
L'autre personne doit vous suivre, à condition que vous puissiez envoyer des DM. Je créerai cette fonctionnalité plus tard.
Il existe également une fonction pour afficher read, mais cette fonction est abandonnée.
Vous pouvez configurer pour recevoir une notification push / notification par SMS (notification par courrier électronique court) / notification par courrier électronique lorsque vous recevez un DM. Je renoncerai également à cette fonction.
Vous pouvez également désactiver les DM de comptes spécifiques pour les empêcher de recevoir des notifications. J'abandonnerai également cette fonction.
Il existe également une fonction pour refuser les DM d'un compte spécifique. Vous pouvez bloquer votre adversaire. J'abandonnerai également cette fonction.
Vous pouvez supprimer le DM reçu. Je vais faire cette fonction. L'expéditeur ne peut pas supprimer le DM une fois qu'il a été envoyé.
DM et courrier ont des écrans différents.
Lorsque j'ai vérifié si le nombre maximal de caractères était différent, il était de 140 caractères jusqu'en juillet 2015 et de 10 000 caractères par la suite. Cette fois, j'utiliserai 140 caractères.
Après avoir vérifié si plusieurs destinations peuvent être utilisées, il y avait une fonction pour créer un groupe et parler avec plusieurs comptes. On dit qu'il a été achevé en janvier 2015, je vais donc abandonner cette fonction.
J'ai compris la fonction de Twitter, et j'ai pu imaginer la fonction à créer cette fois.
J'ai vérifié si le modèle Message est une fonction de Rails, mais je n'ai pas pu trouver un tel article. J'ai trouvé un article pour faire une fonction de chat par moi-même et un article pour faire un chat en temps réel, mais cela ne semble pas pertinent.
Définissez les spécifications du modèle. Relisez le tutoriel où vous créez un Micropost. Au chapitre 13, nous faisons d'abord un modèle en 13.1. Je vais faire un modèle de DM de la même manière.
Nom de colonne | attribut |
---|---|
id | integer |
content | text |
sender_id | integer |
receiver_id | integer |
created_at | datetime |
updated_at | datetime |
Modèle de figure DM
Ici, le récepteur est également lié au modèle utilisateur. Je pense que cette relation est la même que lorsque j'ai fait le modèle suivant, j'ai donc relu le tutoriel.
En relation, la suppression de l'utilisateur supprime également la relation. J'ai décidé de ne pas le supprimer dans DM. Ceci est différent.
En relation, ne pas suivre supprime également la relation. En DM, même si le destinataire supprime le DM, le DM ne disparaît pas et ne disparaît pas de l'écran de l'expéditeur. Il disparaît simplement de l'écran du destinataire. Réfléchissons à ce que cela signifie. La suppression de DM ne signifie pas qu'elle n'a pas été effectuée, mais le fait qu'il a été envoyé demeure. Comme le courrier électronique, lorsque le destinataire supprime le courrier électronique reçu, le courrier électronique envoyé par l'expéditeur n'est pas supprimé. Je l'ai essayé sur Twitter et c'était certain.
Pensez à un seau avec DM, comme un e-mail. Il s'agit d'un modèle dans lequel l'expéditeur et le destinataire ont des compartiments séparés. Lorsque vous envoyez un DM, vous en mettez un dans le compartiment de l'expéditeur et un dans le compartiment du destinataire. J'ai senti que mettre exactement le même message dans deux seaux était un double.
Je vais donc garder un bucket et ajouter un indicateur de suppression afin que le destinataire sache qu'il est supprimé.
J'ai recherché sur le net des attributs à mettre vrai ou faux et j'ai trouvé qu'il y avait un booléen et que je devrais toujours mettre la valeur par défaut. La raison en est que nul et faux sont traités de la même manière en rubis. https://qiita.com/jnchito/items/a342b64cd998e5c4ef3d
Ceci est le modèle modifié.
Nom de colonne | attribut |
---|---|
id | integer |
content | text |
sender_id | integer |
receiver_id | integer |
deleted | boolean |
created_at | datetime |
updated_at | datetime |
Modèle de figure DM
Créez une branche thématique.
ubuntu:~/environment/sample_app (master) $ git checkout -b create-dm
Générez un modèle dm.
ubuntu:~/environment/sample_app (create-dm) $ rails generate model dm content:text user:references
create db/migrate/20201102003220_create_dms.rb
create app/models/dm.rb
create test/models/dm_test.rb
create test/fixtures/dms.ymlrails generate mode dm content:text user:references
Changez la migration. J'ai créé l'index car il y a deux façons possibles, l'une est de spécifier l'expéditeur et de le récupérer en série chronologique, et l'autre est de spécifier le destinataire pour le récupérer en série chronologique. Pour la gestion des null du drapeau supprimé, je me suis référé à l'article précédent sur le net.
db/migrate/20201102003220_create_dms.rb
class CreateDms < ActiveRecord::Migration[5.1]
def change
create_table :dms do |t|
t.text :content
t.integer :sender_id
t.integer :reciever_id
t.boolean :deleted, default: false, null: false
t.timestamps
end
add_index :dms, [:sender_id, :created_at]
add_index :dms, [:receiver_id, :created_at]
end
end
Mettez à jour la base de données.
ubuntu:~/environment/sample_app (create-dm) $ rails db:migrate
Utilisateur associé et DM. Lisez 14.1.2 "Association utilisateur / relation" dans le didacticiel.
app/models/user.rb
class User < ApplicationRecord
has_many :microposts, dependent: :destroy
has_many :active_relationships,class_name: "Relationship",
foreign_key: "follower_id",
dependent: :destroy
has_many :passive_relationships, class_name: "Relationship",
foreign_key: "followed_id",
dependent: :destroy
has_many :following, through: :active_relationships, source: :followed
has_many :followers, through: :passive_relationships, source: :follower
has_many :sent_dms,class_name: "Dm",
foreign_key: "sender_id"
has_many :received_dms,class_name: "Dm",
foreign_key: "receiver_id"
app/models/dm.rb
class Dm < ApplicationRecord
belongs_to :sender, class_name: "User"
belongs_to :receiver, class_name: "User"
end
Dessinez un diagramme pour organiser les relations.
id | name |
---|---|
1 | Michael |
2 | Archer |
modèle d'utilisateur
has_many
sender_id | receiver_id | content |
---|---|---|
1 | 2 | ... |
1 | 3 | ... |
modèle dm
has_many
id | name |
---|---|
2 | Archer |
3 | ... |
modèle d'utilisateur Figure Relation utilisateur et DM
Les méthodes qui seront disponibles sont:
Méthode | Utilisation |
---|---|
user.sent_dms | Renvoie un ensemble de DM envoyés par l'utilisateur |
sent_dms.sender | Renvoie l'expéditeur |
sent_dms.receiver | Retourne le destinataire |
user.sent_dms.create(receiver_id: other_user.id) | Créer un DM en établissant un lien avec l'utilisateur |
user.sent_dms.create!(receiver_id: other_user.id) | Créer un DM en liant avec l'utilisateur (erreur de sortie en cas d'échec) |
user.sent_dms.build(receiver_id: other_user.id) | Renvoie un nouvel objet DM associé à l'utilisateur |
user.sent_dms.find_by(id:1) | Renvoie DM avec l'ID 1 associé à l'utilisateur |
Essayez-le sur la console. Créez dm1.
>> user1 = User.first
>> user2 = User.second
>> dm1 = user1.sent_dms.create(receiver_id: user2.id, content: "hoge dm1")
L'objet Utilisateur de l'expéditeur et du destinataire a été renvoyé.
>> dm1.sender
=> #<User id: 1, name: "Example User", email: "[email protected]", created_at: "2020-10-26 01:37:04", updated_at: "2020-10-26 01:37:04", password_digest: "$2a$10$2TZtcwmSTCfl9Bigz2nYGO8U1YA8ksfNXUr2O/fSGOY...", remember_digest: nil, admin: true, activation_digest: "$2a$10$EaQUKa6hfGEHosjnICR4VuYMxfOxunTOsPGQYUimNLn...", activated: true, activated_at: "2020-10-26 01:37:03", reset_digest: nil, reset_sent_at: nil, unique_name: "Example">
>> dm1.receiver
=> #<User id: 2, name: "Van Zemlak", email: "[email protected]", created_at: "2020-10-26 01:37:04", updated_at: "2020-10-26 01:37:04", password_digest: "$2a$10$H22BJeNVA3hYdEw/a5RArekRy73q/0AtvidwRiVpoUK...", remember_digest: nil, admin: false, activation_digest: "$2a$10$xm7AJE4Q3fzq3gi5tmVnyeld8wahxMHN/dE2Sn2jSUW...", activated: true, activated_at: "2020-10-26 01:37:04", reset_digest: nil, reset_sent_at: nil, unique_name: "Craig1">
Recherchez dans la liste des DM pour l'utilisateur, recherchez dm par identifiant.
>> user1.sent_dms
Dm Load (0.2ms) SELECT "dms".* FROM "dms" WHERE "dms"."sender_id" = ? LIMIT ? [["sender_id", 1], ["LIMIT", 11]]
=> #<ActiveRecord::Associations::CollectionProxy [#<Dm id: 2, content: "hogehoge", sender_id: 1, receiver_id: 2, deleted: false, created_at: "2020-11-02 02:27:35", updated_at: "2020-11-02 02:27:35">, #<Dm id: 3, content: "hoge dm1", sender_id: 1, receiver_id: 2, deleted: false, created_at: "2020-11-03 00:21:40", updated_at: "2020-11-03 00:21:40">]>
>> user1.sent_dms.find_by(receiver_id: 2)
Dm Load (0.4ms) SELECT "dms".* FROM "dms" WHERE "dms"."sender_id" = ? AND "dms"."receiver_id" = ? LIMIT ? [["sender_id", 1], ["receiver_id", 2], ["LIMIT", 1]]
=> #<Dm id: 2, content: "hogehoge", sender_id: 1, receiver_id: 2, deleted: false, created_at: "2020-11-02 02:27:35", updated_at: "2020-11-02 02:27:35">
J'ai besoin d'une liste de DM pour le destinataire. Lisez le tutoriel car suivi a la même structure. La méthode est probable, alors essayez-la sur la console.
>> user2.received_dms
Dm Load (0.1ms) SELECT "dms".* FROM "dms" WHERE "dms"."receiver_id" = ? LIMIT ? [["receiver_id", 2], ["LIMIT", 11]]
=> #<ActiveRecord::Associations::CollectionProxy [#<Dm id: 2, content: "hogehoge", sender_id: 1, receiver_id: 2, deleted: false, created_at: "2020-11-02 02:27:35", updated_at: "2020-11-02 02:27:35">, #<Dm id: 3, content: "hoge dm1", sender_id: 1, receiver_id: 2, deleted: false, created_at: "2020-11-03 00:21:40", updated_at: "2020-11-03 00:21:40">]>
J'ai un modèle, mais je me demande si j'ai toutes les méthodes dont j'ai besoin pour mes besoins.
Examinez à nouveau l'écran Twitter. L'écran DM a une structure parent-enfant et l'écran parent est une liste d'utilisateurs qui ont interagi les uns avec les autres dans le passé. Lorsque vous sélectionnez un utilisateur, c'est un écran qui répertorie les échanges DM.
Une méthode obligatoire est celle qui renvoie une liste d'utilisateurs avec lesquels vous avez interagi dans le passé. Lorsque j'ai recherché find sur le net, j'ai trouvé que la condition OR peut être utilisée dans where. https://qiita.com/nakayuu07/items/3d5e2f8784b6f18186f2 Essayez-le sur la console.
>> Dm.where(sender_id: 1).or(Dm.where(receiver_id: 1))
Dm Load (0.1ms) SELECT "dms".* FROM "dms" WHERE ("dms"."sender_id" = ? OR "dms"."receiver_id" = ?) LIMIT ? [["sender_id", 1], ["receiver_id", 1], ["LIMIT", 11]]
=> #<ActiveRecord::Relation [#<Dm id: 2, content: "hogehoge", sender_id: 1, receiver_id: 2, deleted: false, created_at: "2020-11-02 02:27:35", updated_at: "2020-11-02 02:27:35">, #<Dm id: 3, content: "hoge dm1", sender_id: 1, receiver_id: 2, deleted: false, created_at: "2020-11-03 00:21:40", updated_at: "2020-11-03 00:21:40">]>
>> Dm.where(sender_id: 2).or(Dm.where(receiver_id: 2))
Dm Load (0.1ms) SELECT "dms".* FROM "dms" WHERE ("dms"."sender_id" = ? OR "dms"."receiver_id" = ?) LIMIT ? [["sender_id", 2], ["receiver_id", 2], ["LIMIT", 11]]
=> #<ActiveRecord::Relation [#<Dm id: 2, content: "hogehoge", sender_id: 1, receiver_id: 2, deleted: false, created_at: "2020-11-02 02:27:35", updated_at: "2020-11-02 02:27:35">, #<Dm id: 3, content: "hoge dm1", sender_id: 1, receiver_id: 2, deleted: false, created_at: "2020-11-03 00:21:40", updated_at: "2020-11-03 00:21:40">]>
Cette recherche ne permet pas la fonction des écrans parent et enfant. Tous les DM de tous les adversaires sont mélangés. À ce stade, il s'est avéré que les spécifications n'étaient pas pleinement explorées. La fonction de création d'un écran pour chaque partenaire DM sera promue si elle peut être créée ultérieurement.
Faites un test du modèle. Faire la validation DM en référence à Micropost. Lisez 13.1.2 "Validation Micropost" dans le tutoriel. Le fichier DM de l'appareil est un échantillon, supprimez-le.
test/models/dm_test.rb
class DmTest < ActiveSupport::TestCase
def setup
@sender = users(:michael)
@receiver = users(:archer)
@dm = Dm.new(content: "hogehoge1", sender_id: @sender.id, receiver_id: @receiver.id)
end
test "should be valid" do
assert @dm.valid?
end
test "sender should be present" do
@dm.sender_id = nil
assert_not @dm.valid?
end
test "receiver should be present" do
@dm.receiver_id = nil
assert_not @dm.valid?
end
test "contentr should be present" do
@dm.content = nil
assert_not @dm.valid?
end
test "contentr should be at most 140 characters" do
@dm.content = "a" * 141
assert_not @dm.valid?
end
end
Ajoutez une validation pour le même que micropost. Le test est maintenant VERT.
app/models/dm.rb
class Dm < ApplicationRecord
belongs_to :sender, class_name: "User"
belongs_to :receiver, class_name: "User"
validates :content, presence: true, length: { maximum: 140 }
end
Changez la méthode lors de la création d'un DM de la manière habituellement correcte.
test/models/dm_test.rb
def setup
@dm = @sender.sent_dms.build(content: "hogehoge1", receiver_id: @receiver.id)
end
Fait revenir les DM dans l'ordre chronologique. Lisez 13.1.4 "Amélioration des micropostes". Écrivez d'abord le test.
test/models/dm_test.rb
class DmTest < ActiveSupport::TestCase
...
test "order should be most recent first" do
assert_equal sent_dms(:most_recent), Dm.first
end
end
Créez des données de relation parent-enfant dans l'appareil. https://qiita.com/seimiyajun/items/ffefdfc74b9fce76a538 Je l'ai mentionné.
test/fixtures/dms.yml
morning:
content: "Good morning!"
sender: michael
receiver: archer
created_at: <%= 10.minutes.ago %>
Définis de manière à ce qu'ils soient organisés dans l'ordre de created_at. Le test est maintenant VERT.
app/models/dm.rb
class Dm < ApplicationRecord
belongs_to :sender, class_name: "User"
belongs_to :receiver, class_name: "User"
default_scope -> { order(created_at: :desc) }
validates :content, presence: true, length: { maximum: 140 }
end
Pensez à ajouter: détruire. Lorsque l'utilisateur a été supprimé, le DM précédent a été décidé de rester. Ajoutez ce test. Reportez-vous au Listing 13.20.
test/models/user_test.rb GREEN
test "associated dms should not be destroyed" do
@user.save
@user.sent_dms.create!(content: "Lorem ipsum", receiver_id: users(:archer).id)
assert_no_difference 'Dm.count' do
@user.destroy
end
end
end
Le modèle a été achevé jusqu'à présent.
8,5 heures du 31/10 au 06/11.
Recommended Posts