将字符串转换为一对多关联外键的方法
Method for converting strings into foreign key for a one-to-many association
我有一个 rails 模型 Region
我去过的地区。 Region
与 Location
模型具有一对多关联,其中包含我在该区域内访问过的特定位置。
每个区域都有一个 name
字符串列。我的路线设置为使用给定的 Region.name
来形成大多数 URLs - 例如 /:name/new_location
。这是出于审美原因,因为我不想用数字 (region_id
) 来组成 URL.
因此,对于我添加到区域的每个新位置,都需要分配 region_id
foreign_key。现在我通过在我的 Location
中有一个 region_name
列来做到这一点。然后,我的 new
位置表单有一个字段 "Region name",用于输入字符串。
要真正将新创建的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
连接起来 - 通过向 create
方法添加新代码我的 locations_controller
。因此,如果我使用 id = 28
创建一个名为 "Algonquin Provincial Park" 的新区域,我需要更新我的 locations_controller
- 将 "algonquin provincial park"
连接到 28
,并设置 location.region_id
到 28
。这显然不是最优的。
有没有一种方法可以对我的 new
和 create
方法进行编程,以便自动为新的 location
分配一个 foreign_key 等同于 region_id
它属于 region
的一部分,而无需在每次有新的 region
时向我的 Location create
方法添加代码?
作为介绍,您尝试做的事情有时被称为 pretty urls or friendly urls。您可以自己滚动,或使用 gem。看起来你已经走上了自己的道路(我也是这样做的)。如果您的 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
我有一个 rails 模型 Region
我去过的地区。 Region
与 Location
模型具有一对多关联,其中包含我在该区域内访问过的特定位置。
每个区域都有一个 name
字符串列。我的路线设置为使用给定的 Region.name
来形成大多数 URLs - 例如 /:name/new_location
。这是出于审美原因,因为我不想用数字 (region_id
) 来组成 URL.
因此,对于我添加到区域的每个新位置,都需要分配 region_id
foreign_key。现在我通过在我的 Location
中有一个 region_name
列来做到这一点。然后,我的 new
位置表单有一个字段 "Region name",用于输入字符串。
要真正将新创建的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
连接起来 - 通过向 create
方法添加新代码我的 locations_controller
。因此,如果我使用 id = 28
创建一个名为 "Algonquin Provincial Park" 的新区域,我需要更新我的 locations_controller
- 将 "algonquin provincial park"
连接到 28
,并设置 location.region_id
到 28
。这显然不是最优的。
有没有一种方法可以对我的 new
和 create
方法进行编程,以便自动为新的 location
分配一个 foreign_key 等同于 region_id
它属于 region
的一部分,而无需在每次有新的 region
时向我的 Location create
方法添加代码?
作为介绍,您尝试做的事情有时被称为 pretty urls or friendly urls。您可以自己滚动,或使用 gem。看起来你已经走上了自己的道路(我也是这样做的)。如果您的 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