Не может быть сохранено гнездо, образованное коконом - PullRequest
0 голосов
/ 12 апреля 2020

Проблема

Я кодирую страницу профиля пользователя на Rails. Я добавил жемчужину «выбор языка», чтобы пользователи могли выбрать язык, который они изучают. И пользователи могут изучать несколько языков, поэтому я также добавил гем "кокон". Первый язык, который выбирают пользователи, успешно сохраняется, но другие, выбранные Cocoon, не могут быть сохранены. Я хотел бы, чтобы они были сохранены и отображались на странице их профиля.

Как я достиг этой проблемы

Я добавил кокон, обновив эту страницу и код. README в github Однако кнопка «Сохранить» ничего не отреагировала, поэтому я сделал метод form_for «post».

<%= form_for @user, method: :post do |f| %>
  <div id='languages'>
    <%= f.fields_for :languages do |language| %>
      <%= render 'language_fields', :f => language %>
    <% end %>
    <div class='links'>
      <%= link_to_add_association 'add language', f, :languages %>
    </div>
  </div>
<% end %>

Затем кнопка «Сохранить» сработала, но произошла ошибка.

ActionController::InvalidAuthenticityToken in UsersController#update
ActionController::InvalidAuthenticityToken
Extracted source (around line #211):              

        def handle_unverified_request
          raise ActionController::InvalidAuthenticityToken
        end
      end
    end

Поэтому я добавил «protect_from_forgery with:: null_session» в application_controller.rb. Затем ошибка исчезла, но возникла проблема, о которой я говорил выше. Первый язык, который выбирают пользователи, сохраняется, но другие, выбранные коконом, не могут быть сохранены.

(users # show. html .erb)

<h2><%= @user.language %></h2>

(users # edit. html .erb)

        <%= form_tag("/users/#{@user.id}/update", {multipart: true}) do %>
        <table>
          <p>Languages</p>
            <%= select_tag(:language,options_for_select(languages)) %>
            <%= render 'users/form' %>
          <input type="submit" value="Submit">
        </table>
        <% end %>

(users # _form. html .erb)

Partial of cocoon.

<%= form_for @user, method: :post do |f| %>
  <div id='languages'>
    <%= f.fields_for :languages do |language| %>
      <%= render 'language_fields', :f => language %>
    <% end %>
    <div class='links'>
      <%= link_to_add_association 'add language', f, :languages %>
    </div>
  </div>
<% end %>

(users # _language. html .erb)

Частично кокон.

<div class='nested-fields'>
  <div class="field">
    <%= select_tag(:language,options_for_select(languages)) %>
  </div>
  <%= link_to_remove_association "remove language", f %>
</div>

(users_controller.rb)

Несмотря на то, что я установил "redirect_to (" / users / # {@ user.id} ")" здесь, он перенаправляет на "/ posts / index" после нажатия кнопки "Сохранить". И предложение «Вы уже вошли в систему», которое я поселил в «activid_login_user» в «application_controller.rb», также показано.

  before_action :authenticate_user, {only: [:index, :show, :edit, :update]}
  before_action :forbid_login_user, {only: [:new, :create, :login_form, :login]}
  before_action :ensure_correct_user, {only: [:edit, :update]}

  def edit
    @user = User.find_by(id: params[:id])
  end

  def user_params
    params.require(:user).permit(:name, :description, languages_attributes: [:id, :description, :done, :_destroy])
  end

  def update
    @user = User.find_by(id: params[:id])
    @user.language = params[:language]
    if params[:image]
      @user.image_name = "#{@user.id}.jpg"
      image = params[:image]
      File.binwrite("public/user_images/#{@user.image_name}", image.read)
    end
    if params[:cover_image]
      @user.cover_image_name = "#{@user.id}_cover.jpg"
      cover_image = params[:cover_image]
      File.binwrite("public/user_cover_images/#{@user.cover_image_name}", cover_image.read)
    end
    if @user.save
      flash[:notice] = "Edited user's information"
      redirect_to("/users/#{@user.id}")
    else
      render("users/edit")
    end
  end

(application_controller.rb)

class ApplicationController < ActionController::Base
  protect_from_forgery with: :null_session
  before_action :set_current_user

  def set_current_user
    @current_user = User.find_by(id: session[:user_id])
  end

  def authenticate_user
    if @current_user == nil
      flash[:notice] = "You need to log in"
      redirect_to("/login")
    end
  end

  def forbid_login_user
    if @current_user
      flash[:notice] = "You're already logged in"
      redirect_to("/posts/index")
    end
  end
end

Я добавлю больше кода, если на него нужно ссылаться. Большое спасибо.

Версия

ruby 2.6.4p104 / RubyGems 3.0.3 / Rails 5.2.3


Postscript

Когда я выбираю только один язык, его можно сохранить. Когда я выбираю несколько языков, как показано ниже, возникает проблема, которую я описал выше. Ничего не сохранено. Но после помещения "skip_before_action: verify_authenticity_token" в application_controller.rb, только "Engli sh" (последний) сохраняется (проверяется консолью rails).

  1. "Japanese" (выбирается оригиналом форма)
  2. "Engli sh" (добавлено и выбрано коконом)

В любом случае, пока можно сохранить только 1 язык.

...