2017-08-12 8 views
-1

enter image description here J'écris une application de liste de choses à faire. Chaque utilisateur peut avoir plusieurs catégories de la liste, et chaque catégorie de liste peut contenir plusieurs éléments de liste:Deux couches de has_many/belongs_to

class User < ApplicationRecord 
    has_many :list_categories, dependent: :destroy 
    has_many :list_items, through: :list_categories 

class ListCategory < ApplicationRecord 
    belongs_to :user 
    has_many :list_items, dependent: :destroy 

class ListItem < ApplicationRecord 
    belongs_to :list_category 

Dans la vue d'index du contrôleur list_category J'ai une liste des catégories et une forme pour la création de nouvelles catégories, qui fonctionne bien.

Chaque catégorie de la vue d'index comporte un lien vers l'action d'affichage pour cette catégorie. Dans l'affichage du spectacle, j'ai un formulaire pour créer de nouveaux éléments de liste pour cette catégorie (afin que la page d'affichage agisse effectivement comme la nouvelle page pour les éléments de liste) et le code pour afficher les éléments de liste déjà créés, mais je n'ai pas été en mesure d'obtenir l'un ou l'autre à travailler.

Dans le contrôleur list_categories je:

def show 
    @list_category = current_user.list_categories.find(params[:id]) 
    @list_item = @list_category.list_items.build 
    @list_items = @list_category.list_items 
end 

Dans le contrôleur list_items:

def create 
    @list_category = current_user.list_categories.find(params[:id]) 
    @list_item = @list_category.list_items.build(list_item_params) 
    redirect_to list_category_path(@list_category) 
end 

private 

    def list_item_params 
    params.require(:list_item).permit(:content) 
    end 

La forme que je suis en train d'utiliser est:

<%= form_for(@list_item) do |f| %> 
    <%= f.text_field :content %> 
    <%= f.submit "Add", class: "btn btn-primary" %> 
<% end %> 

Et le code pour afficher chaque élément de liste dans la catégorie de liste:

<% @list_items.each do |item| %> 
    <%= item.content %> 
<% end %> 

Lorsque je tente de présenter un élément de liste sous la forme dans l'action show, je reçois cette erreur dans le list_items contrôleur de créer l'action:

Impossible de trouver ListCategory sans ID

en raison de la ligne

@list_category = current_user.list_categories.find(params[:id]) 

Ai-je raison de penser, y compris @list_item comme argument form_for automatiquement mappe le formulaire à l'action de création list_item? Même lorsque je mets manuellement un numéro d'identification dans la ligne d'erreur et que j'essaie de créer un élément de liste, lorsque j'appelle la méthode list_items sur la catégorie correspondante, il indique qu'il ne contient aucun list_items, donc le for ne fonctionne toujours pas.

C'est le journal du serveur:

Started POST "/list_items" for 127.0.0.1 at 2017-08-12 13:33:24 +0100 
Processing by ListItemsController#create as HTML 
Parameters: {"utf8"=>"✓", "authenticity_token"=>"F9kqlwQryyCFsddetAWF4WcI8g2x3c2hMCfaHGWad8QT1OHeHmdvzIFtEoqB8iYyE7vi0CWN+BChFZrpc1VcYw==", "list_item"=>{"content"=>"task"}, "commit"=>"Add"} 
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] 
Completed 404 Not Found in 3ms (ActiveRecord: 0.1ms) 

ActiveRecord::RecordNotFound (Couldn't find ListCategory without an ID): 
+0

Pouvez-vous poster le journal du serveur qui est généré sur le formulaire soumettre? – Pavan

+0

Ajouté à la publication principale – mef27

Répondre

0

Cela a fonctionné pour un peu, mais quand je redémarré le serveur, etc il a commencé à ne pas me laisser passer le champ caché, parce que category_id et user_id ne sont pas dans les fortes params . Cependant, chaque élément nécessite un identifiant de catégorie à associer à la bonne catégorie, et nécessite également un id_utilisateur (j'ai l'intention d'afficher tous les éléments de l'utilisateur, quelle que soit la catégorie, sur la page d'accueil).

Je ne peux pas ajouter user_id aux paramètres forts pour des raisons de sécurité et category_id n'est peut-être pas bon non plus car cela peut entraîner l'accès d'un utilisateur à la catégorie d'un autre utilisateur. Si je supprime les champs masqués du formulaire, cela ne fonctionnera pas non plus car les validations du modèle échoueront. J'ai essayé d'obtenir quelque chose avec des itinéraires imbriqués pour travailler:

resources :users 
resources :categories, only: [:create, :destroy, :index, :show] do 
    resources :items, only: [:create, :destroy] 
end 

Et sous la forme:

<%= form_for(@item, url: category_items_path(@category)) do |f| %> 

modèle de l'article:

class Item < ApplicationRecord 
    belongs_to :category 
    belongs_to :user 
    default_scope -> { order(:deadline) } 
    validates :category_id, presence: true 
    validates :user_id, presence: true 

EDIT ---

Les routes imbriquées est la bonne approche et j'ai obtenu le code pour travailler en suivant les instructions dans les 2 vidéos suivantes:

https://www.youtube.com/watch?v=HVuawlZTLBw https://www.youtube.com/watch?v=WdaO0-DvjJw

1

Impossible de trouver le ListCategory sans ID

@list_category = current_user.list_categories.find(params[:id]) 

Vous récupérez list_category avec params[:id] qui est mal compte tenu de la params. Vous devriez avoir une hidden_field sous la forme pour stocker @list_category

<%= form_for(@list_item) do |f| %> 
    <%= f.text_field :content %> 
    <%= f.hidden_field :list_category_id, value: @list_category.id %> 
    <%= f.submit "Add", class: "btn btn-primary" %> 
<% end %> 

et accéder avec params[:list_item][:list_category_id] dans l'action list_items#create

@list_category = current_user.list_categories.find(params[:list_item][:list_category_id]). 

De plus, vous n'êtes pas sauver le list_items.Vous devez tordre l'action create au-dessous

def create 
    @list_category = current_user.list_categories.find(params[:list_item][:list_category_id]) 
    @list_item = @list_category.list_items.build(list_item_params) 
    if @list_item.save 
    redirect_to list_category_path(@list_category) 
    else 
    # your code for failed creation 
    end 
end 
+0

Merci beaucoup, ce code le résout! Doit ajouter 'value:' avant '@ list_category.id' dans le champ caché pour éviter l'erreur de fusion – mef27

+0

@ mef27 Content de l'aider :) S'il vous plaît marquer comme accepté en cochant la case en vert :) – Pavan

+0

@ mef27 Puis-je connaître la raison pour laquelle vous avez supprimé l'acceptation? – Pavan