Postings

rails
Browse in : All > subjects > rails

Note: when you create a new publication type, the articles module will automatically use the templates user-display-[publicationtype].xd and user-summary-[publicationtype].xd. If those templates do not exist when you try to preview or display a new article, you'll get this warning :-) Please place your own templates in themes/yourtheme/modules/articles The templates will get the extension .xt there.

Title: make-resourceful and nested polymorphic associations

Author: linoj

Date: July 01, 2007 12:37:42 PM or Sun, 01 July 2007 12:37:42

Summary: Here's a patch that enables make_resourceful to handle polymorphic resources with nested routes.

Body: 

polymorphic resources

A polymorphic model can belong to more than one parent model class. For example, Comments can belong to both Articles and Documents. The Rails idiom for setting this up is like this:

comments table schema includes:

commentable_id:integer
commentable_type:string 

models/comment.rb contains

belongs_to :commentable, :polymorphic => true

then both the models/article.rb and document.rb contains

has_many :comments, :as => :commentable

In this way, you can reference article.comments and document.comments for an Article and Document object, respectively. With RESTful resource routes, you can have url's and named routes like

article_comment_path(@article,@comment) # => /articles/1/comments/22
article_new_comment_path(@article)     # => /articles/1/comments/new

make_resourceful

The make_resourceful ("mr") plugin (ver 0.1.0) automatically creates typical RESTful actions in controllers, but does not presently support these associations.

Although mr supports has_many nested resources (and multiple levels of them at that), it assumes that a child resource has just one kind of parent.

I've submitted this patch to the authors but its not tightly integrated. So if you use this, consider it a temporary patch until the plugin authors integrate it or come up with their own (better) solution.

Most of the code can be put in application.rb. There are a few other methods that go into the controller for the polymorphic resource.

multiple parents

Important: When using polymorphic resources, I've changed the meaning of parents from the standard mr convention. Normally, mr's parents is a list of models in a nested resource chain, such as /projects/3/articles/4/comments/5, then parents contains ["project","article"].

In the polymorphic case, we can have several alternative parents. Thus, I use parents to represent the list of possible parent resources, one level up.

This also means that in the polymorphic case, we only handle one level of nesting. That's not so bad because that's being strongly recommended by the Rails core team. See http://weblog.jamisbuck.org/2007/2/5/nesting-resource

URL helpers

As a sidebar, I want to mention an undocumented feature: mr has a number of very handy URL generator methods, only you need to expose them as helpers to use them in views. They are :object_path, :objects_path, :new_object_path, and :edit_object_path.

You can use these instead of the built-in RESTful named routes. If your resources are nested the nested paths will be generated. My patch now lets them support polymorphic nesting too.

I've also added a new helper, parent_path, that can be used for example in a "Back" link. Thus, for example:

object_path(item) # => /articles/1/comments/22 
object_path       # assumes current_object 
edit_object_path  # => /articles/1/comments/22/edit
parent_path       # => /articles/1 

application.rb

Add the following to your application.rb to extend the make_resourceful library:

 

  # make_resourceful fixes for polymorphic models
  # use this to override parent_objects method 
  # def parent_objects
  #   parent_objects_poly
  # end
  def parent_objects_poly
    return [] if parents.empty?
    return @parent_objects if @parent_objects
    # find index of first (and only) non-zero parent_param 
    parent_i = parent_params.index( parent_params.find { |el| el != 0 })
    return @parent_objects = [] unless parent_i
    model = parent_models[ parent_i ]
    @parent_objects= [model.find(parent_params[parent_i])]
  end
  
  # parent object helper
  def parent_object
    parent_objects[0] unless parent_objects.empty?
  end
  helper_method(:parent_object)
  
  def parent_path
    send("#{namespace_prefix}path", *parent_objects)
  end
  helper_method(:parent_path) 
   
  # expose the url methods as helpers
  helper_method(:object_path, :objects_path, :new_object_path, :edit_object_path)

 

