Skip to content

Commit

Permalink
Remove has_scope from core.
Browse files Browse the repository at this point in the history
  • Loading branch information
josevalim committed Dec 22, 2009
1 parent 499054b commit 9207c29
Show file tree
Hide file tree
Showing 10 changed files with 79 additions and 454 deletions.
9 changes: 7 additions & 2 deletions CHANGELOG
@@ -1,7 +1,12 @@
# Version 0.9.4
* responders was removed from InheritedResources core and is a dependency. To install it, please do:

* DEPRECATION: Use :success and :failure as flash messages instead :notice and :error
sudo gem install responders

* has_scope was removed from InheritedResources core and is now available as a standalone gem.
To install it, please do:

sudo gem install has_scope

# Version 0.9

* Allow dual blocks in destroy;
Expand Down
149 changes: 39 additions & 110 deletions README.rdoc
@@ -1,6 +1,4 @@
Inherited Resources
License: MIT
Version: 0.9.2

== Description

Expand All @@ -16,20 +14,53 @@ http://akitaonrails.com/2009/09/01/screencast-real-thin-restful-controllers-with

Inherited Resources is tested and compatible with Rails 2.2.x and Rails 2.3.x.

keywords: resources, controller, singleton, belongs_to, polymorphic, named_scope and I18n

== Installation

Install Inherited Resources is very easy. It is stored in GitHub, so just run
the following:
Inherited Resources is available as gem on Gemcutter, so just run the following:

gem sources -a http://gemcutter.org
sudo gem install inherited_resources

If you want it as plugin, just do:

script/plugin install git://github.com/josevalim/inherited_resources.git

== Inherited Resources 1.0

Inherited Resources finally reached 1.0 version. A couple things changed,
so be sure to read the following sections:

=== HasScope

Since Inherited Resources 1.0, has_scope is not part of its core anymore.
However, if you are using has_scope in your application, Inherited Resources
will all the required hooks automatically.

has_scope gem is available at:

http://github.com/plataformatec/has_scope

And can be installed as:

sudo gem install has_scope

=== Responders

Since Inherited Resources 1.0, responders are not part of its core anymore,
but is set as an Inherited Resources dependency and it's used by default by
InheritedResources controller. Be sure to check the documentation to see
how it will change your application:

http://github.com/plataformatec/responders

And it can be installed as:

sudo gem install responders

Using responders set the flash message to :notice and :alert. You can change
that through the following configuration value:

InheritedResources.flash_keys = [ :success, :failure ]

== Rspec known bug

When used with integrate_views equals to false, rspec overwrites default_render,
Expand Down Expand Up @@ -246,109 +277,6 @@ And then you can rewrite the last example as:
end
end

== Flash messages and I18n

Flash messages are powered by I18n api. It checks for messages in the following
order:

flash.controller_name.action_name.status
flash.actions.action_name.status

If none is available, a default message in english set. In a create action
on projects controller, it will search for:

flash.projects.create.status
flash.actions.create.status

The status can be :notice (when the object can be created, updated
or destroyed with success) or :error (when the objecy cannot be created
or updated).

Those messages are interpolated by using the resource class human name, which
is also localized and it means you can set:

flash:
actions:
create:
notice: "Hooray! {{resource_name}} was successfully created!"

It will replace {{resource_name}} by the human name of the resource class,
which is "Project" in this case.

But sometimes, flash messages are not that simple. Sometimes you want to say
the title of the project while updating a project. Well, that's easy also:

flash:
projects:
update:
notice: "Hooray! The project "{{project_title}}" was updated!"

Since :project_title is not available for interpolation by default, you have
to overwrite interpolation_options.

def interpolation_options
{ :project_title => @project.title }
end

Then you will finally have:

"Hooray! The project "Plataforma" was updated!"

By default, resource name is capitalized. If you want to make it lower case, you
can add to your application controller:

def interpolation_options
{ :resource_name => resource_class.human_name.downcase }
end

Finally, if your controller is namespaced, for example Admin::ProjectsController,
the messages will be checked in the following order:

flash.admin.projects.create.notice
flash.admin.actions.create.notice
flash.projects.create.notice
flash.actions.create.notice

== Has Scope

InheritedResources tries to integrate nicely with your model. In order to do so,
it also is named_scope fluent. Let's suppose our Project model with the scopes:

class Project < ActiveRecord::Base
named_scope :featured, :conditions => { :featured => true }
named_scope :by_methodology, proc {|methodology| { :conditions => { :methodology => methodology } } }
named_scope :limit, proc{|limit| :limit => limit.to_i }
end

Your controller:

class ProjectsController < InheritedResources::Base
has_scope :featured, :boolean => true, :only => :index
has_scope :by_methodology
has_scope :limit, :default => 10
end

Then for each request:

/projects
#=> acts like a normal request, but returning 10 projects

/projects?featured=true
#=> calls the featured named scope and bring 10 featured projects

/projects?featured=true&by_methodology=agile&limit=20
#=> brings 20 featured projects with methodology agile

You can retrieve the current scopes in use with :current_scopes method.
In the last case, it would return:

{ :featured => "true", :by_methodology => "agile", :limit => "20" }

Finally, let's suppose you store on the session how many projects the user sees
per page. In such cases, you can give a proc as default value:

has_scope :limit, :default => proc{|c| c.session[:limit] || 10 }

== Belongs to

