conditional to_param method
I am using the model instance method t_param to generate a SEO-style URL
def to_param
  url
end
that way I can generate links to the model with path_to_model(model) and query the model with Model.find_by_url(url). This works fine so far.
My question: I have RESTFUL admin routes for the backend. Can I somehow make the to_param me开发者_开发知识库thod react to the route it is called by? Because I want to create links in the backend with the ID parameter and not the URL parameter. Or what is the correct approach here?
I had the same issue. A model really can't/shouldn't know anything about controllers. It's the controller's job to determine what resource is being requested, and to call the model to access it. If your AdminController needs to use the standard numeric ID, you're not going to want to touch to_param.
As it turns out, the solution is quite simple, and I use it in production.
Assuming you've namespaced your controllers, you'll have a MyModelController and a Admin::MyModelController, along with their helpers. In Admin, do things the standard way. In MyModelController, do the following:
In your resource actions, refer to params[:id] but treat it like a permalink (URL). For example
def get
  @my_model = MyModel.find_by_url(params[:id])
  ...
end
In your MyModelHelper
def my_model_path my_model
  super my_model.url
end
def my_model_url my_model
  super my_model.url
end
To me it felt this was the best way to "not fight" rails and get what I needed done.
There might be a more clever way to override the named routes. Also I think you can't use helper :all with this approach, unless you check state of whether you're in admin or not before generating paths/url's.
Are you completely opposed to having the ID in the url? If not, what I've done in the past (that also accomplishes the goal of 'seo friendly' urls is this:
class Person
  def to_param
    "#{id}-#{name.parameterize}"
  end
end
Thus, instead of:
http://www.example.com/users/1
you get
http://www.example.com/users/1-jerry-seinfeld
Since the String::to_i method will stop once it encounters a non-integer character (i.e. "1".to_i and "1-jerry-seinfeld".to_i both return 1), this means you can also do:
person = Person.find(params[:id])
without having to override any of your finders (with the added benefit of working on your frontend and your admin backend).
Use in your model class variable @@to_param and class method for control it.
For example in model:
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
In controller:
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 and other tricks in help =)
Here's one way to do it...
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
grab the gem friendly_id and check out how they do it -- http://rubygems.org/gems/friendly_id
They have
  def to_param
    (friendly_id || id).to_s
  end
in their model support -- https://github.com/norman/friendly_id/blob/master/lib/friendly_id/active_record_adapter/simple_model.rb -- but things seem to work generally like you want so you could probably adapt their code if not reuse the gem.
 加载中,请稍侯......
      
精彩评论