开发者

Adding extra params to rails route resources

What I want to do seems simple, but might not be "proper"

let's say I have an image resource, and I manipulate the image based on the url. In t开发者_StackOverflowhe url I want to specify it's size and whether it's grayed, colored, or dimmed or some other condition.

currently I have a number of named routes that look like this.

map.gray_product_image "images/:product/:image/gray/:size.:format", :controller => 'images', :action => 'gray_product_image'

for me the trick is that if I created this useing Rails resources, I don't know how I would specify the :size, :format, or it's "color type".

I guess I would like to add a member route and specify my params like the following.

map.resources :products do |products| 
  products.resources :images, :member => {:gray_product_image => {':image/:size.:format' => :get}}
end

There are other times where I have wanted to added extra info to a resource route but didn't know how.

Any help would be greatly appreciated, Thanks.


There's no good way to remove the controller/id part of a resource. The closest you're going to get through tricking ActionController with something like this:

map.resources :gray, :path_prefix => "/images/:product/:image_id/", 
  :controller => 'images', :requirements => {:colour => "gray"}

Which will produce routes like www.site.com/images/product/4/gray/1234.html with the following params hash:

params => { 
  :image_id => 4,
  :id => 1234,
  :colour => "gray",
  :product => "product"
}

The format won't be passed explicitly but it will be available in the controller through the usually respond_to means.

Next you'll have to work some magic in controller to trick rails into doing what you want.

class ImagesController < ApplicationController
  def show
    @size = params[:id]
    @image = Image.find(params[:image_id])
    ...
  end
end

This actually works better as a filter so:

class ImagesController < ApplicationController
  def initialize_colour
    unless params[:colour].nil?
      @size = params[:id]
      @colour = params[:colour]
      @image = Image.find(params[:image_id])
    end
  end

  before_filter :initialize_colour, :except => [:index, :new, :create]

  ...

end

However to make good use of these routes, you're going to have to pass all those extra parameters to your url for calls. Like this:

gray_url(size, :image_id => @image.id, :product => product)

But helpers make that easy.

module ApplicationHelper
  def easy_gray_url(image, size, product)
    gray_url(size, :image_id => image.id, :product => product)
  end
end


Check out the documentation for Resources. You'll find this:

The resources method accepts the following options to customize the resulting routes:

  • :requirements - Set custom routing parameter requirements; this is a hash of either regular expressions (which must match for the route to match) or extra parameters. For example:

    map.resource :profile,
                 :path_prefix => ':name',
                 :requirements => { :name => /[a-zA-Z]+/, :extra => 'value' }
    

    will only match if the first part is alphabetic, and will pass the parameter :extra to the controller.


I have realized that the way I want to represent my resources simply falls outside of the normal Rails resources, and that's ok. The problem I was really having was that each time added anther action and named route to get to what I wanted it felt wrong, I was repeating myself, both in my routes and in my actions.

I went back to simply creating my named routes, and spent a little more time in the controller so that I could keep my routes simple. Below is what I have now, and I am ok with it.

#routes.rb
map.with_options :controller => 'sketched_images', :action => 'show', :path_prefix => '/sketches', :name_prefix => 'sketched_', :color => 'grey' do |m|
  m.style "styles/:style/:color/:size.:format"
  m.design "designs/:design/:color/:size.:format"
  m.product "products/:product/:color/:size.:format"
  m.color_combo "colored_products/:color_combo/:size.:format"
end

class SketchedImagesController < ApplicationController
caches_page :show

before_filter :load_data
def show
  @size = params[:size] || 100
  respond_to do |wants|
    wants.png
    wants.jpg
  end
end

private

def load_data
  case 
  when params[:design]
    @image = ClothingDesign.from_param(params[:design]).sketched_image
    greyed
  when params[:style]
    @image = ClothingStyle.from_param(params[:style]).sketched_image
    greyed
  when params[:product]
    @image = Product.from_param(params[:product]).sketched_images.first
    greyed
  when params[:color_combo]
    @color_combo = ColorCombo.find_by_id(params[:color_combo])
    @object = @color_combo.colorable
    if @object.active? && !@object.sketched_images.blank?
      @image = @object.sketched_images.first
      colored
    else
      @image = @product.style.sketched_image
      dimmed
    end
  end
end

def greyed
  @blank = "#FFF"
  @print = "#000"
  @highlight = "#666"
end

def colored
  @blank = "##{@color_combo.blank_color.value}"
  @print = "##{@color_combo.design_color.value}"
  @highlight = "##{@color_combo.highlight_color.value}" unless @color_combo.highlight_color.blank?
end

def dimmed
  @blank = "#BBB"
  @print = "#000"
  @highlight = "#444"
end

end
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