Красивые Пути в Рельсах - PullRequest
2 голосов
/ 19 января 2011

У меня есть модель категории, и я маршрутизирую ее, используя стандартные леса resources :categories.Мне интересно, есть ли способ изменить пути с /category/:id на /category/:name.Я добавил:

match "/categories/:name" => "categories#show"

над строкой ресурсов в routes.rb и изменил действие show в контроллере так:

@category = Category.find_by_name(params[:name])

это работает, но 'магические пути'Например, link_to some_category все еще использует формат :id.

Есть ли способ сделать это?Если это плохая идея (из-за некоторого возможного способа, которым рельсы работают внутри), есть ли другой способ сделать это?Так, например, /categories/music и /categories/3 оба работают?

Ответы [ 3 ]

5 голосов
/ 19 января 2011

В Rails есть отличный метод экземпляра модели под названием to_param, и это то, что используют пути. По умолчанию id, но вы можете переопределить его и создать что-то вроде:

class Category < ActiveRecord::Base
  def to_param
    name
  end
end

cat = Category.find_by_name('music')
category_path(cat)  # => "/categories/music"

Для получения дополнительной информации обратитесь к документации Rails для to_param .

EDIT:

Когда речь идет об именах категорий, которые не идеальны для URL, у вас есть несколько вариантов. Один из них, как вы говорите, заключается в gsub пробелах с дефисами и наоборот при поиске записи. Однако более безопасным вариантом будет создание еще одного столбца в таблице категорий с именем name_param (или аналогичным). Затем вы можете использовать его вместо имени для всего бизнеса, связанного с путями и URL. Используйте инфлектор parameterize, чтобы создать безопасную для URL строку. Вот как я это сделаю:

class Category < ActiveRecord::Base
  after_save :create_name_param

  def to_param
    name_param
  end

  private
    def create_name_param
      self.name_param = name.parameterize
    end
end

# Hypothetical
cat = Category.create(:name => 'My. Kewl. Category!!!')
category_path(cat)  # => "/categories/my-kewl-category"

# Controller
@category = Category.find_by_name_param(param[:id]) # <Category id: 123, name: 'My. Kewl. Category!!!'>
2 голосов
/ 19 января 2011

Если вы не хотите нарушать существующий код, основанный на идентификаторе модели, вы можете определить ваш to_param следующим образом:

 def to_param
   "#{id}-#{name}"
 end

, поэтому ваш URL будет: http://path/1-some-model, и вы все равно сможете загрузить свою модель с Model.find (params [: id]), потому что:

"123-привет-мир" .to_i => 123

1 голос
/ 27 января 2011

Хотя, возможно, больше, чем вам нужно, вы также можете обратиться к поддержке «удобочитаемых для человека URL», например friendly_id или к другим (например, если вам нужна поддержка юникода и т. Д.), Которые описаны здесь на Ruby Toolbox .

...