我有一个拥有个人资料的用户(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
在“个人资料#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 %>
因此,在这里您可以看到,该头像和大约是指个人资料,而街上的用户则来自User表。但是以某种方式,这种形式并不能理解这一点。我允许将nested_attributes用于:profile,但是我猜想,对于这种形式,这无关紧要。我知道,也许更简单的方法是重新排列我的表,以便所有地址属性都存储在Profile中。但是,由于我是Rails的新手,我真的很想了解更多,我很想知道,是否有一种方法可以同时保存到@user和@profile?谢谢!
答案 0 :(得分:0)
您在这里碰到两个稍有不同的概念,大多数初学者都对此感到困惑。
第一个是nested resources。嵌套资源的路径嵌套在另一个资源下。
# config/routes.rb
resources :magazines do
resources :ads
end
所以现在有了/ads
,而不是/magazines/:magazine_id/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的用处。它在模型中创建了一个超级功能的设置器,它可以接受关联模型的属性,并在与父代相同的请求中创建/更新关联记录。
例如,这将使我们以相同的形式创建用户和个人资料:
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
是最容易被误解,误解和最难理解的概念之一。如果您只是刚入门,则应该考虑绕过此方法,并在对导轨有了更好的了解后再转一圈。