Змініть ім'я параметра: id у ресурсах маршрутизації для Rails


107

Я переглянув, як змінити слот для динамічного парамуса і знайшов цю публікацію, яка робить саме те. Допис https://thoughtbot.com/blog/rails-patch-change-the-name-of-the-id-parameter-in

В основному, це робиться, якщо це наступні маршрути:

map.resources :clients, :key => :client_name do |client|
  client.resources :sites, :key => :name do |site|
    site.resources :articles, :key => :title
  end
end

Ці маршрути створюють такі шляхи:

/clients/:client_name
/clients/:client_name/sites/:name
/clients/:client_name/sites/:site_name/articles/:title

Одне рішення - перекрити def to_paramметод у моделі, але я хочу цього, не торкаючись самої моделі.

Але оскільки це для Rails 2.x, як я можу досягти того ж для Rails 3?

Оновлення

Цей додаток використовує Mongoid. Не AR. Отже, самоцвіт не можна використовувати afaik.

Відповіді:


192

Рейки 4 і 5

У Rails 4 :paramбула додана опція, яка, здається, робить саме те, що ви шукаєте. Ви можете подивитися на код Rails 3 порівняно з кодом Rails 4 .

Деталі

Ви можете легко реалізувати це у своєму routes.rbфайлі:

# config/routes.rb

resources :posts, param: :slug

# app/controllers/posts_controller.rb

# ...
@post = Post.find_by(slug: params[:slug])
# ...

На момент випуску Rails 4 ця функціональність задокументована в Rails Guides .

Рейки 3

На жаль, у Rails 3 :keyпараметр для resourcesбуло видалено, тому ви більше не можете легко змінювати назву для створених таким чином маршрутів, просто перейшовши на додатковий варіант.

Деталі

Я припускаю, що ви вже якось змусили програму працювати так, як ви хочете, за минулий рік, але я піду для того, щоб отримати ефект, який ви описуєте в Rails 3 routes.rb. Це просто буде залучати трохи більше роботи, ніж to_paramметод. Ви все ще можете визначити власні параметри маршрутів визначаються з використанням scopeі match(або його кузенів get, put, post, і delete). Ви просто записуєте в параметр назву параметра, яке потрібно:

get 'clients/:client_name', :to => 'clients#show', :as => client

scope 'clients/:client_name' do
  get 'sites/:name', :to => 'sites#show', :as => site
end

Вам доведеться вручну додати всі маршрути, які resourcesавтоматично створюється для вас, але це дозволить досягти того, що ви шукаєте. Ви також можете ефективно використовувати :controllerпараметр із scopeта додатковими scopeблоками, щоб вийняти частину повторення.


EDIT (8 травня 2014 р.): Більш очевидним є те, що відповідь містить інформацію для обох Rails 3 і 4. Оновіть посилання на код, щоб перейти до точних номерів рядків і зобов’язань, щоб вони могли працювати довший період часу.

EDIT (16 листопада 2014 р.): Rails 4 зараз має бути вгорі і містити відповідну інформацію, оскільки це вже поточна версія Rails вже досить давно.

EDIT (9 серпня 2016 р.): Подумайте, що рішення все ще працює в Rails 5, і оновіть застарілі посилання.


1
Таким чином, Rails3 створив параметр ресурсів у маршрутизаторі, щоб бути спокійним, але його потрібно перекрити, щоб мати власні імена змінних ... Відчуває себе кульгавим!
Августин Рідінгер

1
Ось зворотний paramваріант щодо рейок 3: gist.github.com/sj26/44ef47fe8b98b46ee32d
sj26,

Це повертається, порушуючи помічників URL-адреси. Вони завершуються, створюючи звичайний маршрут на основі ідентифікатора, якщо я передаю об'єкт або скаржиться на відсутній ключ [: slug], якщо я передаю слуг. Будь-які ідеї, як виправити?
RonLugge

9
FYI, якщо ви використовуєте вкладені ресурси, параметр для батьківського ресурсу буде post_slug, що може заплутати.
ghayes

4
Це дійсно добре, але що я можу зробити, якщо я не хочу імені параметра батьківського ідентифікатора, наприклад post_post_id для вкладеного ресурсу?
Аснад Атта

45

у Rails 4 перейдіть до параметра param, щоб змінити параметри: id. Наприклад resources :photos, param: :photo_name, генерує / photos /: photo_name


1

Якщо я правильно вас зрозумів, ви хочете мати client_nameзамість цього idв своєму URL-адресі, правда?

Ви можете зробити це, замінивши to_paramметод у своїй моделі. Більше інформації ви можете отримати тут .


1
Як я вже згадував, у мене є обмеження не змінювати модель. Чи згаданий приклад не підтримується чи застарілий у Rails 3?
Автододаток

1

Є дорогоцінний камінь для цього, як і дорогоцінний камінь для всього;)

Я використовував FriendlyId для такої поведінки в рейках 3.

Однак вам потрібно буде додати код до своєї моделі, як-от так:

class Client < ActiveRecord::Base
  has_friendly_id :name
end

... і якщо у ваших клієнтів немає імен, сумісних з URI, ви можете скористатися для цього слизом, з яким ви можете зробити has_friendly_id :name, :use_slug => true. При використанні слизів, очевидно, потрібно також зберігати їх у базі даних.

І як уже згадувалося, ви все одно можете використовувати to_paramтрюк з рейками 3, як це зафіксовано тут . Я вважаю FriendlyId трохи більш універсальним.


Мені подобається дружній ідентифікатор і я використовував у багатьох проектах. Насправді мій додаток використовує Mongoid. І friendly_id не підтримує це afaik. І як я вже згадував, що моє обмеження полягає не у зміні моделі.
Автододаток

1
Якщо ви використовуєте монгоїд, для досягнення цієї функціональності є монгоїд . Він насправді використовує to_param, але це робить і інші розумні речі у фоновому режимі. Я знайшов посилання тут: stackoverflow.com/questions/4744446/…
Мороз

Мені сподобався той самоцвіт. Існує ще одна схожа на молюска . Але, як я вже говорив, у мене є обмеження не змінювати модель. Це to_paramпорушує мою передню частину програми. Насправді я відчайдушно шукаю підхід до маршрутизації - я повинен змінити свій API, але не порушуючи частину Моделі та Frontend від програми. Чому я не можу просто підходити до зміни маршрутів лише так, як я вже заявив, і в прикладі розміщую старішу версію рейок вище ???
Автододаток

Ви намагалися переписати контролери, щоб вони використовували ваші спеціальні ключі маршруту? Наприклад @client = Client.find(:name => param[:client_name]в ClientsController#show? Це може спрацювати.
Мороз

Client.where(:name => param[:client_name]).first, це є.
Мороз

0

У Rails 3 ви можете перейменувати ідентифікаційні клавіші, використовуючи комбінацію просторів імен та таких областей (не дуже приємно):

namespace :clients do
  scope "/:client_name" do
    namespace :sites do
      scope "/:name" do
         post "/:title" => "articles#create"
         ...
      end
    end
  end
end
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.