The first method, parent_objects_poly, is the body of the override of the parent_object method.

I introduce a new parent_object helper that returns the parent of the current_object. Related to this, I've also added a parent_path URL helper.

The last line exposes the built-in mr URL generators as helpers.

You can keep this code in application.rb. Normally these will not affect make_resourceful controllers, unless you add the following code to the controller to make it a polymorphic resource.

your_controller.rb

The second part of the implementation requires adding a few methods to your controller.

If this part looks a little kludgey, its because I'm trying to avoid editing the plugin code directly, to force the order of method overrides (internally, make_resourceful method calls load_parent_objects in base from kontroller.before_filter).

 

  make_resourceful do
    actions: all
  end
 
  # add the following to make this controller for a polymorphic resource 
  def parents
    ["article","document"] #this is the only line specific to this resource
  end
  
  def parent_objects
    parent_objects_poly
  end
  
  def namespaces
    parent_i = parent_params.index( parent_params.find { |p| p != 0 })
    [parents[parent_i]]
  end

(Note, we do not use the belongs_to declaration, rather we override the parents method directly.)

As noted above, parents returns the list of possible parents, one level up. You need to insert your own parents array there.

parent_objects is overriden using the body we put in application.rb. It still returns an array, but it will have no more than one element.

Finally, the internal method for generating namespaces is also overridden for the URL helper methods (again, this didn't work when I put it in application.rb)

 

That it. It seems to be working fine for me. I hope it helps you too.

 

Notes: 

More fields may be available via dynamicdata ..

Last modified on Aug 01, 2007 2:39:26 AM by linoj

Note: Comments are owned by the poster. We are not responsible for their content.

make-resourceful and nested polymorphic associations

Posted by: Anonymous on September 08, 2007 08:00 PM
I've given this a good effort and still can't get it to work. Could you show what the routes.rb info should look like for this example?

#

make-resourceful and nested polymorphic associations

Posted by: linoj on September 15, 2007 12:38 PM

Thomas, if you're using rails edge, the routes might contain:

map.resources :articles, :has_many => :comments
map.resources :documents, :has_many => :comments

Otherwise, its a bit more verbose,

map.resources :articles do |article|
  article.resources :comments, :controller => "Comments", :name_prefix => "articles_"
end
map.resources :documents do |doc|
  doc.resources :comments, :controller => "Comments", :name_prefix => "documents_"
end

#

make-resourceful and nested polymorphic associations

Posted by: Anonymous on November 13, 2007 11:45 PM
Hey, Jonathan, great hack! I'm wondering why parent_params is returning nil instead of 0 when that given parent is not in the path for a request, using the new m_r release with edge. I've had to change p != 0 to not p.nil? in both places and it seemed to pull the trick, tho! Cheers, Fabio.

#

iPhone plastic cases

Posted by: Anonymous on July 22, 2010 03:03 AM
I just purchased my Iphone 3GS and purchased the bundle (extended warranty and Otterbox case). At first I thought - YUK. You can't see my beautiful Iphone! However, when I read the reviews of some of the cases that allow you to see the Iphone, I noticed they all had shortcomings. Chief among them is the fact that they don't do an effective job of protecting your phone. I've noticted a number of complaints about the holster. Personnally, I've never owned a holter that didn't eventually break at the belt clip, or fall off. I'm not risking dropping my $200 investment! I'l forgo use of the holster and hold my device. iphone case

#

iphone for sale

Posted by: Anonymous on July 22, 2010 03:10 AM
Another old but useful function of iPhone OS which is unknown to many people is screenshots on all areas with 768 × 1024 resolution ratio. Hold Power and Home for half a second, here is the screen shot. And it is saved at your photo library. When you finally reach the end of a long page and want to return to the top you only need to click on the title . Do you know you can set to preview more than two lines of he e-mail? iPhone also has this option, but it means nothing for its small screeniphone deals

#

Post a new comment

BBCode Actions : Close Tags

Name : Anonymous


Keywords :

  • make_resourceful
  • polymorphic