Home>

I am making a user profile screen with Rails.
I implemented it using a gem called language-select so that the user can select "the language I'm studying". Also, since the user may be studying multiple languages, this time I used a gem called cocoon so that I can add/remove select tags for language selection asynchronously.

However, the problem is from here, the language that the user first selected is saved firmly, but the language added and selected by cocoon is not saved well.
I want to save the information added/selected by the user well and display it on the profile screen.

Flow to the problem

The implementation of cocoonREADME on githubOrThis pageI did it with reference to.
However, in the same code, there was no response when I pressed the "Save" button, so I made the method of form_for that seems to be applicable to post.

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

Then it started to react, but this time the following error was displayed.

ActionController :: InvalidAuthenticityToken in UsersController # update
ActionController :: InvalidAuthenticityToken
Extracted source (around line # 211):
        def handle_unverified_request
          raise ActionController :: InvalidAuthenticityToken
        end
      end
    end

This has been resolved by adding the sentence "protect_from_forgery with:: null_session" to application_controller.rb.
I was wondering if I could finally confirm the implementation, but as mentioned above, the problem is that the language first selected by the user is saved, but the language added and selected by cocoon is not saved. It has occurred.

Corresponding source code (users#show.html.erb)
<% = @ user.language%>
Corresponding source code (users#edit.html.erb)
    <% = form_tag ("/ users/# {@ user.id}/update", {multipart: true}) do%>    <table>      <p>Language</p>        <% = select_tag (: language, options_for_select (languages))%>        <% = render'users/form'%>      <input type = "submit" value = "save">    </table>    <% end%>
Corresponding source code (users#_form.html.erb)

It is a partial of cocoon.

<% = form_for @user, method:: post do | f |%>  <% = f.fields_for: languages ​​do | language |%>  <% = render'language_fields',: f =>language%><% end%>      <% = link_to_add_association'add language', f,: languages%>  <% end%>
Corresponding source code (users#_language.html.erb)

This is the second part of cocoon.

  <% = select_tag (: language, options_for_select (languages))%><% = link_to_remove_association "remove language", f%>
Corresponding source code (users_controller.rb)

Also, I set "redirect_to ("/users/# {@ user.id} ")" here, but immediately after putting the sentence "protect_from_forgery with :: null_session" in application_controller.rb, it goes to the corresponding page. It will be redirected, but after that it will be redirected to "/ posts/index". At that time, the "already logged in" flash set in forbid_login_user in application_controller.rb is also displayed.

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 information"
      redirect_to ("/ users/# {@ user.id}")
    else else
      render ("users/edit")
    end
  end
Corresponding source code (application_controller.rb)
class ApplicationController</pre>
<p><br />
If there is any other necessary code, I will add it. I would be grateful if anyone could borrow the wisdom.</p>
<strong>Supplementary information (FW/tool version, etc.)</strong>
<p>ruby 2.6.4p104<br />
RubyGems 3.0.3<br />
Rails 5.2.3</p>
<strong>Postscript</strong>
<p>Since it has not been solved yet, I deleted the part duplicated with cocoon that had a problem by commenting out, and proceeded with the work of changing form_tag to form_with. Again, I had the problem that pressing the save button didn't save the content and redirected me to "/ posts/index" (probably due to forbid_login_user).<br />
I'm not trying to go to a page that I can't access while logged in (new registration page, etc.), but I don't understand why this redirect happens ...</p>
<strong>Corresponding source code (users#edit.html.erb)</strong>
<pre><code data-language = "Rails">    <% = form_with (model: User, local: true) do | f |%>      <p>        <% = f.label: username%>        <% = f.text_field: name, value: @ user.name%>      </p>      <p>        <% = f.label: Image%>        <% = f.file_field: image%>      </p>      <p>        <% = f.label: Cover image%>        <% = f.file_field: cover_image%>      </p>      <p>        <% = f.label: Email address%>        <% = f.email_field: email, value: @ user.email%>      </p>      <p>        <% = f.label: Gender%>        <% = f.radio_button: sex,: Male%>Male
          <% = f.radio_button: sex,: Female%>Female
        </p>      <p>        <% = f.label: Nationality%>        <% = f.country_select: country, selected: @ user.country%>      </p>      <p>        <% = f.label: Language%>        <% = select_tag (: language, options_for_select (languages))%>      </p>      <p>        <% = f.label: Self-introduction%>        <% = f.text_area: introduction, rows: "10", cols: "100", value: @ user.introduction%>      </p>      <% = f.submit "save"%>    <% end%>