Formulaire sur une collection d'objets

Par Xanatos, il y a 9 ans


Bonjour,

Pour les besoins d'une application, j'ai besoin de sortir du pattern habituel de RoR.

Ce que je fais

J'ai une liste de voitures (id, brand) avec système de CRUD classique.

# model class Car < ActiveRecord::Base validates :brand, presence: true end # controller def index @cars = Car.all end def new @car = Car.new end / view = simple_form_for @car do |f| = f.input brand

Ce que je veux

Plutôt qu'être dans un CRUD assez classique,
je souhaite avoir dès l'index un formulaire avec tous les véhicules dans des zones de texte (un peu à la méthode des nested fields)

Une solution que j'avais envisager, c'était de faire un modèle parent :
(exemple de code)

# model class Vehicle < ActiveRecord::Base has_many :cars accepts_nested_attributes_for :cars end class Car < ActiveRecord::Base validates :brand, presence: true end # controller def index @cars = Car.all end def new @vehicle = Vehicle.includes(:cars).where(cars: { id: params[:id] }).first end / view = simple_form_for @vehicle do |f| = f.simple_fields_for :cars do |c| = c.input :brand

Dans un soucis de 'perfectionnisme', ça ne m'intéresse pas de créer spécialement une table, et je souhaite savoir s'il y a un moyen plus propre ?

J'ai regardé du côté de la gem Reform de Trailblazer pour créer des "objets virtuels" composé d'une collection de voiture, je galère un peu et du coup je souhaitais avoir l'avis de développeur plus expérimenté :)

(Au delà de ce soucis, je souhaite également créer des formulaires avec des objets qui n'ont parfois aucun rapport, mais avec "1 seul bouton Enregistrer")

1 réponse

Xanatos, il y a 9 ans

La solution se cache dans la simplicité.

J'avais rapidement zappé les chapitres sur les helpers de Rails pour la création de formulaire et je suis allé quasi directement sur la gem Simple Form.

Cette gem est très bien pour des formulaires simples & classiques, mais dès que l'on veut faire des formulaires un peu plus élaboré, elle n'offre pas assez de souplesse.

Pour ceux que ça intéresse, une solution (améliorable) que j'ai trouvé, je met le code brute, il est je pense assez simple à compendre.

Routes

resources :cars match '/cars', to: 'cars#update_all', via: [:patch, :put]

Contrôleur

def index @cars = Car.all end def update_all cars_params = params.require(:cars) # à améliorer pour ne prendre que les champs autorisés # valeur de cars_params # { "1" => { "brand" => "Renault" }, "2" => { "brand" => "Peugeot" }, "3" => { "brand" => "Citroen" } } if Car.update(cars_params.keys, cars_params.values) redirect_to cars_path, :notice => "Les voitures ont été mises à jour." else @cars = Car.all render :index end end

Vue

= form_tag cars_path, { method: :put } do - @cars.each do |car| hr = fields_for "cars[]", car do |c| div = c.label(:brand, "Marque") = c.text_field(:brand) div = submit_tag("Mettre à jour")