ruby-on-rails - form_for 嵌套属性:创建不保存到数据库
问题描述
我有一个用户模型和一个配置文件模型。用户
has_one :profile, dependent: :destroy
after_create :create_profile
has_many :reviews, dependent: :destroy
accepts_nested_attributes_for :profile
因此,在 sign_up 用户被重定向到 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
我查看了everywehre,也在这里查看了Unpermitted Parameters Accepts Nested Attributes形式,但我没有做任何事情使它保存到 DB。另外,我试过
params.require(:profile).permit(:about, :avatar)
但它返回了一个非常奇怪的错误:
ActiveSupport::MessageVerifier::InvalidSignature @profile = Profile.new(profile_params)
我究竟做错了什么?我是 Rails 的新手,我真的被困住了。
PS这是我的用户模型
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
解决方案
所以,这似乎是我问题的一个很好的答案,但不是解决方案,所以也许有人想对此发表评论。对我来说,这是非常新鲜和有趣的事情。主要挑战似乎是验证部分对象。在注册时,我只需提交姓名、电子邮件和密码,在下一步中我要求 strett,我将一个模型拆分为两个表单。这种跨表单拆分模型意味着您必须提出一些尴尬的问题,例如“嘿,ActiveRecord,我目前拥有的这个对象的一半是否有效?” 我不认为 ActiveRecord 是为验证对象的一部分而设计的。
显然有一个叫做 Wicked 的 gem,它处理逐步构建部分对象 - 看起来它对我来说太专业了。但如果有人愿意支持我尝试这个,那就太好了。还有一篇关于这个主题的好文章,我来自https://www.honeybadger.io/blog/multi-step-forms-in-rails/
推荐阅读
- paypal - 将 Paypal Express Checkout 按钮移动到 magento 2 中的结帐页面顶部
- jquery - 动态高图未显示Angular js
- position - 在使用 MRTK2.5 在 Hololens2 上进行操作期间获取手的速度或偏差
- javascript - 带有 let 的 for 循环如何详细工作?
- python - 将多个文本文件转换为 csv 以创建标记数据集
- r - 具有 map2_df 的 2 个数据集之间的差异在函数中没有给出所需的结果,但在单独运行时可以正常工作
- php - Microsoft Graph API:将请求文件内容放入二进制流,上传到 SharePoint 文件夹
- php - Laravel 变形过滤器
- informix - Informix 12.10 查找当前运行查询的完成百分比
- python - 在python中从excel中查找连续值的开始索引和最后一行索引