从 has_many 更改为 has_one 关系 rails
Changing from has_many to has_one relation rails
这里是 personaldetails belongs_to 用户,给定的关系是 has_many,wrong.I 想要将 has_many 关系转换为 has_one 关系,即用户 has_one 个人资料。当我直接更改关系时,出现错误“未初始化常量 User::Personaldetails。请指导我如何转换关系。
Personaldetail.rb
class Personaldetail < ApplicationRecord
belongs_to :user
end
User.rb
class User < ApplicationRecord
has_many :personaldetails, dependent: :destroy
accepts_nested_attributes_for :personaldetails, reject_if: :all_blank, allow_destroy: true
end
routes.rb
resources :users, except: [:new] do
resources :personaldetails
end
user_steps_controller.rb
class UserStepsController < ApplicationController
include Wicked::Wizard
steps : :personaldetails
def show
@user = current_user
@personaldetails = @user.personaldetails.build
render_wizard
end
def update
@user = current_user
@user.update!(user_params)
render_wizard @user
end
private
def user_params
params.require(:user).permit(:name, :password, :password_confirmation, :user_id,
personaldetails_attributes: [:id,:first_name, :last_name, :gmail, :mobile_no, :city, :state, :pin_code, :_destroy])
end
end
personaldetails.html.erb
<%= form_with(model: @user, url: wizard_path, local: true) do |form| %>
<%= form.fields_for :personaldetail,Personaldetail.new do |info| %>
<%= render 'personaldetails_field', form: info %>
<% end %>
<%= form.submit %>
<% end %>
_personaldetails_field.html.erb
<div class="field">
<%= form.label :First_name %><br />
<%= form.text_field :first_name %>
</div>
<div class="field">
<%= form.label :Last_name %><br />
<%= form.text_field :last_name %>
</div>
<div class="field">
<%= form.label :email %><br />
<%= form.text_field :gmail %>
</div>
<div class="field">
<%= form.label :Mobile_number %><br />
<%= form.text_field :mobile_no %>
</div>
<div class="field">
<%= form.label :City %><br />
<%= form.text_field :city %>
</div>
<div class="field">
<%= form.label :State %><br />
<%= form.text_field :state %>
</div>
<div class="field">
<%= form.label :Pincode %><br />
<%= form.text_field :pin_code %>
</div>
所以解决方案是:
Personaldetail.rb
class Personaldetail < ApplicationRecord
belongs_to :user
end
User.rb
class User < ApplicationRecord
has_one :personaldetails, dependent: :destroy
accepts_nested_attributes_for :personaldetails, reject_if: :all_blank, allow_destroy: true
end
routes.rb
resources :users, except: [:new] do
resources :personaldetail
end
user_steps_controller.rb
class UserStepsController < ApplicationController
include Wicked::Wizard
steps : :personaldetails
def show
@user = current_user
render_wizard
end
def update
@user = current_user
@user.update!(user_params)
render_wizard @user
end
private
def user_params
params.require(:user).permit(:name, :password, :password_confirmation, :user_id,
personaldetails_attributes: [:id,:first_name, :last_name, :gmail, :mobile_no, :city, :state, :pin_code, :_destroy])
end
end
personaldetail.html.erb
<%= form_with(model: @user, url: wizard_path, local: true) do |form| %>
<%= form.fields_for :personaldetail,@user.personaldetail || @user.build_personaldetail do |info| %>
<%= render 'personaldetail_field', form: info %>
<% end %>
<%= form.submit %>
<% end %>
_personaldetail_field.html.erb
<div class="field">
<%= form.label :First_name %><br />
<%= form.text_field :first_name %>
</div>
<div class="field">
<%= form.label :Last_name %><br />
<%= form.text_field :last_name %>
</div>
<div class="field">
<%= form.label :email %><br />
<%= form.text_field :gmail %>
</div>
<div class="field">
<%= form.label :Mobile_number %><br />
<%= form.text_field :mobile_no %>
</div>
<div class="field">
<%= form.label :City %><br />
<%= form.text_field :city %>
</div>
<div class="field">
<%= form.label :State %><br />
<%= form.text_field :state %>
</div>
<div class="field">
<%= form.label :Pincode %><br />
<%= form.text_field :pin_code %>
</div>
尝试:has_one :personaldetail, dependent: :destroy
Rails 正在根据名称和关联类型猜测 class 名称,因此对于 has_many 他们将尝试单数化关联名称(personaldetails => Personaldetail)但对于 has_one 他们将尝试按原样到达它 (personaldetails => Personaldetails)
如 spickermann 的评论所述,has_many
关系需要复数形式,has_one
需要单数形式。
也就是说,你应该已经可以从中推断出关系了:
@user.personaldetails # user has many personal details
@user.personaldetail # user has one personal detail
只是一个考虑:当 objects/models 没有正确命名时会出现许多奇怪的情况。根据经验,您应该为需要命名的对象使用最合适和最准确的英语名词。在这种情况下,这将对您有很大帮助。在普通英语中,说“用户有个人详细信息”有些奇怪,但您当然会说“有个人详细信息”。特别是涉及到 ActiveRecord 关联时,Rails 语法应该尽可能接近英语,以避免以后的误解。我想如果模型不是“PersonalDetail”,而是称为“Account”或“Profile”,就不会出现这种混淆。
很少suggestions/comments
- 将模型名称保持为
PersonalDetail
而不是 Personaldetail
和关联名称 has_one :personal_detail
的 CamelCase
- 使用
has_one
关系,您可以使用 user.build_personal_detail.save
创建对象
- 当您再次 运行 第二步时,它将在
personal_details
table 中创建另一条记录,并且在该事务中它将 return 新记录。但是,之后当您尝试查询时,它将 return 第一个创建的 personal_details 记录而不是新记录。这是因为 ActiveRecord
默认按 id 排序,has_one
关系 限制为 1
这里是 personaldetails belongs_to 用户,给定的关系是 has_many,wrong.I 想要将 has_many 关系转换为 has_one 关系,即用户 has_one 个人资料。当我直接更改关系时,出现错误“未初始化常量 User::Personaldetails。请指导我如何转换关系。
Personaldetail.rb
class Personaldetail < ApplicationRecord
belongs_to :user
end
User.rb
class User < ApplicationRecord
has_many :personaldetails, dependent: :destroy
accepts_nested_attributes_for :personaldetails, reject_if: :all_blank, allow_destroy: true
end
routes.rb
resources :users, except: [:new] do
resources :personaldetails
end
user_steps_controller.rb
class UserStepsController < ApplicationController
include Wicked::Wizard
steps : :personaldetails
def show
@user = current_user
@personaldetails = @user.personaldetails.build
render_wizard
end
def update
@user = current_user
@user.update!(user_params)
render_wizard @user
end
private
def user_params
params.require(:user).permit(:name, :password, :password_confirmation, :user_id,
personaldetails_attributes: [:id,:first_name, :last_name, :gmail, :mobile_no, :city, :state, :pin_code, :_destroy])
end
end
personaldetails.html.erb
<%= form_with(model: @user, url: wizard_path, local: true) do |form| %>
<%= form.fields_for :personaldetail,Personaldetail.new do |info| %>
<%= render 'personaldetails_field', form: info %>
<% end %>
<%= form.submit %>
<% end %>
_personaldetails_field.html.erb
<div class="field">
<%= form.label :First_name %><br />
<%= form.text_field :first_name %>
</div>
<div class="field">
<%= form.label :Last_name %><br />
<%= form.text_field :last_name %>
</div>
<div class="field">
<%= form.label :email %><br />
<%= form.text_field :gmail %>
</div>
<div class="field">
<%= form.label :Mobile_number %><br />
<%= form.text_field :mobile_no %>
</div>
<div class="field">
<%= form.label :City %><br />
<%= form.text_field :city %>
</div>
<div class="field">
<%= form.label :State %><br />
<%= form.text_field :state %>
</div>
<div class="field">
<%= form.label :Pincode %><br />
<%= form.text_field :pin_code %>
</div>
所以解决方案是:
Personaldetail.rb
class Personaldetail < ApplicationRecord
belongs_to :user
end
User.rb
class User < ApplicationRecord
has_one :personaldetails, dependent: :destroy
accepts_nested_attributes_for :personaldetails, reject_if: :all_blank, allow_destroy: true
end
routes.rb
resources :users, except: [:new] do
resources :personaldetail
end
user_steps_controller.rb
class UserStepsController < ApplicationController
include Wicked::Wizard
steps : :personaldetails
def show
@user = current_user
render_wizard
end
def update
@user = current_user
@user.update!(user_params)
render_wizard @user
end
private
def user_params
params.require(:user).permit(:name, :password, :password_confirmation, :user_id,
personaldetails_attributes: [:id,:first_name, :last_name, :gmail, :mobile_no, :city, :state, :pin_code, :_destroy])
end
end
personaldetail.html.erb
<%= form_with(model: @user, url: wizard_path, local: true) do |form| %>
<%= form.fields_for :personaldetail,@user.personaldetail || @user.build_personaldetail do |info| %>
<%= render 'personaldetail_field', form: info %>
<% end %>
<%= form.submit %>
<% end %>
_personaldetail_field.html.erb
<div class="field">
<%= form.label :First_name %><br />
<%= form.text_field :first_name %>
</div>
<div class="field">
<%= form.label :Last_name %><br />
<%= form.text_field :last_name %>
</div>
<div class="field">
<%= form.label :email %><br />
<%= form.text_field :gmail %>
</div>
<div class="field">
<%= form.label :Mobile_number %><br />
<%= form.text_field :mobile_no %>
</div>
<div class="field">
<%= form.label :City %><br />
<%= form.text_field :city %>
</div>
<div class="field">
<%= form.label :State %><br />
<%= form.text_field :state %>
</div>
<div class="field">
<%= form.label :Pincode %><br />
<%= form.text_field :pin_code %>
</div>
尝试:has_one :personaldetail, dependent: :destroy
Rails 正在根据名称和关联类型猜测 class 名称,因此对于 has_many 他们将尝试单数化关联名称(personaldetails => Personaldetail)但对于 has_one 他们将尝试按原样到达它 (personaldetails => Personaldetails)
如 spickermann 的评论所述,has_many
关系需要复数形式,has_one
需要单数形式。
也就是说,你应该已经可以从中推断出关系了:
@user.personaldetails # user has many personal details
@user.personaldetail # user has one personal detail
只是一个考虑:当 objects/models 没有正确命名时会出现许多奇怪的情况。根据经验,您应该为需要命名的对象使用最合适和最准确的英语名词。在这种情况下,这将对您有很大帮助。在普通英语中,说“用户有个人详细信息”有些奇怪,但您当然会说“有个人详细信息”。特别是涉及到 ActiveRecord 关联时,Rails 语法应该尽可能接近英语,以避免以后的误解。我想如果模型不是“PersonalDetail”,而是称为“Account”或“Profile”,就不会出现这种混淆。
很少suggestions/comments
- 将模型名称保持为
PersonalDetail
而不是Personaldetail
和关联名称has_one :personal_detail
的 CamelCase
- 使用
has_one
关系,您可以使用user.build_personal_detail.save
创建对象
- 当您再次 运行 第二步时,它将在
personal_details
table 中创建另一条记录,并且在该事务中它将 return 新记录。但是,之后当您尝试查询时,它将 return 第一个创建的 personal_details 记录而不是新记录。这是因为ActiveRecord
默认按 id 排序,has_one
关系 限制为 1