<commit_before># SuperResources

SuperResources DRYs up your controller code by abstracting your controller's strandard RESTful actions and by providing 
standard helpers to access the controller's target resource(s) in a consistent way across all controllers. More than that,
SuperResources exploits the application's routes to provide simplified path helpers for nested resources.

With SuperResources, in the great majority of common REST situations, you can use the same resource helpers and path helpers, 
regardless of the the specific type of resource or how it is nested, even if the resource is nested under many other resources.

## Installation

Add this line to your application's Gemfile:

    gem 'super_resources'

And then execute:

    bundle install

Or install it yourself as:

    gem install super_resources

## Usage

To gain all the standard RESTful actions, just `include SuperResources::Controller` in your controller:

    class OrganizationUnitsController < ApplicationController
      include SuperResources::Controller
    end

### Resource Helper Methods

SuperResources provides helper methods that you can use directly in the controller, views or helper methods:

    resource
    collection

For member actions, `resource` answers a single object that the RESTFUL is operating on.
For collection actions (i.e `index1), `collection` answer a scoped collection of objects.

SuperResources does away with specifically named instance variables, such as those created by standard scaffolds. For example, in the example above, SuperResources does not give you `@organization_unit` or `@organization_units` for free. You won't need them in the common cases. Using `resource` and `collection` in every controller makes for easier coding and maintenance.

### Path Helper Methods

SuperResources provides a set of vastly simplified path helpers.

    collection_path #=> path to the resource's index action
    resource_path(object = resource)
    new_resource_path
    edit_resource_path(object = resource)

Note that the helper methods that require an input argument, assumes the current resource by default, so you don't have to pass it in.

#### These Helper Methods Work Even When the Resource is Nested

Because SuperResources uses the metadata created by your routes declarations to work out whether the resource has been nested and if so, automatically uses the nesting objects to build complete paths. This relieves you of passing in an array to the path helper.

With this feature alone, SuperResources cleans up your code and makes it more reusable. For example, the same code can be used when you 
have a resource that is nested inside multiple other objects. SuperResources dynamically works out the nesting that applies in each case.

## Nested Resource

Let's face it: deailing with nested resources has always been a pain. All that fiddling about, getting the path names and inputs right. Chane the nesting and you have to go through and chaneg all your path calls too. Then, if you have a resource that can be nested within multiple other resources, such as when you have an associative object and you want to navigate to it from any of it associations, the permutations become very complex.

It should be much easier, especially when you take routes into account. If I have an action that is matched to this route:

    /notes/:note_id/pages/:id

then shouldn't I have paths available that can work out the nesting context, so that I don't hard code it?

SuperResources does this. For example, including SuperResources in `PagesController` will allow me to simply call, 
for example, `edit_resource_path` and the code has been actioned through the above route, the nesting with a Note identified by `:note_id` will be assumed. Even better, if the same code is actioned by another route with different nesting, SuperResources will get that right too.

If you need, such as when you want to link 'outside the nest' as it were, you still have `note_page_path(note, page)` available to you.

### Parent Helper Method

Sometimes you want to use the object that is nesting your resource, such as when you want to customize a redirect. SuperResources provides 
`parent` to answer that object. For example given, the following route:

    /notes/:note_id/pages/:id


calling `parent` will answer a Note object with an id of `:note_id`. 

For deeper nests, the immediately nested object is always answered by `parent`. For example, given this route:

    /authors/:author_id/notes/:note_id/pages/:id

calling `parent` will still answer a Note object with an id of `:note_id`. 

### Accessing Route Objects

Any nested route implies a component hierarchy of objects. SuperResources allows you to access these objects bye a convenient name.

For example, given this route:

    /authors/:author_id/notes/:note_id/pages/:id

you can make these calls:

  author  #=> Author with an id of :author_id
  note    #=> Note with an id of :note_id
  page    #=> Page with an id of :id

An example of a place where you will want these, is in a layout template that presents information about the nesting objects. For example, you may want to show a page inside an author layout template. The author layout template will present information about the author. In this case, the layout will be used in the context of `PagesController`, so you can't refer to `resource` in the layout, since it will answer the page, not the author. You need some way to arbitrarily refer to the author.  Being able to call `author` provides this.

## Adapting and Customising

### Resource Class

SuperResources derives the class of the target resource from the controller name. For example, `OrganizationUnitsController` operates, by default, on resources of the class `OrganizationUnit`. If you want to change this, redefine hotspot method `resource_class`, for example:

    class TeamsController < ApplicationController
      include SuperResources::Controller

      protected

      def resource_class
        OrganizationUnit
      end
    end

### Resource Helper Methods

Yes, you can adapt these to suit your needs. 

The `resource` and `collection` methods are used internally by the default RESTful actions provided by SuperResources, and can have their implementations customised easily. The return values of these methods are memoized for various reasons, for this you should make use of the `memoize_resource` and `memoize_collection` methods respectivley. Both methods take a block that is only executed as necessary.

For example, if you wanted 'TeamsController#collection' to return only those teams that the current user has joined, you would write an implementation of `collection` that calls its super, passing a block the evalautes to the right collection:

    def collection
      memoize_collection { resource_class.joined_by(current_user) }
    end

If that looks strange, bear in mind it's been designed so that you don't need to know how SuperResources internally uses your preferred implementation.

### Finder Method

Before being able to use the result of `resource`, SuperResources may need to find it. The canonical way to do this is to do:

  resource_class.find(:params[:id])

While SuperResource uses the `find` method as the default, you can choose another finder method by redefining `finder_method`. For example:

    class PagesController < ApplicationController

      protected

      def finder_method
        :find_by_position
      end
    end

### Builder Method

SuperResources extracts the construction of a new resource into the `build_resource` method. If you need to do specialized work for the build, override the `build_resource` method and be sure to memoize your result:

    def build_resource
      memoize_resource do
        resource_class.new do |p|
          # initialize the state here
        end
      end
    end

### Redefining Actions

Yes, you can. All actions defined by SuperResources use responders and accept parameters to pass to `respond_with`, so customizing these parameters is a common adaptation.

For example, suppose that after creating a comment, you want to redirect to an index of comments that apply to the same parent. Adapt teh action like this:

    def create
      super :location => polymorphic_url([ parent, :comments ])
    end

Anything you can pass to `respond_with`, you can pass to he super call, including a block.

You could, of course, completely redefine an action:

    def new
      # knock yourself out
    end

### Defining Actions

Just do it. Declare them in your controller and match them in routes. All the SuperResources helpers are still available to you.

## Acknowledgments

SuperResources would never have happened without [InheritedResources](https://github.com/josevalim/inherited_resources) existing first.
We preferred the idea of abstracting and extracting RESTful actions out of all our controllers and we're not so keen on scaffolds generating
un-DRY code. We used InheritedResources in a production deployed application [MeetLinkShare](http://www.meetlinkshare.com), gained some experience and decided we wanted an even DRYer tool.

The basic mechanics of SuperResources was hacked out during Rails Camp 12 in Tasmania, Australia and was subsequently applied to MeetLinkShare.
<commit_msg>Fix a few typos, re-indent code for markdown<commit_after># SuperResources

SuperResources DRYs up your controller code by abstracting your controller's strandard RESTful actions and by providing 
standard helpers to access the controller's target resource(s) in a consistent way across all controllers. More than that,
SuperResources exploits the application's routes to provide simplified path helpers for nested resources.

With SuperResources, in the great majority of common REST situations, you can use the same resource helpers and path helpers, 
regardless of the the specific type of resource or how it is nested, even if the resource is nested under many other resources.

## Installation

Add this line to your application's Gemfile:

    gem 'super_resources'

And then execute:

    bundle install

Or install it yourself as:

    gem install super_resources

## Usage

To gain all the standard RESTful actions, just `include SuperResources::Controller` in your controller:

    class OrganizationUnitsController < ApplicationController
      include SuperResources::Controller
    end

### Resource Helper Methods

SuperResources provides helper methods that you can use directly in the controller, views or helper methods:

    resource
    collection

For member actions, `resource` answers a single object that the RESTFUL is operating on.
For collection actions (i.e `index`), `collection` answer a scoped collection of objects.

SuperResources does away with specifically named instance variables, such as those created by standard scaffolds. For example, in the example above, SuperResources does not give you `@organization_unit` or `@organization_units` for free. You won't need them in the common cases. Using `resource` and `collection` in every controller makes for easier coding and maintenance.

### Path Helper Methods

SuperResources provides a set of vastly simplified path helpers.

    collection_path #=> path to the resource's index action
    resource_path(object = resource)
    new_resource_path
    edit_resource_path(object = resource)

Note that the helper methods that require an input argument, assumes the current resource by default, so you don't have to pass it in.

#### These Helper Methods Work Even When the Resource is Nested

Because SuperResources uses the metadata created by your routes declarations to work out whether the resource has been nested and if so, automatically uses the nesting objects to build complete paths. This relieves you of passing in an array to the path helper.

With this feature alone, SuperResources cleans up your code and makes it more reusable. For example, the same code can be used when you 
have a resource that is nested inside multiple other objects. SuperResources dynamically works out the nesting that applies in each case.

## Nested Resource

Let's face it: dealing with nested resources has always been a pain. All that fiddling about, getting the path names and inputs right. Change the nesting and you have to go through and change all your path calls too. Then, if you have a resource that can be nested within multiple other resources, such as when you have an associative object and you want to navigate to it from any of it associations, the permutations become very complex.

It should be much easier, especially when you take routes into account. If I have an action that is matched to this route:

    /notes/:note_id/pages/:id

then shouldn't I have paths available that can work out the nesting context, so that I don't hard code it?

SuperResources does this. For example, including SuperResources in `PagesController` will allow me to simply call, 
for example, `edit_resource_path` and the code has been actioned through the above route, the nesting with a Note identified by `:note_id` will be assumed. Even better, if the same code is actioned by another route with different nesting, SuperResources will get that right too.

If you need, such as when you want to link 'outside the nest' as it were, you still have `note_page_path(note, page)` available to you.

### Parent Helper Method

Sometimes you want to use the object that is nesting your resource, such as when you want to customize a redirect. SuperResources provides 
`parent` to answer that object. For example given, the following route:

    /notes/:note_id/pages/:id


calling `parent` will answer a Note object with an id of `:note_id`. 

For deeper nests, the immediately nested object is always answered by `parent`. For example, given this route:

    /authors/:author_id/notes/:note_id/pages/:id

calling `parent` will still answer a Note object with an id of `:note_id`. 

### Accessing Route Objects

Any nested route implies a component hierarchy of objects. SuperResources allows you to access these objects bye a convenient name.

For example, given this route:

    /authors/:author_id/notes/:note_id/pages/:id

you can make these calls:

    author  #=> Author with an id of :author_id
    note    #=> Note with an id of :note_id
    page    #=> Page with an id of :id

An example of a place where you will want these, is in a layout template that presents information about the nesting objects. For example, you may want to show a page inside an author layout template. The author layout template will present information about the author. In this case, the layout will be used in the context of `PagesController`, so you can't refer to `resource` in the layout, since it will answer the page, not the author. You need some way to arbitrarily refer to the author.  Being able to call `author` provides this.

## Adapting and Customising

### Resource Class

SuperResources derives the class of the target resource from the controller name. For example, `OrganizationUnitsController` operates, by default, on resources of the class `OrganizationUnit`. If you want to change this, redefine hotspot method `resource_class`, for example:

    class TeamsController < ApplicationController
      include SuperResources::Controller

      protected

      def resource_class
        OrganizationUnit
      end
    end

### Resource Helper Methods

Yes, you can adapt these to suit your needs. 

The `resource` and `collection` methods are used internally by the default RESTful actions provided by SuperResources, and can have their implementations customised easily. The return values of these methods are memoized for various reasons, for this you should make use of the `memoize_resource` and `memoize_collection` methods respectivley. Both methods take a block that is only executed as necessary.

For example, if you wanted 'TeamsController#collection' to return only those teams that the current user has joined, you would write an implementation of `collection` that calls its super, passing a block the evalautes to the right collection:

    def collection
      memoize_collection { resource_class.joined_by(current_user) }
    end

If that looks strange, bear in mind it's been designed so that you don't need to know how SuperResources internally uses your preferred implementation.

### Finder Method

Before being able to use the result of `resource`, SuperResources may need to find it. The canonical way to do this is to do:

    resource_class.find(:params[:id])

While SuperResource uses the `find` method as the default, you can choose another finder method by redefining `finder_method`. For example:

    class PagesController < ApplicationController

      protected

      def finder_method
        :find_by_position
      end
    end

### Builder Method

SuperResources extracts the construction of a new resource into the `build_resource` method. If you need to do specialized work for the build, override the `build_resource` method and be sure to memoize your result:

    def build_resource
      memoize_resource do
        resource_class.new do |p|
          # initialize the state here
        end
      end
    end

### Redefining Actions

Yes, you can. All actions defined by SuperResources use responders and accept parameters to pass to `respond_with`, so customizing these parameters is a common adaptation.

For example, suppose that after creating a comment, you want to redirect to an index of comments that apply to the same parent. Adapt the action like this:

    def create
      super :location => polymorphic_url([ parent, :comments ])
    end

Anything you can pass to `respond_with`, you can pass to the super call, including a block.

You could, of course, completely redefine an action:

    def new
      # knock yourself out
    end

### Defining Actions

Just do it. Declare them in your controller and match them in routes. All the SuperResources helpers are still available to you.

## Acknowledgments

SuperResources would never have happened without [InheritedResources](https://github.com/josevalim/inherited_resources) existing first.
We preferred the idea of abstracting and extracting RESTful actions out of all our controllers and we're not so keen on scaffolds generating
un-DRY code. We used InheritedResources in a production deployed application [MeetLinkShare](http://www.meetlinkshare.com), gained some experience and decided we wanted an even DRYer tool.

The basic mechanics of SuperResources was hacked out during Rails Camp 12 in Tasmania, Australia and was subsequently applied to MeetLinkShare.

{'fraction_non_alphanumeric': 0.043569131832797425, 'fraction_numerical': 0.0002679528403001072, 'mean_word_length': 4.278925035360679, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 13, 'https://': 2, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5117711', 'n_tokens_mistral': 4536, 'n_tokens_neox': 4334, 'n_words': 2613}