在我的Rails应用程序中,我有用户。用户被要求提供他们的家乡城市和地区/社区。 p>
class User < ActiveRecord::Base
belongs_to :city
belongs_to :district
end
class City < ActiveRecord::Base
has_many :users
has_many :districts
end
class District < ActiveRecord::Base
has_many :users
belongs_to :city
end
在表单中,我使用User模型上接受字符串的虚拟属性构建关联(如果相关,请在下面提供更多信息)。
在控制台中,这一切都很有效,但在UI中它不起作用。问题似乎是,我可以通过表单获得city_name
没有问题,但是当我尝试以相同的形式分配城市和地区时,它总是失败。换句话说,质量分配不起作用。
@user.update_attributes(params[:user])
相反,我唯一能够弄清楚的是从表单提交中手动设置每个键,例如:
@user.name = params[:user][:name] if params[:user][:name]
@user.city_name = params[:user][:city_name] if params[:user][:city_name]
@user.district_name = params[:user][:district_name] if params[:user][:district_name]
这种方法有效,但它很痛苦,很脆弱,并且感觉一切都错了,因为它开始用很多逻辑来控制控制器。
我的问题是:
有没有办法按特定顺序创建或更新属性,理想情况是在模型中,以便控制器不必担心所有这些?
我这样做错了吗?如果是这样,哪种方法会更好。
额外信息
以下是我如何使用用户模型上的虚拟属性构建关联,以防与任何潜在的回答者相关:
我希望用户只需输入一个名称就可以选择一个城市,例如“Chicago,IL”。这样可以正常使用用户模型上的虚拟属性,如下所示:
def city_name
city.try :full_name
end
def city_name=(string)
self.city = City.find_or_create_by_location_string( string )
end
用户只有从他们选择的城市中查找或创建区域才有意义。这种方式略有不同:
def district_name
district.try :name
end
def district_name=(string)
if self.city.nil?
raise "Cannot assign a district without first assigning a city."
else
self.district = self.city.districts.find_or_create_by_name( string )
end
end
在模型层中,这些工作正常,只要设置了city_name和district_name,区域关联就会按预期工作。
答案 0 :(得分:1)
我认为你可以做一些事情来清理它。首先,您可以使用委托来清理代码。例如
delegate :name, :to => :city, :prefix => true, :allow_nil => true
你可以这样做
user = User.create
user.city_name # nil
city = City.create(:name => 'chicago')
user.city = city
user.save
user.city_name # chicago
它会起作用。
接下来,我会说从你的模型中取出name-to-id逻辑。您可以在表单中(例如,ajax搜索将区域ID /城市ID放入隐藏字段)或控制器中执行此操作。然后只需正常分配城市/地区。