【问题标题】:form_for nested attributes: create doesn't save to DBform_for 嵌套属性:创建不保存到数据库
【发布时间】:2019-11-27 14:43:20
【问题描述】:

我有一个用户模型和一个配置文件模型。用户

has_one :profile, dependent: :destroy
after_create :create_profile
has_many :reviews, dependent: :destroy
accepts_nested_attributes_for :profile

因此,在注册后用户被重定向到 new_user_profile_path 以创建个人资料

class Users::RegistrationsController < Devise::RegistrationsController
    protected
      def after_sign_up_path_for(resource)
        new_user_profile_path(current_user.id)
      end
end

Profile#new 有一个 form_for 嵌套属性,如下所示

<%= form_for(@user, url: user_profile_path(@user), method: :post) do |f| %>
  <%= f.fields_for :profile, @profile do |profile_fields| %>
    <div class="field">
      <%= profile_fields.label :about %>
      <%= profile_fields.text_area :about %>
    </div>

    <div class="field">
      <%= profile_fields.file_field :avatar %>
      <% profile_fields.label "Profile photo" %>
    </div>

  <% end %>


    <div class="field">
        <%= f.label :street %>
        <%= f.text_area :street %>
    </div>

  <div class="actions">
    <%= f.submit %>
  </div>

<% end %>

问题是,此表单既不保存到用户也不保存到配置文件。参数传递如下

Parameters: {"utf8"=>"✓", "authenticity_token"=>"some_token", "user"=>{"profile_attributes"=>{"about"=>"mpl", "avatar"=>#<ActionDispatch::Http::UploadedFile:0x00007fb710cc4a88 @tempfile=#<Tempfile:/var/folders/0q/y8_xn1q57wn1_x9zhph1fpz00000gn/T/RackMultipart20191127-9283-sjkiqb.jpg>, @original_filename="055g.jpg", @content_type="image/jpeg", @headers="Content-Disposition: form-data; name=\"user[profile_attributes][avatar]\"; filename=\"055g.jpg\"\r\nContent-Type: image/jpeg\r\n">}, "street"=>"nmp"}, "commit"=>"Update User", "user_id"=>"14"}

表单有一个提交按钮,默认状态为“更新用户”,所以我想也许我需要在用户中使用更新方法,以使其工作。但这没有帮助。这是我的用户控制器

class UsersController < ApplicationController

  def index
    @users = User.all
  end

  def new
    @user = User.new
  end

  def create
    @user = User.new(user_params)
    @user.save
  end

  def update
    current_user.update_attributes(user_params)
    redirect_to user_profile_path(@user)
  end

  private

  def user_params
    params.require(:user).permit(:email, :password, :password_confirmation, :remember_me, :first_name, :last_name, :street, :house_number, :city, :zip_code, profile_attributes: [:about, :avatar])
  end

end

还有我的 ProfilesController:

class ProfilesController < ApplicationController
  before_action :set_profile, only: [:show, :edit, :update, :destroy]

  def show
    @user = User.eager_load(:profile).find(params[:user_id])
    @profile = @user.profile
    @review = Review.new
    @reviews = Review.where(profile: @profile) 
  end

  def new
    @user = current_user
    @profile = Profile.new
  end

  def edit
    @profile = @user.profile
  end

  def create
    @user = current_user
    @profile = @user.build_profile(profile_params)

    respond_to do |format|
      if @profile.save
        format.html { redirect_to user_profile_path(current_user.id), notice: 'Profile was successfully created.' }
        format.json { render :show, status: :created, location: @profile }
      else
        format.html { render :new, notice: 'Did not save' }
        format.json { render json: @profile.errors, status: :unprocessable_entity }
      end
    end
  end

  def update
    respond_to do |format|
      if @profile.update(profile_params)
        format.html { redirect_to user_profile_path(current_user.id), notice: 'Profile was successfully updated.' }
        format.json { render :show, status: :ok, location: @profile }
      else
        format.html { render :edit }
        format.json { render json: @profile.errors, status: :unprocessable_entity }
      end
    end
  end

  def destroy
    @profile.destroy
    respond_to do |format|
      format.html { redirect_to users_url, notice: 'Profile was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  private

    def set_profile
      @profile = current_user.profile
    end

    def profile_params
      params.permit(:about, :avatar)
    end

end

我到处查看,也在这里查看Unpermitted Parameters Accepts Nested Attributes 的形式,但我所做的一切都无法将其保存到数据库中。另外,我试过了

params.require(:profile).permit(:about, :avatar)

但它返回了一个非常奇怪的错误:

ActiveSupport::MessageVerifier::InvalidSignature @profile = Profile.new(profile_params)

我做错了什么?我是 Rails 的新手,我真的被困住了。

附:这是我的用户模型

class User < ApplicationRecord
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable,
         :omniauthable, omniauth_providers: %i[facebook]


    has_one :profile, dependent: :destroy
    after_create :create_profile
    has_many :reviews, dependent: :destroy
    accepts_nested_attributes_for :profile
    validates :first_name, presence: true
    validates :last_name, presence: true

    def self.from_omniauth(auth)
        where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
            user.email = auth.info.email
            user.password = Devise.friendly_token[0, 20]
            name = auth.info.name
            user.first_name = name.split(" ")[0]
            user.last_name = name.split(" ")[1] 
        end
    end
end

【问题讨论】:

  • 请将您的用户类添加到问题中。
  • 您使用的是哪个版本的 Rails?您的 form_for 声明可能只是 form_for @user do --> 为什么不使用它?
  • 我试过了,但没用。我绝对确定,这不是我的问题
  • user_profile_path 将指向ProfileController,但您的表单正在创建一个:user 来保存。您能否向我们展示一下日志文件 (development.log),我们可以在其中看到 1) 在保存时实际命中了哪个控制器,以及 2) 发送了哪些数据(以及哪些数据将被强参数阻止)。
  • 嗯,我真的很想保存到个人资料。所以,基本上,当保存时,会显示用户属性,比如个人资料页面上的街道以及个人资料属性,比如关于。用户正在注册时创建,此表单仅更新创建的用户。是的,表单引用了配置文件控制器,但我在配置文件控制器中的创建操作不会保存。我知道,我可以将地址添加到配置文件,而不是 ser,这可以解决问题。但我迫切希望找到适合我现在所拥有的解决方案。

标签: ruby-on-rails


【解决方案1】:

所以,这似乎是对我的问题的一个很好的答案,但不是解决方案,所以也许有人想对此发表评论。对我来说,这是非常新鲜和有趣的事情。主要挑战似乎是验证部分对象。在注册时,我只需提交姓名、电子邮件和密码,在下一步中我要求 strett,我将一个模型拆分为两个表单。这种跨表单拆分模型意味着您必须提出一些尴尬的问题,例如“嘿,ActiveRecord,我目前拥有的这个对象的一半是否有效?”我不认为 ActiveRecord 是为验证对象的一部分而设计的。

显然有一个名为 Wicked 的 gem,它处理逐步构建部分对象 - 看起来这对我来说太专业了。但如果有人愿意支持我尝试这个,那就太好了。关于这个主题还有一篇很好的文章,我来自https://www.honeybadger.io/blog/multi-step-forms-in-rails/

【讨论】:

猜你喜欢
  • 2021-04-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-21
  • 1970-01-01
相关资源
最近更新 更多