1
votes

Exception de contrôleur d'action méthode non définie `merge 'pour xxx: chaîne

Je fais de simples sites comme Reddit. J'essaie d'ajouter un bouton aux articles de rapport. Je crée un modèle de rapport , en utilisant button_to J'essaie de publier des données sur le contrôleur de rapport pour le créer mais j'ai reçu NoMethodError dans ReportsController # create fusion de méthode non définie 'pour "post_id": String

model / report.rb

= button_to "Report", reports_path, method: :post, params: {post: post}

report_controller.rb

class ReportsController < ApplicationController
  def create
    report = Report.new(report_params)

    flash[:notice] = if report.save
                       'Raported'
                     else
                       report.errors.full_messages.join('. ')
                     end
  end

  def report_params
    params.require(:post).merge(reporting_user: current_author.id)
  end

end


2 commentaires

Pouvez-vous s'il vous plaît ajouter tous les paramètres ? Je pense que le problème sera dans la méthode report_params , mais j'aimerais être précis.


J'ajoute des paramètres entiers dans le premier message


3 Réponses :


0
votes

Paramètre ActionController"> require renvoie la valeur de la clé requise dans les paramètres. Il s'agit généralement d'un objet renvoyé depuis un formulaire. Dans cet exemple nécessite renverrait {name: "Francesco", age: 22, role: "admin"} et la fusion fonctionnerait.

Votre vue renvoie les paramètres que Rails met en forme dans {post: 'string'} . Nous aurions besoin de voir votre code de vue pour déterminer ce qui doit exactement changer.

Mise à jour: À partir du nouveau code publié, nous pouvons voir que le paramètre renvoyé est "post" => "1" . Normalement, nous attendons un message: {id: 1, ...} .

Mise à jour: le bouton de la vue nécessiterait la mise à jour de la clé params en quelque chose d'ala params: {post: {id: post.id}} < / s> EDIT: J'accepte que params: {report: {post_id: post}} est un meilleur format.


0 commentaires

0
votes

Le problème semble provenir de report_params . Lorsque vous appelez params.require (: post) , il récupère: post de params -> le résultat est une chaîne. Et vous appelez merge sur cette chaîne.

Je recommanderais un changement de vue:

def report_params
  params.require(:report).permit(:post_id).merge(reporting_user_id: current_author.id)
end

puis dans le contrôleur:

= button_to "Report", reports_path, method: :post, params: { report: { post_id: post} }

Notez que j'ai également changé la dénomination selon les conventions: model_id pour id du modèle, modèle ou modèle lui-même.


1 commentaires

Quand je passe à params.require (: report) ... j'ai ActiveModel :: ForbiddenAttributesError



2
votes

Pour commencer, vous voulez utiliser appartient_à et non has_one.

@report = @post.reports.new(report_params) do |r|
  r.reporting_user = current_user
end

Cela place correctement le post_id code> colonne de clé étrangère sur les rapports . L'utilisation de has_one place la colonne fk sur posts , ce qui ne fonctionnera pas.

Et une solution généralement meilleure serait de créer des rapports une ressource imbriquée :

= button_to "Report", post_reports_path(post), method: :post

Cela permet vous simplifiez le bouton pour simplement:

# /config/routes.rb
resources :posts do
  resources :reports, only: [:create]
end

# app/controller/reports_controller.rb
class ReportsController
  before_action :set_post

  # POST /posts/:post_id/reports
  def create
    @report = @post.reports.new(reporting_user: current_author)
    if @report.save
      flash[:notice] = 'Reported'
    else
      flash[:notice] = report.errors.full_messages.join('. ')
    end
    redirect_to @post
  end

  private

  def set_post 
    @post = Post.find(params[:post_id])
  end
end

Puisque le post_id fait partie du chemin, nous n'avons pas besoin d'envoyer de paramètres supplémentaires. p>

Si vous souhaitez permettre à l'utilisateur de transmettre des informations supplémentaires via un formulaire à l'avenir, une meilleure façon de créer / mettre à jour des ressources avec des paramètres et des données de session est de passer un bloc:

class Report < ApplicationRecord
  belongs_to :reporting_user, class_name: 'Author'
  belongs_to :post
end


2 commentaires

Merci. C'est presque du travail, mais maintenant j'ai l'erreur impossible d'écrire l'attribut inconnu 'reporting_user_id'


Vous devez vous assurer que votre tableau de rapports comporte des colonnes reporting_user_id et post_id . Si ce n'est pas le cas, vous devez les ajouter via une migration.