inherited-resources-1.9.0/ 0000755 0001750 0001750 00000000000 13470613050 016241 5 ustar utkarsh2102 utkarsh2102 inherited-resources-1.9.0/lib/ 0000755 0001750 0001750 00000000000 13470613050 017007 5 ustar utkarsh2102 utkarsh2102 inherited-resources-1.9.0/lib/generators/ 0000755 0001750 0001750 00000000000 13470613050 021160 5 ustar utkarsh2102 utkarsh2102 inherited-resources-1.9.0/lib/generators/rails/ 0000755 0001750 0001750 00000000000 13470613050 022272 5 ustar utkarsh2102 utkarsh2102 inherited-resources-1.9.0/lib/generators/rails/USAGE 0000644 0001750 0001750 00000000740 13470613050 023062 0 ustar utkarsh2102 utkarsh2102 Description:
Stubs out a scaffolded controller and its views using InheritedResources.
Pass the model name, either CamelCased or under_scored. The controller
name is retrieved as a pluralized version of the model name.
To create a controller within a module, specify the model name as a
path like 'parent_module/controller_name'.
This generates a controller class in app/controllers and invokes helper,
template engine and test framework generators.
inherited-resources-1.9.0/lib/generators/rails/inherited_resources_controller_generator.rb 0000644 0001750 0001750 00000000510 13470613050 033171 0 ustar utkarsh2102 utkarsh2102 require 'rails/generators/rails/scaffold_controller/scaffold_controller_generator'
module Rails
module Generators
class InheritedResourcesControllerGenerator < ScaffoldControllerGenerator
def self.source_root
@source_root ||= File.expand_path("templates", File.dirname(__FILE__))
end
end
end
end inherited-resources-1.9.0/lib/generators/rails/templates/ 0000755 0001750 0001750 00000000000 13470613050 024270 5 ustar utkarsh2102 utkarsh2102 inherited-resources-1.9.0/lib/generators/rails/templates/controller.rb 0000644 0001750 0001750 00000000650 13470613050 027001 0 ustar utkarsh2102 utkarsh2102 class <%= controller_class_name %>Controller < InheritedResources::Base
<% if options[:singleton] -%>
defaults :singleton => true
<% end -%>
<% if Rails::VERSION::MAJOR >= 4 || defined?(ActiveModel::ForbiddenAttributesProtection) -%>
private
def <%= singular_name %>_params
params.require(:<%= singular_name %>).permit(<%= attributes_names.map{ |a_name| ":#{a_name}" }.join(", ") %>)
end
<% end -%>
end
inherited-resources-1.9.0/lib/inherited_resources.rb 0000644 0001750 0001750 00000003246 13470613050 023406 0 ustar utkarsh2102 utkarsh2102 # This is here because responders don't require it.
require 'rails/engine'
require 'responders'
require 'inherited_resources/engine'
require 'inherited_resources/blank_slate'
require 'inherited_resources/responder'
module InheritedResources
ACTIONS = [ :index, :show, :new, :edit, :create, :update, :destroy ] unless self.const_defined?(:ACTIONS)
autoload :Actions, 'inherited_resources/actions'
autoload :BaseHelpers, 'inherited_resources/base_helpers'
autoload :ShallowHelpers, 'inherited_resources/shallow_helpers'
autoload :BelongsToHelpers, 'inherited_resources/belongs_to_helpers'
autoload :ClassMethods, 'inherited_resources/class_methods'
autoload :DSL, 'inherited_resources/dsl'
autoload :PolymorphicHelpers, 'inherited_resources/polymorphic_helpers'
autoload :SingletonHelpers, 'inherited_resources/singleton_helpers'
autoload :UrlHelpers, 'inherited_resources/url_helpers'
autoload :VERSION, 'inherited_resources/version'
# Change the flash keys used by FlashResponder.
def self.flash_keys=(array)
Responders::FlashResponder.flash_keys = array
end
end
ActiveSupport.on_load(:action_controller) do
# We can remove this check and change to `on_load(:action_controller_base)` in Rails 5.2.
if self == ActionController::Base
# If you cannot inherit from InheritedResources::Base you can call
# inherit_resources in your controller to have all the required modules and
# funcionality included.
def self.inherit_resources
InheritedResources::Base.inherit_resources(self)
initialize_resources_class_accessors!
create_resources_url_helpers!
end
end
end
inherited-resources-1.9.0/lib/inherited_resources/ 0000755 0001750 0001750 00000000000 13470613050 023054 5 ustar utkarsh2102 utkarsh2102 inherited-resources-1.9.0/lib/inherited_resources/engine.rb 0000644 0001750 0001750 00000000527 13470613050 024652 0 ustar utkarsh2102 utkarsh2102 module InheritedResources
class Railtie < ::Rails::Engine
config.inherited_resources = InheritedResources
if config.respond_to?(:app_generators)
config.app_generators.scaffold_controller = :inherited_resources_controller
else
config.generators.scaffold_controller = :inherited_resources_controller
end
end
end
inherited-resources-1.9.0/lib/inherited_resources/dsl.rb 0000644 0001750 0001750 00000001265 13470613050 024167 0 ustar utkarsh2102 utkarsh2102 module InheritedResources
# Allows controllers to write actions using a class method DSL.
#
# class MyController < InheritedResources::Base
# create! do |success, failure|
# success.html { render :text => "It works!" }
# end
# end
#
module DSL
def self.included(base)
ACTIONS.each do |action|
base.class_eval <<-WRITTER
def self.#{action}!(options={}, &block)
define_method :__#{action}, &block
class_eval <<-ACTION
def #{action}
super(\#{options.inspect}, &method(:__#{action}))
end
ACTION
end
WRITTER
end
end
end
end
inherited-resources-1.9.0/lib/inherited_resources/class_methods.rb 0000644 0001750 0001750 00000040334 13470613050 026235 0 ustar utkarsh2102 utkarsh2102 module InheritedResources
module ClassMethods
protected
# Used to overwrite the default assumptions InheritedResources do. Whenever
# this method is called, it should be on the top of your controller, since
# almost other methods depends on the values given to <>defaults.
#
# == Options
#
# * :resource_class - The resource class which by default is guessed
# by the controller name. Defaults to Project in
# ProjectsController.
#
# * :collection_name - The name of the collection instance variable which
# is set on the index action. Defaults to :projects in
# ProjectsController.
#
# * :instance_name - The name of the singular instance variable which
# is set on all actions besides index action. Defaults to
# :project in ProjectsController.
#
# * :route_collection_name - The name of the collection route. Defaults to :collection_name.
#
# * :route_instance_name - The name of the singular route. Defaults to :instance_name.
#
# * :route_prefix - The route prefix which is automically set in namespaced
# controllers. Default to :admin on Admin::ProjectsController.
#
# * :singleton - Tells if this controller is singleton or not.
#
# * :finder - Specifies which method should be called to instantiate the resource.
#
# defaults :finder => :find_by_slug
#
def defaults(options)
raise ArgumentError, 'Class method :defaults expects a hash of options.' unless options.is_a? Hash
options.symbolize_keys!
options.assert_valid_keys(:resource_class, :collection_name, :instance_name,
:class_name, :route_prefix, :route_collection_name,
:route_instance_name, :singleton, :finder)
self.resource_class = options[:resource_class] if options.key?(:resource_class)
self.resource_class = options[:class_name].constantize if options.key?(:class_name)
acts_as_singleton! if options.delete(:singleton)
config = self.resources_configuration[:self]
config[:route_prefix] = options.delete(:route_prefix) if options.key?(:route_prefix)
if options.key?(:resource_class) or options.key?(:class_name)
config[:request_name] = begin
request_name = self.resource_class
request_name = request_name.model_name.param_key if request_name.respond_to?(:model_name)
request_name.to_s.underscore.gsub('/', '_')
end
options.delete(:resource_class) and options.delete(:class_name)
end
options.each do |key, value|
config[key] = value.to_sym
end
create_resources_url_helpers!
end
# Defines wich actions will be inherited from the inherited controller.
# Syntax is borrowed from resource_controller.
#
# actions :index, :show, :edit
# actions :all, :except => :index
#
def actions(*actions_to_keep)
raise ArgumentError, 'Wrong number of arguments. You have to provide which actions you want to keep.' if actions_to_keep.empty?
options = actions_to_keep.extract_options!
actions_to_remove = Array(options[:except])
actions_to_remove += ACTIONS - actions_to_keep.map { |a| a.to_sym } unless actions_to_keep.first == :all
actions_to_remove.map! { |a| a.to_sym }.uniq!
(instance_methods.map { |m| m.to_sym } & actions_to_remove).each do |action|
undef_method action, "#{action}!"
end
end
# Defines that this controller belongs to another resource.
#
# belongs_to :projects
#
# == Options
#
# * :parent_class - Allows you to specify what is the parent class.
#
# belongs_to :project, :parent_class => AdminProject
#
# * :class_name - Also allows you to specify the parent class, but you should
# give a string. Added for ActiveRecord belongs to compatibility.
#
# * :instance_name - The instance variable name. By default is the name of the association.
#
# belongs_to :project, :instance_name => :my_project
#
# * :finder - Specifies which method should be called to instantiate the parent.
#
# belongs_to :project, :finder => :find_by_title!
#
# This will make your projects be instantiated as:
#
# Project.find_by_title!(params[:project_id])
#
# Instead of:
#
# Project.find(params[:project_id])
#
# * :param - Allows you to specify params key to retrieve the id.
# Default is :association_id, which in this case is :project_id.
#
# * :route_name - Allows you to specify what is the route name in your url
# helper. By default is association name.
#
# * :collection_name - Tell how to retrieve the next collection. Let's
# suppose you have Tasks which belongs to Projects
# which belongs to companies. This will do somewhere
# down the road:
#
# @company.projects
#
# But if you want to retrieve instead:
#
# @company.admin_projects
#
# You supply the collection name.
#
# * :polymorphic - Tell the association is polymorphic.
#
# * :singleton - Tell it's a singleton association.
#
# * :optional - Tell the association is optional (it's a special
# type of polymorphic association)
#
def belongs_to(*symbols, &block)
options = symbols.extract_options!
options.symbolize_keys!
options.assert_valid_keys(:class_name, :parent_class, :instance_name, :param,
:finder, :route_name, :collection_name, :singleton,
:polymorphic, :optional, :shallow)
optional = options.delete(:optional)
shallow = options.delete(:shallow)
polymorphic = options.delete(:polymorphic)
finder = options.delete(:finder)
include BelongsToHelpers if self.parents_symbols.empty?
acts_as_polymorphic! if polymorphic || optional
acts_as_shallow! if shallow
raise ArgumentError, 'You have to give me at least one association name.' if symbols.empty?
raise ArgumentError, "You cannot define multiple associations with options: #{options.keys.inspect} to belongs to." unless symbols.size == 1 || options.empty?
symbols.each do |symbol|
symbol = symbol.to_sym
if polymorphic || optional
self.parents_symbols << :polymorphic unless self.parents_symbols.include?(:polymorphic)
self.resources_configuration[:polymorphic][:symbols] << symbol
self.resources_configuration[:polymorphic][:optional] ||= optional
else
self.parents_symbols << symbol
end
self.resources_configuration[:self][:shallow] = true if shallow
config = self.resources_configuration[symbol] = {}
class_name = ''
config[:parent_class] = options.delete(:parent_class) ||
begin
class_name = if options[:class_name]
options.delete(:class_name)
else
namespace = self.name.deconstantize
model_name = symbol.to_s.pluralize.classify
klass = model_name
while namespace != ''
new_klass = "#{namespace}::#{model_name}"
if new_klass.safe_constantize
klass = new_klass
break
else
namespace = namespace.deconstantize
end
end
klass = model_name if klass.start_with?('::')
klass
end
class_name.constantize
rescue NameError => e
raise unless e.message.include?(class_name)
nil
end
config[:singleton] = options.delete(:singleton) || false
config[:collection_name] = options.delete(:collection_name) || symbol.to_s.pluralize.to_sym
config[:instance_name] = options.delete(:instance_name) || symbol
config[:param] = options.delete(:param) || :"#{symbol}_id"
config[:route_name] = options.delete(:route_name) || symbol
config[:finder] = finder || :find
end
if block_given?
class_eval(&block)
else
create_resources_url_helpers!
end
helper_method :parent, :parent?
end
alias :nested_belongs_to :belongs_to
# A quick method to declare polymorphic belongs to.
#
def polymorphic_belongs_to(*symbols, &block)
options = symbols.extract_options!
options.merge!(:polymorphic => true)
belongs_to(*symbols, options, &block)
end
# A quick method to declare singleton belongs to.
#
def singleton_belongs_to(*symbols, &block)
options = symbols.extract_options!
options.merge!(:singleton => true)
belongs_to(*symbols, options, &block)
end
# A quick method to declare optional belongs to.
#
def optional_belongs_to(*symbols, &block)
options = symbols.extract_options!
options.merge!(:optional => true)
belongs_to(*symbols, options, &block)
end
# Defines custom restful actions by resource or collection basis.
#
# custom_actions :resource => [:delete, :transit], :collection => :search
#
# == Options
#
# * :resource - Allows you to specify resource actions.
# custom_actions :resource => :delete
# This macro creates 'delete' method in controller and defines
# delete_resource_{path,url} helpers. The body of generated 'delete'
# method is same as 'show' method. So you can override it if need
#
# * :collection - Allows you to specify collection actions.
# custom_actions :collection => :search
# This macro creates 'search' method in controller and defines
# search_resources_{path,url} helpers. The body of generated 'search'
# method is same as 'index' method. So you can override it if need
#
def custom_actions(options)
self.resources_configuration[:self][:custom_actions] = options
options.each do | resource_or_collection, actions |
[*actions].each do | action |
create_custom_action(resource_or_collection, action)
end
end
create_resources_url_helpers!
[*options[:resource]].each do | action |
helper_method "#{action}_resource_path", "#{action}_resource_url"
end
[*options[:collection]].each do | action |
helper_method "#{action}_resources_path", "#{action}_resources_url"
end
end
# Defines the role to use when creating or updating resource.
# Makes sense when using rails 3.1 mass assignment conventions
def with_role(role)
self.resources_configuration[:self][:role] = role.try(:to_sym)
end
def without_protection(flag)
self.resources_configuration[:self][:without_protection] = flag
end
private
def acts_as_singleton! #:nodoc:
unless self.resources_configuration[:self][:singleton]
self.resources_configuration[:self][:singleton] = true
include SingletonHelpers
actions :all, :except => :index
end
end
def acts_as_polymorphic! #:nodoc:
unless self.parents_symbols.include?(:polymorphic)
include PolymorphicHelpers
helper_method :parent_type, :parent_class
end
end
def acts_as_shallow! #:nodoc:
include BelongsToHelpers
include ShallowHelpers
end
# Initialize resources class accessors and set their default values.
#
def initialize_resources_class_accessors! #:nodoc:
# First priority is the namespaced model, e.g. User::Group
self.resource_class ||= begin
namespaced_class = self.name.sub(/Controller$/, '').singularize
namespaced_class.constantize
rescue NameError
nil
end
# Second priority is the top namespace model, e.g. EngineName::Article for EngineName::Admin::ArticlesController
self.resource_class ||= begin
namespaced_classes = self.name.sub(/Controller$/, '').split('::')
namespaced_class = [namespaced_classes.first, namespaced_classes.last].join('::').singularize
namespaced_class.constantize
rescue NameError
nil
end
# Third priority the camelcased c, i.e. UserGroup
self.resource_class ||= begin
camelcased_class = self.name.sub(/Controller$/, '').gsub('::', '').singularize
camelcased_class.constantize
rescue NameError
nil
end
# Otherwise use the Group class, or fail
self.resource_class ||= begin
class_name = self.controller_name.classify
class_name.constantize
rescue NameError => e
raise unless e.message.include?(class_name)
nil
end
self.parents_symbols = self.parents_symbols.try(:dup) || []
# Initialize resources configuration hash
self.resources_configuration = self.resources_configuration.try(:dup) || {}
self.resources_configuration.each do |key, value|
next unless value.is_a?(Hash) || value.is_a?(Array)
self.resources_configuration[key] = value.dup
end
config = (self.resources_configuration[:self] ||= {})
config[:collection_name] = self.controller_name.to_sym
config[:instance_name] = self.controller_name.singularize.to_sym
config[:route_collection_name] = config[:collection_name]
config[:route_instance_name] = config[:instance_name]
# Deal with namespaced controllers
namespaces = self.controller_path.split('/')[0..-2]
# Remove namespace if its a mountable engine
namespaces.delete_if do |namespace|
begin
"#{namespace}/engine".camelize.constantize.isolated?
rescue StandardError, LoadError
false
end
end
config[:route_prefix] = namespaces.join('_') unless namespaces.empty?
# Deal with default request parameters in namespaced controllers, e.g.
# Forum::Thread#create will properly pick up the request parameter
# which will be forum_thread, and not thread
# Additionally make this work orthogonally with instance_name
config[:request_name] = self.resource_class.to_s.underscore.gsub('/', '_')
# Initialize polymorphic, singleton, scopes and belongs_to parameters
polymorphic = self.resources_configuration[:polymorphic] || { :symbols => [], :optional => false }
polymorphic[:symbols] = polymorphic[:symbols].dup
self.resources_configuration[:polymorphic] = polymorphic
end
def create_custom_action(resource_or_collection, action)
class_eval <<-CUSTOM_ACTION, __FILE__, __LINE__
def #{action}(options={}, &block)
respond_with(*with_chain(#{resource_or_collection}), options, &block)
end
alias :#{action}! :#{action}
protected :#{action}!
CUSTOM_ACTION
end
# Hook called on inheritance.
#
def inherited(base) #:nodoc:
super(base)
base.send :initialize_resources_class_accessors!
base.send :create_resources_url_helpers!
end
end
end
inherited-resources-1.9.0/lib/inherited_resources/polymorphic_helpers.rb 0000644 0001750 0001750 00000012314 13470613050 027471 0 ustar utkarsh2102 utkarsh2102 module InheritedResources
# = polymorphic associations
#
# In some cases you have a resource that belongs to two different resources
# but not at the same time. For example, let's suppose you have File, Message
# and Task as resources and they are all commentable.
#
# Polymorphic associations allows you to create just one controller that will
# deal with each case.
#
# class Comment < InheritedResources::Base
# belongs_to :file, :message, :task, :polymorphic => true
# end
#
# Your routes should be something like:
#
# resources :files do
# resources :comments #=> /files/13/comments
# end
# resources :tasks do
# resources :comments #=> /tasks/17/comments
# end
# resources :messages do
# resources :comments #=> /messages/11/comments
# end
#
# When using polymorphic associations, you get some free helpers:
#
# parent? #=> true
# parent_type #=> :task
# parent_class #=> Task
# parent #=> @task
#
# This polymorphic controllers thing is a great idea by James Golick and he
# built it in resource_controller. Here is just a re-implementation.
#
# = optional polymorphic associations
#
# Let's take another break from ProjectsController. Let's suppose we are
# building a store, which sell products.
#
# On the website, we can show all products, but also products scoped to
# categories, brands, users. In this case case, the association is optional, and
# we deal with it in the following way:
#
# class ProductsController < InheritedResources::Base
# belongs_to :category, :brand, :user, :polymorphic => true, :optional => true
# end
#
# This will handle all those urls properly:
#
# /products/1
# /categories/2/products/5
# /brands/10/products/3
# /user/13/products/11
#
# = nested polymorphic associations
#
# You can have polymorphic associations with nested resources. Let's suppose
# that our File, Task and Message resources in the previous example belongs to
# a project.
#
# This way we can have:
#
# class CommentsController < InheritedResources::Base
# belongs_to :project {
# belongs_to :file, :message, :task, :polymorphic => true
# }
# end
#
# Or:
#
# class CommentsController < InheritedResources::Base
# nested_belongs_to :project
# nested_belongs_to :file, :message, :task, :polymorphic => true
# end
#
# Choose the syntax that makes more sense to you. :)
#
# Finally your routes should be something like:
#
# resources :projects do
# resources :files do
# resources :comments #=> /projects/1/files/13/comments
# end
# resources :tasks do
# resources :comments #=> /projects/1/tasks/17/comments
# end
# resources :messages do
# resources :comments #=> /projects/1/messages/11/comments
# end
# end
#
# The helpers work in the same way as above.
#
module PolymorphicHelpers
protected
# Returns the parent type. A Comments class can have :task, :file, :note
# as parent types.
#
def parent_type
unless @parent_type
symbols_for_association_chain
end
@parent_type
end
def parent_class
parent.class if parent_type
end
# Returns the parent object. They are also available with the instance
# variable name: @task, @file, @note...
#
def parent
if parent_type
p = instance_variable_get("@#{parent_type}")
p || instance_variable_set("@#{parent_type}", association_chain[-1])
end
end
# If the polymorphic association is optional, we might not have a parent.
#
def parent?
if resources_configuration[:polymorphic][:optional]
parents_symbols.size > 1 || !parent_type.nil?
else
true
end
end
private
# Maps parents_symbols to build association chain.
#
# If the parents_symbols find :polymorphic, it goes through the
# params keys to see which polymorphic parent matches the given params.
#
# When optional is given, it does not raise errors if the polymorphic
# params are missing.
#
def symbols_for_association_chain #:nodoc:
polymorphic_config = resources_configuration[:polymorphic]
parents_symbols.map do |symbol|
if symbol == :polymorphic
params_keys = params.keys
keys = polymorphic_config[:symbols].map do |poly|
params_keys.include?(resources_configuration[poly][:param].to_s) ? poly : nil
end.compact
if keys.empty?
raise ScriptError, "Could not find param for polymorphic association. The request " <<
"parameters are #{params.keys.inspect} and the polymorphic " <<
"associations are #{polymorphic_config[:symbols].inspect}." unless polymorphic_config[:optional]
nil
else
@parent_type = keys[-1].to_sym
@parent_types = keys.map(&:to_sym)
end
else
symbol
end
end.flatten.compact
end
end
end
inherited-resources-1.9.0/lib/inherited_resources/actions.rb 0000644 0001750 0001750 00000003144 13470613050 025043 0 ustar utkarsh2102 utkarsh2102 module InheritedResources
# Holds all default actions for InheritedResouces.
module Actions
# GET /resources
def index(options={}, &block)
respond_with(*with_chain(collection), options, &block)
end
alias :index! :index
# GET /resources/1
def show(options={}, &block)
respond_with(*with_chain(resource), options, &block)
end
alias :show! :show
# GET /resources/new
def new(options={}, &block)
respond_with(*with_chain(build_resource), options, &block)
end
alias :new! :new
# GET /resources/1/edit
def edit(options={}, &block)
respond_with(*with_chain(resource), options, &block)
end
alias :edit! :edit
# POST /resources
def create(options={}, &block)
object = build_resource
if create_resource(object)
options[:location] ||= smart_resource_url
end
respond_with_dual_blocks(object, options, &block)
end
alias :create! :create
# PUT /resources/1
def update(options={}, &block)
object = resource
if update_resource(object, resource_params)
options[:location] ||= smart_resource_url
end
respond_with_dual_blocks(object, options, &block)
end
alias :update! :update
# DELETE /resources/1
def destroy(options={}, &block)
object = resource
options[:location] ||= smart_collection_url
destroy_resource(object)
respond_with_dual_blocks(object, options, &block)
end
alias :destroy! :destroy
# Make aliases protected
protected :index!, :show!, :new!, :create!, :edit!, :update!, :destroy!
end
end
inherited-resources-1.9.0/lib/inherited_resources/belongs_to_helpers.rb 0000644 0001750 0001750 00000006555 13470613050 027271 0 ustar utkarsh2102 utkarsh2102 module InheritedResources
# = belongs_to
#
# Let's suppose that we have some tasks that belongs to projects. To specify
# this assoication in your controllers, just do:
#
# class TasksController < InheritedResources::Base
# belongs_to :project
# end
#
# belongs_to accepts several options to be able to configure the association.
# For example, if you want urls like /projects/:project_title/tasks, you
# can customize how InheritedResources find your projects:
#
# class TasksController < InheritedResources::Base
# belongs_to :project, :finder => :find_by_title!, :param => :project_title
# end
#
# It also accepts :route_name, :parent_class and :instance_name as options.
# Check the lib/inherited_resources/class_methods.rb for more.
#
# = nested_belongs_to
#
# Now, our Tasks get some Comments and you need to nest even deeper. Good
# practices says that you should never nest more than two resources, but sometimes
# you have to for security reasons. So this is an example of how you can do it:
#
# class CommentsController < InheritedResources::Base
# nested_belongs_to :project, :task
# end
#
# If you need to configure any of these belongs to, you can nested them using blocks:
#
# class CommentsController < InheritedResources::Base
# belongs_to :project, :finder => :find_by_title!, :param => :project_title do
# belongs_to :task
# end
# end
#
# Warning: calling several belongs_to is the same as nesting them:
#
# class CommentsController < InheritedResources::Base
# belongs_to :project
# belongs_to :task
# end
#
# In other words, the code above is the same as calling nested_belongs_to.
#
module BelongsToHelpers
protected
# Parent is always true when belongs_to is called.
#
def parent?
true
end
def parent
@parent ||= association_chain[-1]
end
def parent_type
parent.class.name.underscore.to_sym
end
private
# Evaluate the parent given. This is used to nest parents in the
# association chain.
#
def evaluate_parent(parent_symbol, parent_config, chain = nil) #:nodoc:
get_parent_ivar(parent_config[:instance_name]) ||
set_parent_instance(parent_config, chain)
end
def get_parent_ivar(instance_name) #:nodoc:
instance_variable_defined?(:"@#{instance_name}") &&
instance_variable_get("@#{instance_name}")
end
def set_parent_instance(parent_config, chain) #:nodoc:
if parent_config[:singleton]
parent = if chain
chain.send(parent_config[:instance_name])
else
nil
end
else
parent = if chain
chain.send(parent_config[:collection_name])
else
parent_config[:parent_class]
end
parent = parent.send(parent_config[:finder], params[parent_config[:param]])
end
instance_variable_set("@#{parent_config[:instance_name]}", parent)
end
# Maps parents_symbols to build association chain. In this case, it
# simply return the parent_symbols, however on polymorphic belongs to,
# it has some customization.
#
def symbols_for_association_chain #:nodoc:
parents_symbols
end
end
end
inherited-resources-1.9.0/lib/inherited_resources/version.rb 0000644 0001750 0001750 00000000071 13470613050 025064 0 ustar utkarsh2102 utkarsh2102 module InheritedResources
VERSION = '1.9.0'.freeze
end
inherited-resources-1.9.0/lib/inherited_resources/responder.rb 0000644 0001750 0001750 00000000173 13470613050 025403 0 ustar utkarsh2102 utkarsh2102 module InheritedResources
class Responder < ActionController::Responder
include Responders::FlashResponder
end
end
inherited-resources-1.9.0/lib/inherited_resources/base_helpers.rb 0000644 0001750 0001750 00000031637 13470613050 026047 0 ustar utkarsh2102 utkarsh2102 # Whenever base is required load the dumb responder since it's used inside actions.
require 'inherited_resources/blank_slate'
module InheritedResources
# Base helpers for InheritedResource work. Some methods here can be overwritten
# and you will need to do that to customize your controllers from time to time.
#
module BaseHelpers
protected
# This is how the collection is loaded.
#
# You might want to overwrite this method if you want to add pagination
# for example. When you do that, don't forget to cache the result in an
# instance_variable:
#
# def collection
# @projects ||= end_of_association_chain.paginate(params[:page]).all
# end
#
def collection
get_collection_ivar || begin
c = end_of_association_chain
if defined?(ActiveRecord::DeprecatedFinders)
# ActiveRecord::Base#scoped and ActiveRecord::Relation#all
# are deprecated in Rails 4. If it's a relation just use
# it, otherwise use .all to get a relation.
set_collection_ivar(c.is_a?(ActiveRecord::Relation) ? c : c.all)
else
set_collection_ivar(c.respond_to?(:scoped) ? c.scoped : c.all)
end
end
end
# This is how the resource is loaded.
#
# You might want to overwrite this method when you are using permalink.
# When you do that, don't forget to cache the result in an
# instance_variable:
#
# def resource
# @project ||= end_of_association_chain.find_by_permalink!(params[:id])
# end
#
# You also might want to add the exclamation mark at the end of the method
# because it will raise a 404 if nothing can be found. Otherwise it will
# probably render a 500 error message.
#
def resource
get_resource_ivar || set_resource_ivar(end_of_association_chain.send(method_for_find, params[:id]))
end
# This method is responsible for building the object on :new and :create
# methods. If you overwrite it, don't forget to cache the result in an
# instance variable.
#
def build_resource
get_resource_ivar || set_resource_ivar(end_of_association_chain.send(method_for_build, *resource_params))
end
# Responsible for saving the resource on :create method. Overwriting this
# allow you to control the way resource is saved. Let's say you have a
# PassworsController who is responsible for finding an user by email and
# sent password instructions for him. Instead of overwriting the entire
# :create method, you could do something:
#
# def create_resource(object)
# object.send_instructions_by_email
# end
#
def create_resource(object)
object.save
end
# Responsible for updating the resource in :update method. This allow you
# to handle how the resource is going to be updated, let's say in a different
# way than the usual :update_attributes:
#
# def update_resource(object, attributes)
# object.reset_password!(attributes)
# end
#
def update_resource(object, attributes)
object.update_attributes(*attributes)
end
# Handle the :destroy method for the resource. Overwrite it to call your
# own method for destroying the resource, as:
#
# def destroy_resource(object)
# object.cancel
# end
#
def destroy_resource(object)
object.destroy
end
# This class allows you to set a instance variable to begin your
# association chain. For example, usually your projects belongs to users
# and that means that they belong to the current logged in user. So you
# could do this:
#
# def begin_of_association_chain
# @current_user
# end
#
# So every time we instantiate a project, we will do:
#
# @current_user.projects.build(params[:project])
# @current_user.projects.find(params[:id])
#
# The variable set in begin_of_association_chain is not sent when building
# urls, so this is never going to happen when calling resource_url:
#
# project_url(@current_user, @project)
#
# If the user actually scopes the url, you should use belongs_to method
# and declare that projects belong to user.
#
def begin_of_association_chain
nil
end
# Returns if the controller has a parent. When only base helpers are loaded,
# it's always false and should not be overwritten.
#
def parent?
false
end
# Returns the association chain, with all parents (does not include the
# current resource).
#
def association_chain
@association_chain ||=
symbols_for_association_chain.inject([begin_of_association_chain]) do |chain, symbol|
chain << evaluate_parent(symbol, resources_configuration[symbol], chain.last)
end.compact.freeze
end
# Overwrite this method to provide other interpolation options when
# the flash message is going to be set.
#
# def flash_interpolation_options
# { }
# end
private
# Adds the given object to association chain.
def with_chain(object)
association_chain + [ object ]
end
# Fast accessor to resource_collection_name
#
def resource_collection_name #:nodoc:
self.resources_configuration[:self][:collection_name]
end
# Fast accessor to resource_instance_name
#
def resource_instance_name #:nodoc:
self.resources_configuration[:self][:instance_name]
end
def resource_request_name
self.resources_configuration[:self][:request_name]
end
# This methods gets your begin_of_association_chain, join it with your
# parents chain and returns the scoped association.
def end_of_association_chain #:nodoc:
if chain = association_chain.last
if 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 singleton controller without parents. In this case, the chain
# is exactly the begin_of_association_chain which is already an
# instance and then not scopable.
chain
end
else
apply_scopes_if_available(resource_class)
end
end
# Returns the appropriated method to build the resource.
#
def method_for_build #:nodoc:
(begin_of_association_chain || parent?) ? method_for_association_build : :new
end
# Returns the name of the method used for building the resource in cases
# where we have a parent. This is overwritten in singleton scenarios.
#
def method_for_association_build
:build
end
# Returns the name of the method to be called, before returning the end
# of the association chain. This is overwritten by singleton cases
# where no method for association chain is called.
#
def method_for_association_chain #:nodoc:
resource_collection_name
end
# Returns finder method for instantiate resource by params[:id]
def method_for_find
resources_configuration[:self][:finder] || :find
end
# Get resource ivar based on the current resource controller.
#
def get_resource_ivar #:nodoc:
if instance_variable_defined?(:"@#{resource_instance_name}")
instance_variable_get("@#{resource_instance_name}")
else
nil
end
end
# Set resource ivar based on the current resource controller.
#
def set_resource_ivar(resource) #:nodoc:
instance_variable_set("@#{resource_instance_name}", resource)
end
# Get collection ivar based on the current resource controller.
#
def get_collection_ivar #:nodoc:
if instance_variable_defined?(:"@#{resource_collection_name}")
instance_variable_get("@#{resource_collection_name}")
else
nil
end
end
# Set collection ivar based on the current resource controller.
#
def set_collection_ivar(collection) #:nodoc:
instance_variable_set("@#{resource_collection_name}", collection)
end
# Used to allow to specify success and failure within just one block:
#
# def create
# create! do |success, failure|
# failure.html { redirect_to root_url }
# end
# end
#
# It also calculates the response url in case a block without arity is
# given and returns it. Otherwise returns nil.
#
def respond_with_dual_blocks(object, options, &block) #:nodoc:
args = (with_chain(object) << options)
case block.try(:arity)
when 2
respond_with(*args) do |responder|
blank_slate = InheritedResources::BlankSlate.new
if object.errors.empty?
block.call(responder, blank_slate)
else
block.call(blank_slate, responder)
end
end
when 1
respond_with(*args, &block)
else
options[:location] = block.call if block
respond_with(*args)
end
end
# Hook to apply scopes. By default returns only the target_object given.
# It's extend by HasScopeHelpers.
#
def apply_scopes_if_available(target_object) #:nodoc:
respond_to?(:apply_scopes, true) ? apply_scopes(target_object) : target_object
end
# Symbols chain in base helpers return nothing. This is later overwritten
# by belongs_to and can be complex in polymorphic cases.
#
def symbols_for_association_chain #:nodoc:
[]
end
# URL to redirect to when redirect implies resource url.
def smart_resource_url
url = nil
if respond_to? :show
url = resource_url rescue nil
end
url ||= smart_collection_url
end
# URL to redirect to when redirect implies collection url.
def smart_collection_url
url = nil
if respond_to? :index
url ||= collection_url rescue nil
end
if respond_to? :parent, true
url ||= parent_url rescue nil
end
url ||= root_url rescue nil
end
# memoize the extraction of attributes from params
def resource_params
@resource_params ||= build_resource_params
end
def resource_params_method_name
"#{resource_instance_name}_params"
end
# Returns hash of sanitized params in a form like
# `{:project => {:project_attribute => 'value'}}`
#
# This method makes use of `project_params` (or `smth_else_params`) which
# is a default Rails controller method for strong parameters definition.
#
# `permitted_params` is usually fired by method :new, :create, :update
# actions. Action :new usually has no parameters so strong parameters
# `require` directive raises a +ActionController::ParameterMissing+
# exception. `#permitted_params` rescues such exceptions in :new and
# returns an empty hash of parameters (which is reasonable default).
# If for any reasons you need something more specific, you can redefine
# this method in a way previous `inherited_resources` versions did:
#
# # Unnecessary redefinition
# def permitted_params
# params.permit(:project => [:project_attribute])
# end
#
def permitted_params
return nil unless respond_to?(resource_params_method_name, true)
{resource_request_name => send(resource_params_method_name)}
rescue ActionController::ParameterMissing
# typically :new action
if params[:action].to_s == 'new'
{resource_request_name => {}}
else
raise
end
end
# extract attributes from params
def build_resource_params
parameters = permitted_params || params
rparams = [parameters[resource_request_name] || parameters[resource_instance_name] || {}]
if without_protection_given?
rparams << without_protection
else
rparams << as_role if role_given?
end
rparams
end
# checking if role given
def role_given?
self.resources_configuration[:self][:role].present?
end
# getting role for mass-asignment
def as_role
{ :as => self.resources_configuration[:self][:role] }
end
def without_protection_given?
self.resources_configuration[:self][:without_protection].present?
end
def without_protection
{ :without_protection => self.resources_configuration[:self][:without_protection] }
end
end
end
inherited-resources-1.9.0/lib/inherited_resources/shallow_helpers.rb 0000644 0001750 0001750 00000003065 13470613050 026600 0 ustar utkarsh2102 utkarsh2102 module InheritedResources
# Shallow provides a functionality that goes on pair with Rails' shallow.
# It is very similar to "optional" but it actually finds all the parents
# resources instead of leaving them blank. Consider the following example:
#
# belongs_to :post, :shallow => true do
# belongs_to :comment
# end
#
# When accessed as /comments/1, Inherited Resources will automatically get
# the post resource so both objects are actually accessible through the views.
#
# However, when using optional, Inherited Resources wouldn't actually bother
# with finding the parent object.
module ShallowHelpers
private
def symbols_for_association_chain #:nodoc:
parent_symbols = parents_symbols.dup
instance = nil
if id = params[:id]
finder_method = resources_configuration[:self][:finder] || :find
instance = self.resource_class.send(finder_method, id)
elsif parents_symbols.size > 1
config = resources_configuration[parent_symbols.pop]
finder_method = config[:finder] || :find
instance = config[:parent_class].send(finder_method, params[config[:param]])
end
load_parents(instance, parent_symbols) if instance
parents_symbols
end
def load_parents(instance, parent_symbols)
parent_symbols.reverse.each do |parent|
instance = instance.send(parent)
config = resources_configuration[parent]
params[config[:param]] = instance.to_param
end
end
end
end
inherited-resources-1.9.0/lib/inherited_resources/singleton_helpers.rb 0000644 0001750 0001750 00000005114 13470613050 027126 0 ustar utkarsh2102 utkarsh2102 module InheritedResources
# = singleton
#
# Singletons are usually used in associations which are related through has_one
# and belongs_to. You declare those associations like this:
#
# class ManagersController < InheritedResources::Base
# belongs_to :project, :singleton => true
# end
#
# But in some cases, like an AccountsController, you have a singleton object
# that is not necessarily associated with another:
#
# class AccountsController < InheritedResources::Base
# defaults :singleton => true
# end
#
# Besides that, you should overwrite the methods :resource and :build_resource
# to make it work properly:
#
# class AccountsController < InheritedResources::Base
# defaults :singleton => true
#
# protected
# def resource
# @current_user.account
# end
#
# def build_resource(attributes = {})
# Account.new(attributes)
# end
# end
#
# When you have a singleton controller, the action index is removed.
#
module SingletonHelpers
protected
# Singleton methods does not deal with collections.
#
def collection
nil
end
# Overwrites how singleton deals with resource.
#
# If you are going to overwrite it, you should notice that the
# end_of_association_chain here is not the same as in default belongs_to.
#
# class TasksController < InheritedResources::Base
# belongs_to :project
# end
#
# In this case, the association chain would be:
#
# Project.find(params[:project_id]).tasks
#
# So you would just have to call find(:all) at the end of association
# chain. And this is what happened.
#
# In singleton controllers:
#
# class ManagersController < InheritedResources::Base
# belongs_to :project, :singleton => true
# end
#
# The association chain will be:
#
# Project.find(params[:project_id])
#
# So we have to call manager on it, not find.
#
def resource
get_resource_ivar || set_resource_ivar(end_of_association_chain.send(resource_instance_name))
end
private
# Returns the appropriated method to build the resource.
#
def method_for_association_build #:nodoc:
:"build_#{resource_instance_name}"
end
# Sets the method_for_association_chain to nil. See resource
# above for more information.
#
def method_for_association_chain #:nodoc:
nil
end
end
end
inherited-resources-1.9.0/lib/inherited_resources/blank_slate.rb 0000644 0001750 0001750 00000000413 13470613050 025656 0 ustar utkarsh2102 utkarsh2102 module InheritedResources
# An object from BlankSlate simply discards all messages sent to it.
class BlankSlate
instance_methods.each do |m|
undef_method m unless m =~ /^(__|object_id)/
end
def method_missing(*args)
nil
end
end
end
inherited-resources-1.9.0/lib/inherited_resources/url_helpers.rb 0000644 0001750 0001750 00000021746 13470613050 025737 0 ustar utkarsh2102 utkarsh2102 module InheritedResources
# = URLHelpers
#
# When you use InheritedResources it creates some UrlHelpers for you.
# And they handle everything for you.
#
# # /posts/1/comments
# resource_url # => /posts/1/comments/#{@comment.to_param}
# resource_url(comment) # => /posts/1/comments/#{comment.to_param}
# new_resource_url # => /posts/1/comments/new
# edit_resource_url # => /posts/1/comments/#{@comment.to_param}/edit
# collection_url # => /posts/1/comments
# parent_url # => /posts/1
#
# # /projects/1/tasks
# resource_url # => /projects/1/tasks/#{@task.to_param}
# resource_url(task) # => /projects/1/tasks/#{task.to_param}
# new_resource_url # => /projects/1/tasks/new
# edit_resource_url # => /projects/1/tasks/#{@task.to_param}/edit
# collection_url # => /projects/1/tasks
# parent_url # => /projects/1
#
# # /users
# resource_url # => /users/#{@user.to_param}
# resource_url(user) # => /users/#{user.to_param}
# new_resource_url # => /users/new
# edit_resource_url # => /users/#{@user.to_param}/edit
# collection_url # => /users
# parent_url # => /
#
# The nice thing is that those urls are not guessed during runtime. They are
# all created when you inherit.
#
module UrlHelpers
protected
# This method hard code url helpers in the class.
#
# We are doing this because is cheaper than guessing them when our action
# is being processed (and even more cheaper when we are using nested
# resources).
#
# When we are using polymorphic associations, those helpers rely on
# polymorphic_url Rails helper.
#
def create_resources_url_helpers!
resource_segments, resource_ivars = [], []
resource_config = self.resources_configuration[:self]
singleton = resource_config[:singleton]
uncountable = !singleton && resource_config[:route_collection_name] == resource_config[:route_instance_name]
polymorphic = self.parents_symbols.include?(:polymorphic)
# Add route_prefix if any.
unless resource_config[:route_prefix].blank?
if polymorphic
resource_ivars << resource_config[:route_prefix].to_s.inspect
else
resource_segments << resource_config[:route_prefix]
end
end
# Deal with belongs_to associations and polymorphic associations.
# Remember that we don't have to build the segments in polymorphic cases,
# because the url will be polymorphic_url.
#
self.parents_symbols.each do |symbol|
if symbol == :polymorphic
resource_ivars << :parent
else
config = self.resources_configuration[symbol]
if config[:singleton] && polymorphic
resource_ivars << config[:instance_name].inspect
else
resource_segments << config[:route_name]
end
if !config[:singleton]
resource_ivars << :"@#{config[:instance_name]}"
end
end
end
collection_ivars = resource_ivars.dup
collection_segments = resource_segments.dup
# Generate parent url before we add resource instances.
unless parents_symbols.empty?
generate_url_and_path_helpers nil, :parent, resource_segments, resource_ivars
generate_url_and_path_helpers :edit, :parent, resource_segments, resource_ivars
end
# This is the default route configuration, later we have to deal with
# exception from polymorphic and singleton cases.
#
collection_segments << resource_config[:route_collection_name]
resource_segments << resource_config[:route_instance_name]
resource_ivars << :"@#{resource_config[:instance_name]}"
# In singleton cases, we do not send the current element instance variable
# because the id is not in the URL. For example, we should call:
#
# project_manager_url(@project)
#
# Instead of:
#
# project_manager_url(@project, @manager)
#
# Another exception in singleton cases is that collection url does not
# exist. In such cases, we create the parent collection url. So in the
# manager case above, the collection url will be:
#
# project_url(@project)
#
# If the singleton does not have a parent, it will default to root_url.
#
# Finally, polymorphic cases we have to give hints to the polymorphic url
# builder. This works by attaching new ivars as symbols or records.
#
if singleton
collection_segments.pop
resource_ivars.pop
if polymorphic
resource_ivars << resource_config[:instance_name].inspect
new_ivars = resource_ivars
end
elsif polymorphic
collection_ivars << '(@_resource_class_new ||= resource_class.new)'
end
# If route is uncountable then add "_index" suffix to collection index route name
if uncountable
collection_segments << :"#{collection_segments.pop}_index"
end
generate_url_and_path_helpers nil, :collection, collection_segments, collection_ivars
generate_url_and_path_helpers :new, :resource, resource_segments, new_ivars || collection_ivars
generate_url_and_path_helpers nil, :resource, resource_segments, resource_ivars
generate_url_and_path_helpers :edit, :resource, resource_segments, resource_ivars
if resource_config[:custom_actions]
[*resource_config[:custom_actions][:resource]].each do | method |
generate_url_and_path_helpers method, :resource, resource_segments, resource_ivars
end
[*resource_config[:custom_actions][:collection]].each do | method |
generate_url_and_path_helpers method, :resources, collection_segments, collection_ivars
end
end
end
def handle_shallow_resource(prefix, name, segments, ivars) #:nodoc:
return segments, ivars unless self.resources_configuration[:self][:shallow]
case name
when :collection, :resources
segments = segments[-2..-1]
ivars = [ivars.last]
when :resource
if prefix == :new
segments = segments[-2..-1]
ivars = [ivars.last]
else
segments = [segments.last]
ivars = [ivars.last]
end
when :parent
segments = [segments.last]
ivars = [ivars.last]
end
segments ||= []
unless self.resources_configuration[:self][:route_prefix].blank?
segments.unshift self.resources_configuration[:self][:route_prefix]
end
return segments, ivars
end
def generate_url_and_path_helpers(prefix, name, resource_segments, resource_ivars) #:nodoc:
resource_segments, resource_ivars = handle_shallow_resource(prefix, name, resource_segments, resource_ivars)
ivars = resource_ivars.dup
singleton = self.resources_configuration[:self][:singleton]
polymorphic = self.parents_symbols.include?(:polymorphic)
# If it's not a singleton, ivars are not empty, not a collection or
# not a "new" named route, we can pass a resource as argument.
#
unless (singleton && name != :parent) || ivars.empty? || name == :collection || prefix == :new
ivars.push "(given_args.first || #{ivars.pop})"
end
# In collection in polymorphic cases, allow an argument to be given as a
# replacemente for the parent.
#
if name == :collection && polymorphic
index = ivars.index(:parent)
ivars.insert index, "(given_args.first || parent)"
ivars.delete(:parent)
end
# When polymorphic is true, the segments must be replace by :polymorphic
# and ivars should be gathered into an array, which is compacted when
# optional.
#
if polymorphic
segments = :polymorphic
ivars = "[#{ivars.join(', ')}]"
ivars << '.compact' if self.resources_configuration[:polymorphic][:optional]
else
segments = resource_segments.empty? ? 'root' : resource_segments.join('_')
ivars = ivars.join(', ')
end
prefix = prefix ? "#{prefix}_" : ''
ivars << (ivars.empty? ? 'given_options' : ', given_options')
given_args_transform = 'given_args = given_args.collect { |arg| arg.respond_to?(:permitted?) ? arg.to_h : arg }'
class_eval <<-URL_HELPERS, __FILE__, __LINE__
protected
undef :#{prefix}#{name}_path if method_defined? :#{prefix}#{name}_path
def #{prefix}#{name}_path(*given_args)
#{given_args_transform}
given_options = given_args.extract_options!
#{prefix}#{segments}_path(#{ivars})
end
undef :#{prefix}#{name}_url if method_defined? :#{prefix}#{name}_url
def #{prefix}#{name}_url(*given_args)
#{given_args_transform}
given_options = given_args.extract_options!
#{prefix}#{segments}_url(#{ivars})
end
URL_HELPERS
end
end
end
inherited-resources-1.9.0/MIT-LICENSE 0000644 0001750 0001750 00000002044 13470613050 017675 0 ustar utkarsh2102 utkarsh2102 Copyright (c) 2009-2017 José Valim
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
inherited-resources-1.9.0/app/ 0000755 0001750 0001750 00000000000 13470613050 017021 5 ustar utkarsh2102 utkarsh2102 inherited-resources-1.9.0/app/controllers/ 0000755 0001750 0001750 00000000000 13470613050 021367 5 ustar utkarsh2102 utkarsh2102 inherited-resources-1.9.0/app/controllers/inherited_resources/ 0000755 0001750 0001750 00000000000 13470613050 025434 5 ustar utkarsh2102 utkarsh2102 inherited-resources-1.9.0/app/controllers/inherited_resources/base.rb 0000644 0001750 0001750 00000003503 13470613050 026674 0 ustar utkarsh2102 utkarsh2102 module InheritedResources
# = Base
#
# This is the base class that holds all actions. If you see the code for each
# action, they are quite similar to Rails default scaffold.
#
# To change your base behavior, you can overwrite your actions and call super,
# call default class method, call <actions class method
# or overwrite some helpers in the base_helpers.rb file.
#
class Base < ::ApplicationController
# Overwrite inherit_resources to add specific InheritedResources behavior.
def self.inherit_resources(base)
base.class_eval do
include InheritedResources::Actions
include InheritedResources::BaseHelpers
extend InheritedResources::ClassMethods
extend InheritedResources::UrlHelpers
# Add at least :html mime type
respond_to :html if self.mimes_for_respond_to.empty?
self.responder = InheritedResources::Responder
helper_method :resource, :collection, :resource_class, :association_chain,
:resource_instance_name, :resource_collection_name,
:resource_url, :resource_path,
:collection_url, :collection_path,
:new_resource_url, :new_resource_path,
:edit_resource_url, :edit_resource_path,
:parent_url, :parent_path,
:smart_resource_url, :smart_collection_url
self.class_attribute :resource_class, :instance_writer => false unless self.respond_to? :resource_class
self.class_attribute :parents_symbols, :resources_configuration, :instance_writer => false
protected :resource_class, :parents_symbols, :resources_configuration,
:resource_class?, :parents_symbols?, :resources_configuration?
end
end
inherit_resources(self)
end
end inherited-resources-1.9.0/README.md 0000644 0001750 0001750 00000050735 13470613050 017532 0 ustar utkarsh2102 utkarsh2102 ## Notice
Inherited Resources is no longer actively maintained by the original author and
has been transferred to the ActiveAdmin organization for maintenance. New feature
requests are not encouraged.
If you are not already using Inherited Resources we suggest instead using Rails'
`respond_with` feature alongside the [responders gem](https://github.com/plataformatec/responders).
## Inherited Resources
[](https://rubygems.org/gems/inherited_resources)
[](https://travis-ci.org/activeadmin/inherited_resources)
Inherited Resources speeds up development by making your controllers inherit
all restful actions so you just have to focus on what is important. It makes
your controllers more powerful and cleaner at the same time.
In addition to making your controllers follow a pattern, it helps you to write better
code by following fat models and skinny controllers convention. There are
two screencasts available besides this README:
* http://railscasts.com/episodes/230-inherited-resources
* http://akitaonrails.com/2009/09/01/screencast-real-thin-restful-controllers-with-inherited-resources
## Installation
You can let bundler install Inherited Resources by adding this line to your application's Gemfile:
```ruby
gem 'inherited_resources'
```
And then execute:
```sh
$ bundle install
```
Or install it yourself with:
```sh
$ gem install inherited_resources
```
## HasScope
Since Inherited Resources 1.0, has_scope is not part of its core anymore but
a gem dependency. Be sure to check the documentation to see how you can use it:
-
And it can be installed as:
```sh
$ gem install has_scope
```
## Responders
Since Inherited Resources 1.0, responders are not part of its core anymore,
but is set as Inherited Resources dependency and it's used by default by
InheritedResources controllers. Be sure to check the documentation to see
how it will change your application:
-
And it can be installed with:
```sh
$ gem install responders
```
Using responders will set the flash message to :notice and :alert. You can change
that through the following configuration value:
```ruby
InheritedResources.flash_keys = [ :success, :failure ]
```
Notice the CollectionResponder won't work with InheritedResources, as
InheritedResources hardcodes the redirect path based on the current scope (like
belongs to, polymorphic associations, etc).
## Basic Usage
To use Inherited Resources you just have to inherit (duh) it:
```ruby
class ProjectsController < InheritedResources::Base
end
```
And all actions are defined and working, check it! Your projects collection
(in the index action) is still available in the instance variable `@projects`
and your project resource (all other actions) is available as `@project`.
The next step is to define which mime types this controller provides:
```ruby
class ProjectsController < InheritedResources::Base
respond_to :html, :xml, :json
end
```
You can also specify them per action:
```ruby
class ProjectsController < InheritedResources::Base
respond_to :html, :xml, :json
respond_to :js, :only => :create
respond_to :iphone, :except => [ :edit, :update ]
end
```
For each request, it first checks if the "controller/action.format" file is
available (for example "projects/create.xml") and if it's not, it checks if
the resource respond to :to_format (in this case, `:to_xml`). Otherwise returns 404.
Another option is to specify which actions the controller will inherit from
the `InheritedResources::Base`:
```ruby
class ProjectsController < InheritedResources::Base
actions :index, :show, :new, :create
end
```
Or:
```ruby
class ProjectsController < InheritedResources::Base
actions :all, :except => [ :edit, :update, :destroy ]
end
```
In your views, you will get the following helpers:
```ruby
resource #=> @project
collection #=> @projects
resource_class #=> Project
```
As you might expect, collection (`@projects` instance variable) is only available
on index actions.
If for some reason you cannot inherit from `InheritedResources::Base`, you can
call inherit_resources in your controller class scope:
```ruby
class AccountsController < ApplicationController
inherit_resources
end
```
One reason to use the `inherit_resources` macro would be to ensure that your controller
never responds with the html mime-type. `InheritedResources::Base` already
responds to `:html`, and the `respond_to` macro is strictly additive.
Therefore, if you want to create a controller that, for example, responds ONLY via `:js`,
you will have to write it this way:
```ruby
class AccountsController < ApplicationController
respond_to :js
inherit_resources
end
```
## Overwriting defaults
Whenever you inherit from InheritedResources, several defaults are assumed.
For example you can have an `AccountsController` for account management while the
resource is a `User`:
```ruby
class AccountsController < InheritedResources::Base
defaults :resource_class => User, :collection_name => 'users', :instance_name => 'user'
end
```
In the case above, in your views you will have `@users` and `@user` variables, but
the routes used will still be `accounts_url` and `account_url`. If you plan also to
change the routes, you can use `:route_collection_name` and `:route_instance_name`.
Namespaced controllers work out of the box, but if you need to specify a
different route prefix you can do the following:
```ruby
class Administrators::PeopleController < InheritedResources::Base
defaults :route_prefix => 'admin'
end
```
Then your named routes will be: `admin_people_url`, `admin_person_url` instead
of `administrators_people_url` and `administrators_person_url`.
If you want to customize how resources are retrieved you can overwrite
collection and resource methods. The first is called on index action and the
second on all other actions. Let's suppose you want to add pagination to your
projects collection:
```ruby
class ProjectsController < InheritedResources::Base
protected
def collection
get_collection_ivar || set_collection_ivar(end_of_association_chain.paginate(:page => params[:page]))
end
end
```
The `end_of_association_chain` returns your resource after nesting all associations
and scopes (more about this below).
InheritedResources also introduces another method called `begin_of_association_chain`.
It's mostly used when you want to create resources based on the `@current_user` and
you have urls like "account/projects". In such cases you have to do
`@current_user.projects.find` or `@current_user.projects.build` in your actions.
You can deal with it just by doing:
```ruby
class ProjectsController < InheritedResources::Base
protected
def begin_of_association_chain
@current_user
end
end
```
## Overwriting actions
Let's suppose that after destroying a project you want to redirect to your
root url instead of redirecting to projects url. You just have to do:
```ruby
class ProjectsController < InheritedResources::Base
def destroy
super do |format|
format.html { redirect_to root_url }
end
end
end
```
You are opening your action and giving the parent action a new behavior. On
the other hand, I have to agree that calling super is not very readable. That's
why all methods have aliases. So this is equivalent:
```ruby
class ProjectsController < InheritedResources::Base
def destroy
destroy! do |format|
format.html { redirect_to root_url }
end
end
end
```
Since most of the time when you change a create, update or destroy
action you do so because you want to change its redirect url, a shortcut is
provided. So you can do:
```ruby
class ProjectsController < InheritedResources::Base
def destroy
destroy! { root_url }
end
end
```
If you simply want to change the flash message for a particular action, you can
pass the message to the parent action using the keys `:notice` and `:alert` (as you
would with flash):
```ruby
class ProjectsController < InheritedResources::Base
def create
create!(:notice => "Dude! Nice job creating that project.")
end
end
```
You can still pass the block to change the redirect, as mentioned above:
```ruby
class ProjectsController < InheritedResources::Base
def create
create!(:notice => "Dude! Nice job creating that project.") { root_url }
end
end
```
Now let's suppose that before create a project you have to do something special
but you don't want to create a before filter for it:
```ruby
class ProjectsController < InheritedResources::Base
def create
@project = Project.new(params[:project])
@project.something_special!
create!
end
end
```
Yes, it's that simple! The nice part is since you already set the instance variable
`@project`, it will not build a project again.
Same goes for updating the project:
```ruby
class ProjectsController < InheritedResources::Base
def update
@project = Project.find(params[:id])
@project.something_special!
update!
end
end
```
Before we finish this topic, we should talk about one more thing: "success/failure
blocks". Let's suppose that when we update our project, in case of failure, we
want to redirect to the project url instead of re-rendering the edit template.
Our first attempt to do this would be:
```ruby
class ProjectsController < InheritedResources::Base
def update
update! do |format|
unless @project.errors.empty? # failure
format.html { redirect_to project_url(@project) }
end
end
end
end
```
Looks too verbose, right? We can actually do:
```ruby
class ProjectsController < InheritedResources::Base
def update
update! do |success, failure|
failure.html { redirect_to project_url(@project) }
end
end
end
```
Much better! So explaining everything: when you give a block which expects one
argument it will be executed in both scenarios: success and failure. But if you
give a block that expects two arguments, the first will be executed only in
success scenarios and the second in failure scenarios. You keep everything
clean and organized inside the same action.
## Smart redirects
Although the syntax above is a nice shortcut, you won't need to do it frequently
because (since version 1.2) Inherited Resources has smart redirects. Redirects
in actions calculates depending on the existent controller methods.
Redirects in create and update actions calculates in the following order: `resource_url`,
`collection_url`, `parent_url` (which we are going to see later), and `root_url`. Redirect
in destroy action calculate in following order `collection_url`, `parent_url`, `root_url`.
Example:
```ruby
class ButtonsController < InheritedResources::Base
belongs_to :window
actions :all, :except => [:show, :index]
end
```
This controller redirect to parent window after all CUD actions.
## Success and failure scenarios on destroy
The destroy action can also fail, this usually happens when you have a
`before_destroy` callback in your model which returns false. However, in
order to tell InheritedResources that it really failed, you need to add
errors to your model. So your `before_destroy` callback on the model should
be something like this:
```ruby
def before_destroy
if cant_be_destroyed?
errors.add(:base, "not allowed")
false
end
end
```
## Belongs to
Finally, our Projects are going to get some Tasks. Then you create a
`TasksController` and do:
```ruby
class TasksController < InheritedResources::Base
belongs_to :project
end
```
`belongs_to` accepts several options to be able to configure the association.
For example, if you want urls like "/projects/:project_title/tasks", you can
customize how InheritedResources find your projects:
```ruby
class TasksController < InheritedResources::Base
belongs_to :project, :finder => :find_by_title!, :param => :project_title
end
```
It also accepts `:route_name`, `:parent_class` and `:instance_name` as options.
Check the [lib/inherited_resources/class_methods.rb](https://github.com/activeadmin/inherited_resources/blob/master/lib/inherited_resources/class_methods.rb)
for more.
## Nested belongs to
Now, our Tasks get some Comments and you need to nest even deeper. Good
practices says that you should never nest more than two resources, but sometimes
you have to for security reasons. So this is an example of how you can do it:
```ruby
class CommentsController < InheritedResources::Base
nested_belongs_to :project, :task
end
```
If you need to configure any of these belongs to, you can nest them using blocks:
```ruby
class CommentsController < InheritedResources::Base
belongs_to :project, :finder => :find_by_title!, :param => :project_title do
belongs_to :task
end
end
```
Warning: calling several `belongs_to` is the same as nesting them:
```ruby
class CommentsController < InheritedResources::Base
belongs_to :project
belongs_to :task
end
```
In other words, the code above is the same as calling `nested_belongs_to`.
## Polymorphic belongs to
We can go even further. Let's suppose our Projects can now have Files, Messages
and Tasks, and they are all commentable. In this case, the best solution is to
use polymorphism:
```ruby
class CommentsController < InheritedResources::Base
belongs_to :task, :file, :message, :polymorphic => true
# polymorphic_belongs_to :task, :file, :message
end
```
You can even use it with nested resources:
```ruby
class CommentsController < InheritedResources::Base
belongs_to :project do
belongs_to :task, :file, :message, :polymorphic => true
end
end
```
The url in such cases can be:
```
/project/1/task/13/comments
/project/1/file/11/comments
/project/1/message/9/comments
```
When using polymorphic associations, you get some free helpers:
```ruby
parent? #=> true
parent_type #=> :task
parent_class #=> Task
parent #=> @task
```
Right now, Inherited Resources is limited and does not allow you
to have two polymorphic associations nested.
## Optional belongs to
Later you decide to create a view to show all comments, independent if they belong
to a task, file or message. You can reuse your polymorphic controller just doing:
```ruby
class CommentsController < InheritedResources::Base
belongs_to :task, :file, :message, :optional => true
# optional_belongs_to :task, :file, :message
end
```
This will handle all those urls properly:
```
/comment/1
/tasks/2/comment/5
/files/10/comment/3
/messages/13/comment/11
```
This is treated as a special type of polymorphic associations, thus all helpers
are available. As you expect, when no parent is found, the helpers return:
```ruby
parent? #=> false
parent_type #=> nil
parent_class #=> nil
parent #=> nil
```
## Singletons
Now we are going to add manager to projects. We say that `Manager` is a singleton
resource because a `Project` has just one manager. You should declare it as
`has_one` (or resource) in your routes.
To declare an resource of current controller as singleton, you just have to give the
`:singleton` option in defaults.
```ruby
class ManagersController < InheritedResources::Base
defaults :singleton => true
belongs_to :project
# singleton_belongs_to :project
end
```
So now you can use urls like "/projects/1/manager".
In the case of nested resources (when some of the can be singletons) you can declare it separately
```ruby
class WorkersController < InheritedResources::Base
#defaults :singleton => true #if you have only single worker
belongs_to :project
belongs_to :manager, :singleton => true
end
```
This is correspond urls like "/projects/1/manager/workers/1".
It will deal with everything again and hide the action :index from you.
## Namespaced Controllers
Namespaced controllers works out the box.
```ruby
class Forum::PostsController < InheritedResources::Base
end
```
Inherited Resources prioritizes the default resource class for the namespaced controller in
this order:
```
Forum::Post
ForumPost
Post
```
## URL Helpers
When you use InheritedResources it creates some URL helpers.
And they handle everything for you. :)
```ruby
# /posts/1/comments
resource_url # => /posts/1/comments/#{@comment.to_param}
resource_url(comment) # => /posts/1/comments/#{comment.to_param}
new_resource_url # => /posts/1/comments/new
edit_resource_url # => /posts/1/comments/#{@comment.to_param}/edit
edit_resource_url(comment) # => /posts/1/comments/#{comment.to_param}/edit
collection_url # => /posts/1/comments
parent_url # => /posts/1
# /projects/1/tasks
resource_url # => /projects/1/tasks/#{@task.to_param}
resource_url(task) # => /projects/1/tasks/#{task.to_param}
new_resource_url # => /projects/1/tasks/new
edit_resource_url # => /projects/1/tasks/#{@task.to_param}/edit
edit_resource_url(task) # => /projects/1/tasks/#{task.to_param}/edit
collection_url # => /projects/1/tasks
parent_url # => /projects/1
# /users
resource_url # => /users/#{@user.to_param}
resource_url(user) # => /users/#{user.to_param}
new_resource_url # => /users/new
edit_resource_url # => /users/#{@user.to_param}/edit
edit_resource_url(user) # => /users/#{user.to_param}/edit
collection_url # => /users
parent_url # => /
```
Those urls helpers also accepts a hash as options, just as in named routes.
```ruby
# /projects/1/tasks
collection_url(:page => 1, :limit => 10) #=> /projects/1/tasks?page=1&limit=10
```
In polymorphic cases, you can also give the parent as parameter to `collection_url`.
Another nice thing is that those urls are not guessed during runtime. They are
all created when your application is loaded (except for polymorphic
associations, that relies on Rails' `polymorphic_url`).
## Custom actions
Since version 1.2, Inherited Resources allows you to define custom actions in controller:
```ruby
class ButtonsController < InheritedResources::Base
custom_actions :resource => :delete, :collection => :search
end
```
This code creates delete and search actions in controller (they behaves like show and
index actions accordingly). Also, it will produce `delete_resource_{path,url}` and
`search_resources_{path,url}` url helpers.
## What about views?
Sometimes just DRYing up the controllers is not enough. If you need to DRY up your views,
check this Wiki page:
https://github.com/activeadmin/inherited_resources/wiki/Views-Inheritance
Notice that Rails 3.1 ships with view inheritance built-in.
## Some DSL
For those DSL lovers, InheritedResources won't leave you alone. You can overwrite
your success/failure blocks straight from your class binding. For it, you just
need to add a DSL module to your application controller:
```ruby
class ApplicationController < ActionController::Base
include InheritedResources::DSL
end
```
And then you can rewrite the last example as:
```ruby
class ProjectsController < InheritedResources::Base
update! do |success, failure|
failure.html { redirect_to project_url(@project) }
end
end
```
## Strong Parameters
If your controller defines a method named `permitted_params`, InheritedResources
will call it where it would normally call params. This allows for easy
integration with the strong_parameters gem:
```ruby
def permitted_params
params.permit(:widget => [:permitted_field, :other_permitted_field])
end
```
Remember that if your field is sent by client to server as an array, you have to write `:permitted_field => []`, not just `:permitted_field`.
Note that this doesn't work if you use strong_parameters' require method
instead of permit, because whereas permit returns the entire sanitized
parameter hash, require returns only the sanitized params below the parameter
you required.
If you need `params.require` you can do it like this:
```ruby
def permitted_params
{:widget => params.fetch(:widget, {}).permit(:permitted_field, :other_permitted_field)}
end
```
Or better yet just override `#build_resource_params` directly:
```ruby
def build_resource_params
[params.fetch(:widget, {}).permit(:permitted_field, :other_permitted_field)]
end
```
Instead you can stick to a standard Rails 4 notation (as rails scaffold generates) and write:
```ruby
def widget_params
params.require(:widget).permit(:permitted_field, :other_permitted_field)
end
```
In such case you should remove #permitted_params method because it has greater priority.
## Bugs and Feedback
If you discover any bugs, please describe it in the issues tracker, including Rails and InheritedResources versions.
Questions are better handled on StackOverflow.
MIT License. Copyright (c) 2009-2017 José Valim.
inherited-resources-1.9.0/inherited_resources.gemspec 0000644 0001750 0001750 00000006031 13470613050 023653 0 ustar utkarsh2102 utkarsh2102 #########################################################
# This file has been automatically generated by gem2tgz #
#########################################################
# -*- encoding: utf-8 -*-
# stub: inherited_resources 1.9.0 ruby lib
Gem::Specification.new do |s|
s.name = "inherited_resources".freeze
s.version = "1.9.0"
s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
s.require_paths = ["lib".freeze]
s.authors = ["Jos\u00E9 Valim".freeze, "Rafael Mendon\u00E7a Fran\u00E7a".freeze]
s.date = "2018-08-10"
s.description = "Inherited Resources speeds up development by making your controllers inherit all restful actions so you just have to focus on what is important.".freeze
s.files = ["MIT-LICENSE".freeze, "README.md".freeze, "app/controllers/inherited_resources/base.rb".freeze, "lib/generators/rails/USAGE".freeze, "lib/generators/rails/inherited_resources_controller_generator.rb".freeze, "lib/generators/rails/templates/controller.rb".freeze, "lib/inherited_resources.rb".freeze, "lib/inherited_resources/actions.rb".freeze, "lib/inherited_resources/base_helpers.rb".freeze, "lib/inherited_resources/belongs_to_helpers.rb".freeze, "lib/inherited_resources/blank_slate.rb".freeze, "lib/inherited_resources/class_methods.rb".freeze, "lib/inherited_resources/dsl.rb".freeze, "lib/inherited_resources/engine.rb".freeze, "lib/inherited_resources/polymorphic_helpers.rb".freeze, "lib/inherited_resources/responder.rb".freeze, "lib/inherited_resources/shallow_helpers.rb".freeze, "lib/inherited_resources/singleton_helpers.rb".freeze, "lib/inherited_resources/url_helpers.rb".freeze, "lib/inherited_resources/version.rb".freeze]
s.homepage = "http://github.com/activeadmin/inherited_resources".freeze
s.licenses = ["MIT".freeze]
s.required_ruby_version = Gem::Requirement.new(">= 2.3".freeze)
s.rubyforge_project = "inherited_resources".freeze
s.rubygems_version = "2.7.6.2".freeze
s.summary = "Inherited Resources speeds up development by making your controllers inherit all restful actions so you just have to focus on what is important.".freeze
if s.respond_to? :specification_version then
s.specification_version = 4
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
s.add_runtime_dependency(%q.freeze, ["< 5.3", ">= 4.2"])
s.add_runtime_dependency(%q.freeze, ["~> 0.6"])
s.add_runtime_dependency(%q.freeze, ["< 5.3", ">= 4.2"])
s.add_runtime_dependency(%q.freeze, [">= 0"])
else
s.add_dependency(%q.freeze, ["< 5.3", ">= 4.2"])
s.add_dependency(%q.freeze, ["~> 0.6"])
s.add_dependency(%q.freeze, ["< 5.3", ">= 4.2"])
s.add_dependency(%q.freeze, [">= 0"])
end
else
s.add_dependency(%q.freeze, ["< 5.3", ">= 4.2"])
s.add_dependency(%q.freeze, ["~> 0.6"])
s.add_dependency(%q.freeze, ["< 5.3", ">= 4.2"])
s.add_dependency(%q.freeze, [">= 0"])
end
end