Проблема
Я кодирую страницу профиля пользователя на 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).
- "Japanese" (выбирается оригиналом форма)
- "Engli sh" (добавлено и выбрано коконом)
В любом случае, пока можно сохранить только 1 язык.