[RubyOnRails] Comment implémenter le pull-down sur form_with en fonction des données de table

Contenu

En essayant d'introduire une sélection déroulante dans form_with et en l'implémentant, il y avait des endroits où j'ai répété des essais et des erreurs, donc je vais le laisser comme un rappel.

environnement

・ Rubis 2.6.5 ・ Rails 6.0.3

Situation préalable et ce que vous voulez faire

Statut

Il y a une table de magasin pour enregistrer les informations du restaurant. Il existe une table de station qui contient les données de station sur la ligne Yamate sous forme de liste. Les deux tables ont une relation plusieurs à plusieurs et forment une association via une table intermédiaire (table shop_station).

Chose que tu veux faire

Je souhaite implémenter les fonctions suivantes. ** ① Lors de la création de données de magasin, je souhaite sélectionner et enregistrer la station la plus proche dans le menu déroulant. ** ** ** ② L'enregistrement de la station la plus proche est facultatif et ne doit pas être enregistré. Vous pouvez enregistrer jusqu'à 2 stations. ** ** ** ③ Naturellement, je souhaite enregistrer toutes les stations les plus proches en même temps en soumettant le formulaire une fois. ** **

Je laisserai la procédure de montage ci-dessus pour rappel.

Eh bien, j'écrirai la procédure ci-dessous.

(1) Créer et implémenter des options déroulantes basées sur les données de table

Cette fois, nous implémenterons le formulaire dans la nouvelle action du contrôleur de boutique. Je vais d'abord extraire et écrire le code.

Controller

shops_controller.rb


before_action :set_select_lists, only: [:new]

def new
    @shop = Shop.new
  end

private
  def set_select_lists
    @stations = Station.all.map {|station| [station.name, station.id] }
  end

View

haml:new.html.haml


.shop-wrapper
  = form_with model: [@owner, @shop], html: {class: "shopform"}, local: true do |f|

-#Omission(L'indentation est appropriée pour mettre en évidence la syntaxe. Excusez-moi. Indentation selon la notation haml)

= f.select :station_ids, @stations,{},{class: "select"}
= f.select :station_ids, @stations,{},{class: "select"}
* En enregistrant la station la plus proche, elle sera affichée dans la recherche de désignation de station.

L'explication de chacun est la suivante.

Controller @stations crée les données qui serviront de base à ce choix. Ce qui suit est une explication approximative.

Station.all Toutes les données de la table Station

Station.all.map {~} Pour chaque donnée (enregistrement) de la table Station toutes les données, traiter selon {}

Station.all.map {|station| [station.name, station.id]} Génère un hachage avec chaque enregistrement comme station, station.name (valeur dans la colonne name de chaque enregistrement) comme clé et station.id (valeur dans la colonne id) comme valeur.

View

= f.select :station_ids, @stations,{},{class: "select"}

Envoyez des données avec form_with. Créez un menu déroulant avec f.select. Lors de l'envoi de données, envoyez-les avec la clé: station_ids. Les choix sont basés sur @stations. Le nom de la classe est select.

La clé définie dans le contrôleur est ** "choix affichés dans le menu déroulant" **, et la valeur est ** "valeur envoyée par les paramètres" **. Lorsque les gens choisissent, ils veulent choisir par nom de station, et lors de l'enregistrement des données, ils veulent s'associer par identifiant. C'est pourquoi j'ai défini la clé et la valeur de cette manière.

La figure qui les met en œuvre est la suivante.

スクリーンショット 2020-06-29 23.56.04.png

Deux des mêmes tiroirs sont alignés et un est ouvert. Il est certain que station.name est affiché en option.

② Rendre facultatif l'enregistrement de la station la plus proche

Dans l'image précédente, puisque la liste est faite à partir de données de table, ** il n'y a pas de "choix" de "ne pas sélectionner une station". ** ** Afin de rendre le commun "Veuillez choisir parmi ce qui suit", j'ai réécrit le contrôleur comme suit.

shops_controller.rb


def set_select_lists
    @stations = Station.all.map {|station| [station.name, station.id] }.unshift(["Veuillez choisir parmi les suivants", nil])
end

J'ai ajouté .unshift (["Veuillez choisir ci-dessous", nil]) à @stations plus tôt. unshift est une méthode qui ajoute un élément au tout début d'un tableau. Nous avons ajouté l'option de passer nil à la valeur avec la phrase "Veuillez choisir parmi les éléments suivants" comme clé.

L'ajout d'un enregistrement tel que "Il n'y a pas de station la plus proche" aux données de la table elle-même n'est pas préférable car le nombre d'enregistrements dans la table intermédiaire augmentera inutilement, j'ai donc ajouté l'option permettant de définir la valeur sur zéro par moi-même.

スクリーンショット 2020-06-30 0.01.57.png

Vous avez maintenant implémenté avec succès le menu déroulant souhaité.

③ Enregistrez toutes les stations les plus proches à la fois en soumettant le formulaire une fois

