Wypełnianie ankiety z użyciem JSON i AJAX

Witam :smile:

nie bardzo mogę/wiem jak poradzić sobie z problemem tworzenia ankiety, a mianowicie:

mam sobie traki przykładowy widok gdzie użytkownik wybiera skalę znajomości języka, jak wybierze to AJAX tworzy nową instancje z daną wartością, a robię to tak:

controller:

def create
@answer_questionnaire = AnswerQuestionnaire.new answer_questionnaire_params

respond_to do |format|
  if @answer_questionnaire.save
    format.json { render json: @answer_questionnaire  }
  else
    format.html { render :new }
    format.json { render json: @answer_questionnaire.errors, status: :unprocessable_entity}
  end
end
end

coffee:

$.ajax({
  type: "POST",
  url: "/answer_questionnaires",
  data: { answer_questionnaire: { answer: $(this).val() } },
  success:(data) ->
    console.log "OK"
  error:(data) ->
    console.log "NO"
})

i teraz nie wiem jak zrobić żeby edytować tą już wybraną wartość :wink:

Pogubiłem się trochę. Zakładam że załączasz widok new - tak wnioskuję z tego że dołączasz też create :slight_smile:

Kiedy wywołujesz ten CS? Po submicie formularza? Po zmianie wpisu w danym polu? Niestety tego nie załączyłeś w kodzie.

Jeśli robisz create, to z gruntu nie powinieneś tego potem próbować edytować, bo do tego jest edit… wydaje mi się też że coś za bardzo kombinujesz z zapisywaniem tego forma, ale to takie moje gdybanie nie widząc kodu do forma i nieco więcej CSa :slight_smile:

Mam widok strony:

- @question_questionnaire.each do |qq|
  %table.table
    %tr.headline-questionnarie
      %td{colspan: '2'}
        = qq.name
    - @response = Response.where(question_questionnaire_id: qq.id)
    - @response.each do |r|
    %tr
      %td.first-column-questionnaire
        = r.name
      %td.second-column-questionnaire
        - if r.descriptive_response
          = render 'answer_questionnaires/descriptive_response_form'
        - else
          = render 'answer_questionnaires/scale_form'

descriptive_response_form:

= simple_form_for @answer_questionnaire do |f|
  = f.input :answer, :input_html => { class: "input_questionnaire"}, label: false

scale_form

= simple_form_for @answer_questionnaire do |f|
  = f.input :answer, collection: 0..5, :input_html => { class: "input_questionnaire"}, label: false

coffee

$ ->
  $(document).on "change", ".input_questionnaire", ->
    $.ajax({
      type: "POST",
        url: "/answer_questionnaires",
        data: { answer_questionnaire: { answer: $(this).val() } },
       success:(data) ->
         console.log "OK"
       error:(data) ->
         console.log "NO"
    })

A teraz spróbuję to wyjaśnić :smiley:

Po wybraniu wartości z select-a ajax-em tworzę nową instancję i chodzi o to że jak później zmienię wartość tego select-a to żeby zrobić update ajax-em

Spróbuj zrobić coś takiego:

    $ ->
  $(document).on "change", ".input_questionnaire", ->
    type = $(this).data('answer-id') === 'undefined' ? 'POST' : 'PUT'
    id = $(this).data('answer-id') === 'undefined' ? 's' : ('/' + $(this).data('answer-id'))
    $.ajax({
      type: type,
        url: "/answer_questionnaire" + id,
        data: { answer_questionnaire: { answer: $(this).val() } },
       success:(data) ->
         // jeśli to był post, wyciągnij tu sobie id z danych zwracanych i
         $(this).data('answer-id', id_pobrany_z_data)
       error:(data) ->
         console.log "NO"
    })

To oczywiście tylko taka koncepcja. Generalnie chodzi o to, że jak zrobisz create takiego obiektu, to zassij sobie informację o jego ID i dalsze zapytania do tego samego obiektu rób już PUT/PATCH pod inny adres.

Ta linia może być trochę dzika:

        id = $(this).data('answer-id') === 'undefined' ? 's' : ('/' + $(this).data('answer-id'))

Szczególnie to ‘s’. Chodzi o to, że jak to doklejamy do adresu, o tu:

url: "/answer_questionnaire" + id,

To dla POST chcemy uzyskać answer_questionnaires, a dla PUT answer_questionnaire/:id.

Kod powyżej to tylko taka luźna koncepcja, oczywiście nie testowałem tego - no i moje doświadczenie z CoffeeScriptem jest bardziej ubogie niż bym chciał, więc możesz musieć sobie przełożyć to bardziej z JS na CS.

a no właśnie i co zrobić dalej z tym ID ?

Właściwie nic, samo się robi :smile: Jak się przyjrzysz temu fragmentowi kodu który wyżej wrzuciłem, to ID ląduje w data-attribute o nazwie ‘answer-id’, na podstawie którego na samym początku funkcji jest wybierana metoda (POST lub PUT) i wykonywane zapytanie albo do create, albo do update.

Przynajmniej w teorii, mogą tam być jakieś bugi, chodziło bardziej o ogólną ideę. (Aż tyle czasu żeby robić sobie appkę testową i sprawdzać czy to jest idealnie nie mam :smiley: )

Jak by ktoś miał podobny problem to po podpowiedziach @paweljw rozwiązałem to tak:

$ ->
  $(document).on "change", ".input_questionnaire", ->
    thisInput = $(this)
    type = if thisInput.data('answer-id') is null then "POST" else "PUT"
    id = if thisInput.data('answer-id') is null then "" else ('/' + thisInput.data 'answer-id')
    $.ajax({
      type: type,
      url: "/answer_questionnaires" + id,
      data: { answer_questionnaire: { answer: $(this).val() } },
      success:(data) ->
        thisInput.data 'answer-id', data.id
        return true
      error:(data) ->
    })
1 Like