我有一个用户谁有一个个人资料(2个型号)。以下是我的模式的相关部分:
create_table "profiles", force: :cascade do |t|
t.text "about"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "user_id"
end
create_table "users", force: :cascade do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "provider"
t.string "uid"
t.string "first_name"
t.string "last_name"
t.string "street"
t.integer "house_number"
t.string "city"
t.integer "zip_code"
t.string "image"
t.index ["email"], name: "index_users_on_email", unique: true
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
end我之所以将概要文件作为单独的模型,是因为我认为以后为某些操作分配角色会更容易。所以,现在我想知道,是否可以要求
user.first_name , user.last_name, user.email and user.password 在登记表格内,请填写
user.street, user.house_number, user.city and user.zip_code 在Profile#new _form中。如下所示:
<%= form_for([@user, @profile], url: user_profiles_path, method: :post) do |form| %>
<div class="field">
<%= form.label :about %>
<%= form.text_area :about %>
</div>
<div class="field">
<%= form.file_field :avatar %>
<% form.label "Profile photo" %>
</div>
<div class="field">
<%= form.label :street %><br />
<%= form.text_field :street, class: 'form-control' %>
</div>
<div class="actions">
<%= form.submit %>
</div>
<% end %>所以在这里您可以看到,头像和关于是指配置文件,而街道则是来自用户表。但不知何故,这种形式并没有理解这一点。我允许nested_attributes :profile,但是我想,这对于这个表单来说并不重要。我知道,也许更简单的方法是重新排列我的表,这样所有的地址属性都存储在配置文件中。但由于我是Rails的新手,我真的希望了解更多,我很想知道,是否有一种方法可以同时保存到@user和@profile中?谢谢!
发布于 2019-11-27 03:40:11
您在这里涉及到了两个有点不同的概念,大多数初学者都会被难倒。
第一个是nested resources。嵌套资源的路径嵌套在另一个资源下。
# config/routes.rb
resources :magazines do
resources :ads
end所以现在我们用/magazines/:magazine_id/ads代替了/ads。因此,路由本身以一种RESTful的方式描述了两种资源之间的关系--太棒了。
class AdsController < ApplicationController
before_action :set_magazine
# GET /magazines/:magazine_id/ads/new
def new
@ad = @magazine.ads.new
end
# POST /magazines/:magazine_id/ads/new
def create
@ad = @magazine.ads.new(ad_params)
if @ad.save
redirect_to @ad
else
render :new
end
end
def set_magazine
@magazine = Magazine.find(params[:magazine_id])
end
# ...
end<%= form_for([@ad, @magazine]) do |f| >
# ...
<% end %>这将允许您创建属于杂志的广告。它不会神奇地让你在同一时间创建一个杂志作为一个相同的形式的添加。
这就是nested attributes的用武之地。它在模型中创建了一个功能强大的setter,允许它接受关联模型的属性,并在与父对象相同的请求中创建/更新关联记录。
例如,这将允许我们以相同的形式创建用户和配置文件:
class User < ApplicationRecord
has_one :profile
accepts_nested_attributes_for :profile
end
class Profile < ApplicationRecord
belongs_to :user
end<%= form_for(@user) do |f|>
<div class="field">
<%= f.label :email %>
<%= f.email_field :street, class: 'form-control' %>
</div>
# ...
<%= f.fields_for(:profile) do |profile_fields| %>
<div class="field">
<%= profile_fields.label :about %>
<%= profile_fields.text_area :about %>
</div>
<% end %>
# ...
<% end %>class UsersController < ApplicationRecord
POST /users
def create
@user = User.new(user_params)
if @user.save
redirect_to :user
else
render :new
end
end
# ...
private
def user_params
params.require(:user)
.permit(:email, ..., profile_attributes: [:about])
end
end然而,accepts_nested_attributes_for是rails中使用最多、被误解最多、最难掌握的概念之一。如果你刚刚开始,你应该考虑绕过这一步,一旦你对rails有了更好的理解,你就可以回头看看。
https://stackoverflow.com/questions/59057740
复制相似问题