условный метод to_param - PullRequest
       11

условный метод to_param

6 голосов
/ 10 января 2011

Я использую метод экземпляра модели t_param для генерации URL-адреса в стиле SEO

def to_param
  url
end

, чтобы я мог генерировать ссылки на модель с помощью path_to_model (model) и запрашивать модель с помощью Model.find_by_urlURL).Это работает отлично до сих пор.

Мой вопрос: у меня есть RESTFUL административные маршруты для бэкэнда.Можно ли как-то заставить метод to_param реагировать на маршрут, по которому он вызывается?Потому что я хочу создавать ссылки в бэкэнде с параметром ID, а не с параметром URL.Или какой правильный подход здесь?

Ответы [ 5 ]

2 голосов
/ 29 сентября 2013

Используйте в своей модели переменную класса @@to_param и метод класса для ее управления.

Например, в модели:

class ProductCategory < ActiveRecord::Base
  @@to_param = true

  attr_accessible :description, :name, :parent_id
  has_ancestry
  has_many :products
  validates :slug, :uniqueness => true, :presence => true

  before_validation :generate_slug

  #Trigger fo 'to_param' method
  def self.to_param_trigger(test)
    if (test)
      @@to_param = true
    else
      @@to_param = false
    end
  end

  def to_param
    if @@to_param
      slug
    else
      id
    end
  end

  def generate_slug
    self.slug ||= self.ancestors.map {|item| item.name.parameterize}.push(self.name.parameterize).join('/')
  end
end

В контроллере:

class Backend::ProductCategoriesController < Backend::BaseController
  def index
    # Disable 'to_param'
    ProductCategory.to_param_trigger false
    @categories = ProductCategory
      .select([:id, :name, :slug])
      .select("COALESCE(ancestry, '0') as anctr")
      .order :anctr, :name
  end

  def new
  end

  def edit
  end
end

before_filter и другие трюки в справке =)

2 голосов
/ 12 марта 2011

У меня была такая же проблема. Модель действительно не может / не должна ничего знать о контроллерах. Задача контроллера - определить, какой ресурс запрашивается, и вызвать модель для доступа к нему. Если ваш AdminController должен использовать стандартный числовой идентификатор, вам не нужно нажимать to_param.

Как оказалось, решение довольно простое, и я использую его в производстве.

Предполагая, что у вас есть пространство имен для ваших контроллеров, у вас будут MyModelController и Admin :: MyModelController, а также их помощники. В Админе делай вещи стандартным способом. В MyModelController выполните следующие действия:

В действиях с вашим ресурсом обращайтесь к params[:id], но рассматривайте его как постоянную ссылку (URL). Например

def get
  @my_model = MyModel.find_by_url(params[:id])
  ...
end

В вашем MyModelHelper

def my_model_path my_model
  super my_model.url
end

def my_model_url my_model
  super my_model.url
end

Мне показалось, что это был лучший способ "не сражаться" с рельсами и получить то, что мне нужно было сделать.

Возможно, есть более разумный способ переопределить именованные маршруты. Также я думаю, что вы не можете использовать helper :all с таким подходом, если вы не проверите состояние того, являетесь ли вы администратором или нет, прежде чем создавать пути / URL.

2 голосов
/ 11 января 2011

Вы полностью против наличия идентификатора в URL?Если нет, то, что я сделал в прошлом (это также достигает цели «дружественных по отношению к SEO»), это:

class Person
  def to_param
    "#{id}-#{name.parameterize}"
  end
end

Таким образом, вместо:

http://www.example.com/users/1

вы получаете

http://www.example.com/users/1-jerry-seinfeld

Поскольку метод String::to_i остановится, как только встретится с нецелым символом (т.е. "1".to_i и "1-jerry-seinfeld".to_i оба возвращают 1), это означает, что вы также можете делать:

person = Person.find(params[:id])

без необходимости переопределять какие-либо из ваших искателей (с дополнительным преимуществом работы на вашем веб-интерфейсе и бэкэнде администратора).

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

возьмите gem friendly_id и посмотрите, как они это делают - http://rubygems.org/gems/friendly_id

У них

  def to_param
    (friendly_id || id).to_s
  end

в поддержке модели - https://github.com/norman/friendly_id/blob/master/lib/friendly_id/active_record_adapter/simple_model.rb -но в целом все работает так, как вы хотите, поэтому вы, возможно, сможете адаптировать их код, если не будете использовать этот драгоценный камень.

0 голосов
/ 11 января 2011

Вот один из способов сделать это ...

class BlogPost
  def to_param
    url
  end

  # BlogPost.find_by_param("14") => looks for ID 14
  # BlogPost.find_by_param("foobar") => looks for url "foobar"
  # BlogPost.find_by_param("14-foobar") => looks for ID 14 (ignores the "-foobar" part)
  def self.find_by_param(param)
    if param.to_s =~ /^[0-9]+/
      find_by_id param.to_i
    else
      find_by_url param.to_s
    end
  end
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...