将字符串转换为一对多关联的外键的方法



我有一个针对我访问过的地区的轨道模型RegionRegionLocation模型具有一对多关联,该模型包含我在该区域访问过的特定位置。

每个区域都有一个name字符串列。 我的路由设置为使用给定Region.name来形成大多数 URL - 例如/:name/new_location。这是出于美学原因,因为我不希望一个数字(region_id)形成URL。

因此,对于我添加到区域的每个新位置,都需要分配一个region_idforeign_key。 现在我正在通过在我的Location中有一个region_name专栏来做到这一点。 然后,我的new位置表单有一个字段"区域名称",其中输入了一个字符串。

为了实际将新创建的location与其region相关联,我的locations_controller中的create方法包含一段代码,如下所示:

# CONVERT REGION_NAME TO REGION_ID
location = Location.new
l = location.region_name.downcase
if l == "chicagoland"
location.region_id = 3
elsif l == "roadtrip 2016"
location.region_id = 4
#...
end
location.save
redirect_to("/regions/#{region.name}/#{location.id}")

因此,对于我创建的每个新region,我无法添加新位置,直到我手动将其字符串名称与其id连接 - 通过向locations_controller中的create方法添加新代码。 因此,如果我使用id = 28创建一个名为"阿冈昆省立公园"的新区域,我需要更新我的locations_controller- 将"algonquin provincial park"连接到28,并将location.region_id设置为28。 这显然不是最佳的。

有没有办法对我的newcreate方法进行编程,以便自动为新location分配一个foreign_key,相当于它所属regionregion_id,而无需每次有新region时都向我的Location create方法添加代码?

作为介绍,您尝试执行的操作有时是指漂亮的URL或友好的URL。您可以自己滚动,也可以使用宝石。看起来你已经走上了自己的道路(这也是我所做的)。如果您的name字段包含非 url 好友元素,那么您可能需要考虑使用slugs.我会留给你自己的研究。

在您的routes.rb中,假设您有:

resources :regions, param: :name do 
resources :locations
end

这将为您提供:

region_locations GET    /regions/:region_name/locations(.:format)                locations#index
POST   /regions/:region_name/locations(.:format)                locations#create
new_region_location GET    /regions/:region_name/locations/new(.:format)            locations#new
edit_region_location GET    /regions/:region_name/locations/:id/edit(.:format)       locations#edit
region_location GET    /regions/:region_name/locations/:id(.:format)            locations#show
PATCH  /regions/:region_name/locations/:id(.:format)            locations#update
PUT    /regions/:region_name/locations/:id(.:format)            locations#update
DELETE /regions/:region_name/locations/:id(.:format)            locations#destroy
regions GET    /regions(.:format)                                       regions#index
POST   /regions(.:format)                                       regions#create
new_region GET    /regions/new(.:format)                                   regions#new
edit_region GET    /regions/:name/edit(.:format)                            regions#edit
region GET    /regions/:name(.:format)                                 regions#show
PATCH  /regions/:name(.:format)                                 regions#update
PUT    /regions/:name(.:format)                                 regions#update
DELETE /regions/:name(.:format)                                 regions#destroy

我们还假设您有:

class Region < ActiveRecord::Base
has_many :locations
end

和:

class Location < ActiveRecord::Base
belongs_to :region
end

然后,在locations_controller.rb中,执行以下操作:

class LocationsController < ApplicationController 
...
def create
@region = Region.find_by(name: params[:region_name])
@location = @region.locations.new(location_params)
if @location.save
redirect_to region_location_path(@region.name, @location)
else
# do something when the location doesn't save
end
end
...
private
def location_params
params.require(:location).permit(:some, :location, :attributes)
end
end

最新更新