Je pensais pouvoir m'enregistrer à ce stade, mais lorsque j'ai en fait ignoré les données des paramètres, le problème suivant s'est produit. ** Puisque les deux menus déroulants envoient des données avec la clé du même nom que station_ids, le résultat est que la deuxième valeur écrase la première valeur et qu'une seule valeur est envoyée. ** **

C'était évident quand j'ai regardé binding.pry. Cependant, ce que je veux faire ici est d'envoyer et d'enregistrer plusieurs station_ids. Autrement dit, je veux envoyer ** station_ids sous forme de tableau **

Je pense qu'il y a plusieurs façons de le faire, mais j'ai réécrit la vue comme suit (c'est probablement une technique de puissance, mais j'ai pu l'utiliser sous la forme après cela)

haml:new.html.haml


= f.select :station_ids, @stations,{},{name: 'shop[station_ids][]', class: "select"}
= f.select :station_ids, @stations,{},{name: 'shop[station_ids][]', class: "select"}

L'attribut de nom est ajouté à l'état précédent. Si vous ajoutez l'attribut name dans form_with, vous pouvez spécifier ** "Comment envoyer les paramètres?" **.

Si vous regardez réellement les paramètres dans binding.pry, vous pouvez voir comment les données sont envoyées. station_ids sont envoyés sous la forme ** params [: shop] [: station_ids] **.

Je voulais en faire un tableau, donc en ajoutant [] à la fin de l'attribut name, je peux envoyer les deux données en toute sécurité sous la forme d'un tableau.

shops_controller.rb


def shop_params
    params.require(:shop).permit(:name, :address, :capacity, :owner_id, :genre_id, :mark_ids,introduces_attributes: [:content, :image, :number],station_ids: [])
end

En passant, j'ai mentionné plus tôt que les données ont été envoyées sous la forme de paramètres [: shop] [: station_ids], comme mentionné ci-dessus, avec le paramètre strong ** Tout d'abord, require: shop et appuyez sur la touche. Si vous le permettez, les données seront saisies en toute sécurité. ** ** J'ai bien compris cela dans binding.pry. Était drôle.

À la fin

La méthode à spécifier avec l'attribut name est assez puissante, alors dites-moi si vous rencontrez une méthode plus intelligente. Cependant, chaque valeur du formulaire après cela a également été implémentée avec cela.

J'ai appris le plus en voyant comment les paramètres sont envoyés dans binding.pry.

Recommended Posts

[RubyOnRails] Comment implémenter le pull-down sur form_with en fonction des données de table
Comment effacer toutes les données d'une table particulière
Comment implémenter la fonctionnalité de recherche dans Rails
Comment implémenter le calcul de la date en Java
Comment implémenter le filtre de Kalman par Java
Comment appliquer les conventions de codage en Java
Comment implémenter la fonctionnalité de classement dans Rails
Comment utiliser les variables d'environnement dans RubyOnRails
Comment implémenter le traitement asynchrone dans Outsystems
Comment écraser les données Firebase avec Swift
Comment implémenter une fonctionnalité similaire dans Rails
Comment créer facilement un pull-down avec des rails
Comment implémenter le verrouillage optimiste dans l'API REST
Notes sur la façon de rédiger des commentaires en anglais
Comment implémenter la pagination dans GraphQL (pour ruby)
Comment créer une combinaison unique de données dans la table intermédiaire des rails
Comment implémenter la connexion invité en 5 minutes sur le portefeuille de rails
Comment créer un URI de données (base64) en Java
[Ruby On Rails] Comment réinitialiser DB dans Heroku
Résumé de la mise en œuvre des arguments par défaut en Java
Remarques sur l'utilisation des expressions régulières en Java
Comment utiliser les données JSON dans la communication WebSocket (Java, JavaScript)
Comment afficher des graphiques dans Ruby on Rails (LazyHighChart)
Comment implémenter l'affichage sur une seule ligne de TextView dans le développement Android
Comment changer Java à l'ère d'OpenJDK sur Mac
Comment déployer avec heroku
[Rails] Comment mettre en œuvre le scraping
[Java] Comment implémenter le multithreading
Comment implémenter un travail qui utilise l'API Java dans JobScheduler
Comment faire fonctionner automatiquement un écran créé en Java sous Windows
Comment changer de version Java avec direnv dans le terminal sur Mac
Comment obtenir et ajouter des données depuis Firebase Firestore dans Ruby
Comment installer confortablement JDK 11 dans votre Mac
Comment utiliser Lombok au printemps
Implémenter un test piloté par table dans Java 14
Comment trouver May'n dans XPath
Comment masquer la barre de défilement dans WebView
Comment utiliser la méthode form_with
Comment déployer Laravel sur CentOS 7
Comment exécuter JUnit dans Eclipse
Comment itérer indéfiniment en Ruby
Essayez d'implémenter Yuma dans Ruby
Comment "évider" une vue sur Android
Remarques sur l'utilisation de Spring Data JDBC
Comment exécuter Ant dans Gradle
Comment maîtriser la programmation en 3 mois