我在Rails中有这个方法返回params:
def customer_params
params.require(:treatment_booking).require(:customer)
end
我想从:phone
中删除空格并返回整个哈希值。我可以这样做:
params.require(:treatment_booking).require(:customer).merge(:phone => params[:treatment_booking][:customer][:phone].gsub(/\s+/, ""))
..但我认为它有点不优雅,因为我必须引用我已经调用方法的哈希的整个路径。还有更好的方法吗?
答案可以是Ruby和Rails。
一般来说,我所做的是在预订控制器中更新客户。客户可以保留,但没有密码,所以我不能让它改变它的数据 - 只添加。
这是控制器中的内容:
def create
customer = Customer.find_or_create_by(email: customer_params[:email])
if not customer.persisted?
customer.phone = customer_params[:phone] if not customer_params[:phone].empty?
customer.name = customer_params[:name] if not customer_params[:name].empty?
save_customer(customer)
elsif (customer.phone != customer_params[:phone] || customer.name.downcase != customer_params[:name].downcase)
customer.phone = customer_params[:phone] if customer.phone.empty?
customer.name = customer_params[:name] if customer.name.empty?
save_customer(customer)
redirect_to :back, notice: "This email address has been used before, you can register it or use the same Name and Phone"
return
else
set_session_customer(customer.id)
end
< .. .. >
end
答案 0 :(得分:2)
我认为控制器无需清理参数。但是模型的责任是确保其属性有效。
要清理模型属性,我会将自定义setter添加到Customer
模型中,如下所示:
# in app/models/customer.rb
def phone=(phone)
write_attribute(:phone, phone.gsub(/\s+/, ''))
end
并保持控制器中的customer_params
不变。
解决您的评论:您的控制器中有很多事情发生。而IMO控制器很难理解和重构。特别是因为我不知道方法save_customer
和set_session_customer
做了什么以及你需要对变更属性有多严格。
我认为将更新代码移到Customer
模型中是有意义的。这使得测试更容易。我使用了Rails' Dirty Attributes。
# in the controller
def create
existing_customer = Customer.find_by(present_customer_params.fetch(:email))
if existing_customer
if existing_customer.contact_detail_update(present_customer_params)
save_customer(existing_customer)
redirect_to(
:back, notice: 'This email address has been used before, you can register it or use the same Name and Phone'
) and return
else
set_session_customer(existing_customer.id)
end
else
new_customer = Customer.create(present_customer_params)
save_customer(new_customer)
end
# ...
end
private
def present_customer_params
# excludes blank values from the customer_params
customer_params.select { |_, v| v.present? }
end
# in the `Contact` model
def contact_detail_update(attrs = {})
contact_attributes = [:phone, :name]
# update the customers attributes and let existing customer setters to their job
attributes = attrs.slice(*contact_attributes)
# check case-insensitively if there were any non-trivial changes
changes.slice(*contact_attributes).values.any? do |change|
change.first.casecmp(change.last) != 0
end
end
我不确定这是否能回答您的评论,但也许这个想法对您未来的重构很有帮助......
答案 1 :(得分:0)
回调是这类任务的有用工具:
class Customer < ActiveRecord::Base
before_save :sanitize_phone
def sanitize_phone
self.phone = phone.gsub(/\s+/, '')
end
end
您还可以使用ActiveModel::Dirty
提供的方法,使用回调来拒绝对现有属性的更改。 http://api.rubyonrails.org/classes/ActiveModel/Dirty.html
before_save :reset_changed_attributes
def reset_changed_attributes
phone = phone_was if phone_changed?
name = name_was if name_changed?
end