Finally, our Projects are going to get some Tasks. Then you create a
Expand Down Expand Up @@ -522,3 +450,4 @@ If you discover any bugs or want to drop a line, join us in the mailing list:
http://groups.google.com/group/inherited_resources

Copyright (c) 2009 José Valim http://blog.plataformatec.com.br
See the attached MIT License.
4 changes: 2 additions & 2 deletions lib/inherited_resources/base.rb
Expand Up @@ -31,10 +31,10 @@ def self.inherit_resources(base)
base.with_options :instance_writer => false do |c|
c.class_inheritable_accessor :resource_class
c.class_inheritable_array :parents_symbols
c.class_inheritable_hash :resources_configuration, :scopes_configuration
c.class_inheritable_hash :resources_configuration
end

protected :resource_class, :parents_symbols, :resources_configuration, :scopes_configuration
protected :resource_class, :parents_symbols, :resources_configuration
end
end

Expand Down
8 changes: 4 additions & 4 deletions lib/inherited_resources/base_helpers.rb
Expand Up @@ -156,7 +156,7 @@ def resource_instance_name #:nodoc:
def end_of_association_chain #:nodoc:
if chain = association_chain.last
if method_for_association_chain
apply_scope_to(chain.send(method_for_association_chain))
apply_scopes_if_available(chain.send(method_for_association_chain))
else
# This only happens when we specify begin_of_association_chain in
# a singletion controller without parents. In this case, the chain
Expand All @@ -165,7 +165,7 @@ def end_of_association_chain #:nodoc:
chain
end
else
apply_scope_to(resource_class)
apply_scopes_if_available(resource_class)
end
end

Expand Down Expand Up @@ -347,8 +347,8 @@ def respond_with_dual_blocks(object, options, success, given_block, &block) #:no
# Hook to apply scopes. By default returns only the target_object given.
# It's extend by HasScopeHelpers.
#
def apply_scope_to(target_object) #:nodoc:
target_object
def apply_scopes_if_available(target_object) #:nodoc:
respond_to?(:apply_scopes) ? apply_scopes(target_object) : target_object
end

# Symbols chain in base helpers return nothing. This is later overwriten
Expand Down
83 changes: 1 addition & 82 deletions lib/inherited_resources/class_methods.rb
Expand Up @@ -71,86 +71,6 @@ def actions(*actions_to_keep)
end
end

# Detects params from url and apply as scopes to your classes.
#
# Your model:
#
# class Graduation < ActiveRecord::Base
# named_scope :featured, :conditions => { :featured => true }
# named_scope :by_degree, proc {|degree| { :conditions => { :degree => degree } } }
# end
#
# Your controller:
#
# class GraduationsController < InheritedResources::Base
# has_scope :featured, :boolean => true, :only => :index
# has_scope :by_degree, :only => :index
# end
#
# Then for each request:
#
# /graduations
# #=> acts like a normal request
#
# /graduations?featured=true
# #=> calls the named scope and bring featured graduations
#
# /graduations?featured=true&by_degree=phd
# #=> brings featured graduations with phd degree
#
# You can retrieve the current scopes in use with <tt>current_scopes</tt>
# method. In the last case, it would return: { :featured => "true", :by_degree => "phd" }
#
# == Options
#
# * <tt>:boolean</tt> - When set to true, call the scope only when the param is true or 1,
# and does not send the value as argument.
#
# * <tt>:only</tt> - In which actions the scope is applied. By default is :all.
#
# * <tt>:except</tt> - In which actions the scope is not applied. By default is :none.
#
# * <tt>:as</tt> - The key in the params hash expected to find the scope.
# Defaults to the scope name.
#
# * <tt>:if</tt> - Specifies a method, proc or string to call to determine
# if the scope should apply
#
# * <tt>:unless</tt> - Specifies a method, proc or string to call to determine
# if the scope should NOT apply.
#
# * <tt>:default</tt> - Default value for the scope. Whenever supplied the scope
# is always called. This is useful to add easy pagination.
#
def has_scope(*scopes)
options = scopes.extract_options!

options.symbolize_keys!
options.assert_valid_keys(:boolean, :key, :only, :except,
:if, :unless, :default, :as)

if options[:key]
ActiveSupport::Deprecation.warn "has_scope :key is deprecated, use :as instead"
options[:as] ||= options[:key]
end

if self.scopes_configuration.empty?
include HasScopeHelpers
helper_method :current_scopes
end

scopes.each do |scope|
self.scopes_configuration[scope] ||= {}
self.scopes_configuration[scope][:as] = options[:as] || scope
self.scopes_configuration[scope][:only] = Array(options[:only])
self.scopes_configuration[scope][:except] = Array(options[:except])

[:if, :unless, :boolean, :default].each do |opt|
self.scopes_configuration[scope][opt] = options[opt] if options.key?(opt)
end
end
end

# Defines that this controller belongs to another resource.
#
# belongs_to :projects
Expand Down Expand Up @@ -321,8 +241,7 @@ def initialize_resources_class_accessors! #:nodoc:
config[:route_prefix] = namespaces.join('_') unless namespaces.empty?

# Initialize polymorphic, singleton, scopes and belongs_to parameters
self.parents_symbols ||= []
self.scopes_configuration ||= {}
self.parents_symbols ||= []
self.resources_configuration[:polymorphic] ||= { :symbols => [], :optional => false }
end

Expand Down

0 comments on commit 9207c29

Please sign in to comment.