Rails4: Formtastic3.0 , save multiple instances (f

2020-05-07 06:56发布

I have Question model and an answer model.

Each question can have one answer per user. I am trying to preset to a user a form to answer all questions, but couldnt really figure out how to do it with formtastic

Here is what I have so far

    - @questions.each do |q|
      = q.content
      - ans = @user.answers.where(question_id:q.id).first.try(:content) || q.description
      = semantic_form_for @answers do |f|
        = f.label q.content
        = f.inputs :content, placeholder: ans 
      = f.actions

I am trying to get some hint from How to loop through two alternating resources on a form? but I keep getting "undefined method `model_name' for Class:Class" for @questions if I try:

= semantic_form_for @questions do |q|
  = q.input :content
  = q.semantic_fields_for @answer do |a|
    = a.inputs :content
  = q.actions

Based on Railscast 198, but using formtastic here is my attempt that doesn't work either:

- semantic_form_for :Answer, :url => api_v1_answers_path, :method => :put do |f|
  - @questions.each do |q|
    - f.fields_for 'questions[]', q do |ff|
      = q.content
      = ff.input
  = submit_tag "Submit"

Note:

1] I will like to have user press submit only once after he has added/edited all the answers

2] If there is an answer already present, it should be pre-poulated in the text box

3] I dont mind using simple_form gem if that makes life easier

1条回答
老娘就宠你
2楼-- · 2020-05-07 07:27

Rather then making a form for @questions you need to pass a single object to your form helper (@questions is an array of questions). A good way to achieve this is though a form object.

# app/forms/questions_form.rb
class QuestionsForm
  include ActiveModel::Model

  def initialize(user)
    @user = user
  end

  def questions
    @questions ||= Question.all
  end

  def submit(params)
    params.questions.each_pair do |question_id, answer|
      answer = Answer.find_or_initialize_by(question_id: question_id, user: current_user)
      answer.content = answer
      answer.save
    end
  end

  def answer_for(question)
    answer = answers.select { |answer| answer.question_id == question.id }
    answer.try(:content)
  end

  def answers
    @answers ||= @user.answers.where(question: questions)
  end
end

Then in your controller you'd have:

# app/controllers/submissions_controller.rb
Class SubmissionsController < ApplicationController
  ...
  def new
    @questions_form = QuestionsForm.new(current_user)
  end

  def create
    @questions_form = QuestionsForm.new(current_user)

    @questions_form.submit(params[:questions_form])
    redirect_to # where-ever
  end
  ...
end

In your view you'll want something along the lines of:

# app/views/submissions/new.html.haml
= form_for @questions_form, url: submissions_path do |f|
  - @questions_form.questions.each do |question|
    %p= question.content
    = f.text_field "questions[#{question.id}]", value: @questions_form.answer_for(question)
  = f.submit "Submit"

This doesn't use formtastic at all, it's just using the plain rails form helpers.

This code isn't tested so not sure if it even works but hopefully it helps get you on the right track.

查看更多
登录 后发表回答