我是一个新的Rails开发者,我试图优化我的应用程序的一部分,但很难找到Rails惯例的方式来实现我想要的。我有一个“位置”模型,其中一个用户可以被指定为默认联系人。这由引用“用户”模型的位置表中的default_contact_id键捕获。在位置编辑视图中,我希望用户能够通过在文本框中输入电子邮件地址来输入所需的default_contact。然而,我在如何实现这一点上遇到了困难--我试着用fields_for来实现,但我最终不想更新关联的用户对象,只想更新关联本身(存储在location中)。我也不想使用下拉列表,即使它会很好地给予user_id,因为可能有几十个或几百个用户可以被分配为默认联系人。
我最终在Location模型中构建了一个attr_accessor来临时获取所需的电子邮件地址,然后向控制器/helper添加逻辑来根据输入更新值。但这是相当冗长的,给了一个双数据库命中,真的不像“Rails方式”。有没有一个更巧妙的方法来实现这一点,我完全错过了?
这是当前的hacked together解决方案:
Location.rb:
class Location < ApplicationRecord
belongs_to :default_contact, class_name: 'User', foreign_key: 'default_contact_id', optional: true
attr_accessor :default_contact_email
end
views\locations\edit.html.erb:
<h1>Update Location</h1>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_with(model: @location) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
... other fields ...
<%= f.label :default_contact_email %>
<%= f.email_field :default_contact_email, :value => @location.default_contact.email, class: 'form-control' %>
<%= f.submit "Update Location", class: "btn btn-primary" %>
<% end %>
</div>
</div>
locations_controller.rb:
def update
@location = Location.find(params[:id])
if @location.update(update_location_params)
set_default_contact(@location)
flash[:success] = "Location updated"
redirect_to @location
else
flash[:danger] = "Changes were not saved"
render 'edit', status: :unprocessable_entity
end
end
private
def update_location_params
params.require(:location).permit(:name, :business_unit_id, :default_contact_email)
end
locations_helper.rb
def set_default_contact(loc)
if loc.default_contact_id.nil? or (loc.default_contact && ( loc.default_contact.email != loc.default_contact_email ))
if loc.default_contact_email == nil
loc.default_contact_id = nil
elsif
u = User.find_sole_by(email: loc.default_contact_email)
loc.default_contact_id = u.id
end
loc.save
end
end
PS -是的,有数据库的限制,用户的电子邮件必须是唯一的。在用户的方案表中:
t.index ["email"], name: "index_users_on_email", unique: true
1条答案
按热度按时间qv7cva1a1#
您可以删除访问器,并在控制器中应用登录,如下所示。
您不需要这些额外的检查,因为如果
.find_by
没有找到用户,它将返回nil
(即使email值为nil)