[RUBY] Enregistrement d'apprentissage qui a créé la fonction tweet avec le modèle STI

Le contenu de cet article est actuellement en attente de révision et pourrait changer!

Qu'est-ce que STI (single table inheritance)?

Laissez littéralement hériter une table de la classe parent à la classe enfant! Dans ce cas, le parent Tweet → enfant Mediatweet`` Texttweet. Classes pour les tweets médiatiques et les tweets texte, respectivement!

Cependant, comme les tables sont les mêmes, toutes les classes, parents et enfants, ont les mêmes colonnes. Ainsi, Mediatweet a aussi une colonne content, et ** Texttweet a aussi une colonne ʻimg`. ** **

db/schema.rb


  create_table "tweets", options: hogehoge
    t.text "content"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
    t.string "img"
    t.integer "user_id"
    t.string "type"
  end

Pourquoi fais-tu cela

Il sera plus facile d'écrire les différences dans le modèle. Par exemple, si vous écrivez une validation sans espaces uniquement dans le texttweet, l'image peut être tweetée sans texte. Cependant, comme le contenu est presque le même, les STI qui peuvent partager la table sont bonnes.

Méthode de mise en œuvre

  1. Il était déjà dans db / schema.rb, mais laissez la classe parent (table) avoir une colonne type (type chaîne).
  2. Fabriquez chaque modèle. Créez le modèle parent avec rails g model etc. et créez le modèle enfant etc. directement dans ʻapp / model /`

models/tweet.rb


class Tweet < ApplicationRecord
end

models/mediatweet.rb


class Mediatweet < Tweet
end

models/texttweet.rb


class Texttweet < Tweet
end

Pour le moment, c'est la fin de la mise en œuvre des STI. Le reste se fera automatiquement. Par exemple, si vous enregistrez la base de données avec Mediatweet.create etc., un enregistrement contenant Mediatweet et des données sera ajouté à la colonne type.

Distribution du modèle basée sur le contenu des paramètres acquis par form_with

Je veux trier les modèles automatiquement en fonction de l'existence ou non de données multimédias, je l'ai donc implémenté comme suit.

index.html.erb


<%= form_with model: @tweet, url: tweets_path do |form| %>
  <%= form.text_area :content %><br>
  <%= form.label "Télécharger l'image" %><br>
  <%= form.file_field :img %>
  <%= form.submit 'Publier' %><br>
<% end %>

Cette fois, c'est une page de publication et de liste qui a un formulaire de publication tel qu'il est dans l'index. Le téléchargeur d'images est implémenté dans carriewave. Je vais omettre cela. Les paramètres soumis en soumettant le formulaire ci-dessus sont

{
"authenticity_token"=>"hoge", 
"tweet"=>{"content"=>"hoge", "img"=>"hoge"}, 
"commit"=>"Publier"
}

Vous pouvez obtenir les paramètres d'une structure double comme celle-ci (une structure avec {} à l'intérieur {}).

Et il correspond automatiquement à l'action de création du contrôleur

tweets_controller.rb


  def create
    @tweet = tweettype_class.new(tweet_params)
    if @tweet.save
      redirect_to("/tweets")
    else
      @tweets = Tweet.all.order(created_at: :desc)
      render("index")
  #Le rendu revient à la page originale de la liste des articles._Si vous ne spécifiez pas l'URL de avec
  #form_La racine de with est tirée par le modèle enfant et une erreur se produit (par exemple)Anciennes tétines_chemin Après le rendu → tweets de texte_le chemin n'est pas grand-chose.
    end
  end
  private

  def tweet_params
  #Seule la partie où la clé est tweet est extraite par require({"content"=>"hoge","img"=>"hoge"})
    params.require(:tweet).permit(:content, :img).merge(user_id: @current_user.id)
  end
  #[:img]Les modèles sont triés selon la présence ou l'absence de données
  #Comme il a une structure double, la valeur ne peut pas être obtenue correctement à moins que la clé ne soit également spécifiée deux fois.
  def tweettype
    case
    when params[:tweet][:img].present?
      'mediatweet'
    when params[:tweet][:img].blank?
      'texttweet'
    end
  end
  #Convertit la chaîne de caractères reçue en cas de chameau,De plus, il est converti en un nom constant
  #(Exemple) mediatweet.cmelize=>Mediatweet.constantize=>Mediatweet(id: integer, content: text, created_at: datetime, hogehoge.... )
  def tweettype_class
    tweettype.camelize.constantize
  end

Comme ça, j'ai essayé de trier les modèles automatiquement selon que l'image était téléchargée ou non.

Cela a facilité l'écriture de différents rôles pour chaque modèle!

Recommended Posts

Enregistrement d'apprentissage qui a créé la fonction tweet avec le modèle STI
[Java] Implémenter une fonction qui utilise une classe implémentée dans le modèle Builder