benhoskings-hammock 0.2.5 → 0.2.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +29 -0
- data/Manifest.txt +3 -0
- data/hammock.gemspec +3 -4
- data/lib/hammock.rb +2 -2
- data/lib/hammock/ajaxinate.rb +1 -1
- data/lib/hammock/callback.rb +16 -0
- data/lib/hammock/callbacks.rb +1 -14
- data/lib/hammock/canned_scopes.rb +5 -1
- data/lib/hammock/constants.rb +2 -0
- data/lib/hammock/controller_attributes.rb +0 -13
- data/lib/hammock/model_attributes.rb +21 -6
- data/lib/hammock/monkey_patches/active_record.rb +10 -6
- data/lib/hammock/monkey_patches/hash.rb +8 -0
- data/lib/hammock/monkey_patches/route_set.rb +1 -173
- data/lib/hammock/resource_retrieval.rb +4 -4
- data/lib/hammock/restful_actions.rb +1 -1
- data/lib/hammock/restful_support.rb +37 -33
- data/lib/hammock/route_for.rb +1 -1
- data/lib/hammock/route_node.rb +159 -0
- data/lib/hammock/route_step.rb +87 -0
- data/lib/hammock/scope.rb +14 -7
- metadata +7 -5
data/History.txt
CHANGED
@@ -1,3 +1,32 @@
|
|
1
|
+
== 0.2.6 2009-03-05
|
2
|
+
|
3
|
+
Access current_nested_records in nested_route_for through the method instead of directly.
|
4
|
+
Replaced #assign_nestable_resources with #assign_nesting_entities, to separately kick and assign an ivar for each of the current rou
|
5
|
+
Added nesting_scope_list to encapsulate what @hammock_nesting_scopes was set to before.
|
6
|
+
Updated nested_within? to use methods instead of ivars, removed duping from current_nested_[record,resource]s, and added add_nested_en
|
7
|
+
Updated empty_scope for sqlite, to bring it in line with public_scope.
|
8
|
+
Updated current_scope to fail gracefully if current_verb_scope (renamed from verb_scope along with [current_]nest_scope) returns nil.
|
9
|
+
Replaced RouteNode#nesting_scope_for with nesting_scope_list_for, and changed nest_scope call appropriately. The scopes are returned s
|
10
|
+
Replaced AR::Base#id_or_description with #description, added .description, and use in link_class_for for more consistent class names.
|
11
|
+
Split Hammock::Callback (previously HammockCallback) out into its own file.
|
12
|
+
Split RouteNode and RouteStep (previously HammockResource and HammockRoutePiece) out into their own files.
|
13
|
+
Reject Hammock:: classes from hammock load. Classes are modules. Who knew?
|
14
|
+
Changed inheritable_attribute keys from strings to symbols.
|
15
|
+
Caching the model within HammockResource was causing stale class fails in development mode.
|
16
|
+
retrieve_record uses mdl.routing_attribute now instead of the old find_column_name.
|
17
|
+
Default routing_attribute to :id.
|
18
|
+
Fixed the 'no valid AR reflections' message to be a user error instead of an internal hammock error (they just need to add a reflection)
|
19
|
+
HammockRoutePiece erroneously had a root? check instead of a parent.nil? check - fixed.
|
20
|
+
Only set creator_id if someone is logged in.
|
21
|
+
Updated #nest_scope to use #nesting_scope_for instead of manually recursively selecting within a single context, and updated #curren
|
22
|
+
Re-enabled logging of Ambition queries as they are assigned as entities.
|
23
|
+
Replaced the questionable #current_route with #current_hammock_resource, which uses HammockResource#base_for.
|
24
|
+
Added HammockResource#base_for, #nesting_scope_for and #nesting_scope_segment_for.
|
25
|
+
Added HammockResource#determine_routing_parent, to determine which ActiveRecord reflection to use to generate joins for route queryi
|
26
|
+
Added Hash#selekt, to sidestep the ruby-1.8/1.9 #select changes.
|
27
|
+
Commented current_route-dependent code in hamlink_to until that is sorted out.
|
28
|
+
Test if obj is defined before attempting to select .spinner within it.
|
29
|
+
|
1
30
|
== 0.2.4 2009-02-25
|
2
31
|
|
3
32
|
* Initial gem release
|
data/Manifest.txt
CHANGED
@@ -6,6 +6,7 @@ Rakefile
|
|
6
6
|
hammock.gemspec
|
7
7
|
lib/hammock.rb
|
8
8
|
lib/hammock/ajaxinate.rb
|
9
|
+
lib/hammock/callback.rb
|
9
10
|
lib/hammock/callbacks.rb
|
10
11
|
lib/hammock/canned_scopes.rb
|
11
12
|
lib/hammock/constants.rb
|
@@ -34,6 +35,8 @@ lib/hammock/restful_rendering.rb
|
|
34
35
|
lib/hammock/restful_support.rb
|
35
36
|
lib/hammock/route_drawing_hooks.rb
|
36
37
|
lib/hammock/route_for.rb
|
38
|
+
lib/hammock/route_node.rb
|
39
|
+
lib/hammock/route_step.rb
|
37
40
|
lib/hammock/scope.rb
|
38
41
|
lib/hammock/suggest.rb
|
39
42
|
lib/hammock/utils.rb
|
data/hammock.gemspec
CHANGED
@@ -2,15 +2,15 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{hammock}
|
5
|
-
s.version = "0.2.
|
5
|
+
s.version = "0.2.6"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Ben Hoskings"]
|
9
|
-
s.date = %q{2009-
|
9
|
+
s.date = %q{2009-03-05}
|
10
10
|
s.description = %q{Hammock is a Rails plugin that eliminates redundant code in a very RESTful manner. It does this in lots in lots of different places, but in one manner: it encourages specification in place of implementation. Hammock enforces RESTful resource access by abstracting actions away from the controller in favour of a clean, model-like callback system. Hammock tackles the hard and soft sides of security at once with a scoping security system on your models. Specify who can verb what resources under what conditions once, and everything else - the actual security, link generation, index filtering - just happens. Hammock inspects your routes and resources to generate a routing tree for each resource. Parent resources in a nested route are handled transparently at every point - record retrieval, creation, and linking. It makes more sense when you see how it works though, so check out the screencast!}
|
11
11
|
s.email = ["ben@hoskings.net"]
|
12
12
|
s.extra_rdoc_files = ["History.txt", "Manifest.txt", "README.rdoc", "misc/scaffold.txt"]
|
13
|
-
s.files = ["History.txt", "LICENSE", "Manifest.txt", "README.rdoc", "Rakefile", "hammock.gemspec", "lib/hammock.rb", "lib/hammock/ajaxinate.rb", "lib/hammock/callbacks.rb", "lib/hammock/canned_scopes.rb", "lib/hammock/constants.rb", "lib/hammock/controller_attributes.rb", "lib/hammock/export_scope.rb", "lib/hammock/hamlink_to.rb", "lib/hammock/javascript_buffer.rb", "lib/hammock/logging.rb", "lib/hammock/model_attributes.rb", "lib/hammock/model_logging.rb", "lib/hammock/monkey_patches/action_pack.rb", "lib/hammock/monkey_patches/active_record.rb", "lib/hammock/monkey_patches/array.rb", "lib/hammock/monkey_patches/hash.rb", "lib/hammock/monkey_patches/logger.rb", "lib/hammock/monkey_patches/module.rb", "lib/hammock/monkey_patches/numeric.rb", "lib/hammock/monkey_patches/object.rb", "lib/hammock/monkey_patches/route_set.rb", "lib/hammock/monkey_patches/string.rb", "lib/hammock/overrides.rb", "lib/hammock/resource_mapping_hooks.rb", "lib/hammock/resource_retrieval.rb", "lib/hammock/restful_actions.rb", "lib/hammock/restful_rendering.rb", "lib/hammock/restful_support.rb", "lib/hammock/route_drawing_hooks.rb", "lib/hammock/route_for.rb", "lib/hammock/scope.rb", "lib/hammock/suggest.rb", "lib/hammock/utils.rb", "misc/scaffold.txt", "misc/template.rb", "tasks/hammock_tasks.rake", "test/hammock_test.rb"
|
13
|
+
s.files = ["History.txt", "LICENSE", "Manifest.txt", "README.rdoc", "Rakefile", "hammock.gemspec", "lib/hammock.rb", "lib/hammock/ajaxinate.rb", "lib/hammock/callback.rb", "lib/hammock/callbacks.rb", "lib/hammock/canned_scopes.rb", "lib/hammock/constants.rb", "lib/hammock/controller_attributes.rb", "lib/hammock/export_scope.rb", "lib/hammock/hamlink_to.rb", "lib/hammock/javascript_buffer.rb", "lib/hammock/logging.rb", "lib/hammock/model_attributes.rb", "lib/hammock/model_logging.rb", "lib/hammock/monkey_patches/action_pack.rb", "lib/hammock/monkey_patches/active_record.rb", "lib/hammock/monkey_patches/array.rb", "lib/hammock/monkey_patches/hash.rb", "lib/hammock/monkey_patches/logger.rb", "lib/hammock/monkey_patches/module.rb", "lib/hammock/monkey_patches/numeric.rb", "lib/hammock/monkey_patches/object.rb", "lib/hammock/monkey_patches/route_set.rb", "lib/hammock/monkey_patches/string.rb", "lib/hammock/overrides.rb", "lib/hammock/resource_mapping_hooks.rb", "lib/hammock/resource_retrieval.rb", "lib/hammock/restful_actions.rb", "lib/hammock/restful_rendering.rb", "lib/hammock/restful_support.rb", "lib/hammock/route_drawing_hooks.rb", "lib/hammock/route_for.rb", "lib/hammock/route_node.rb", "lib/hammock/route_step.rb", "lib/hammock/scope.rb", "lib/hammock/suggest.rb", "lib/hammock/utils.rb", "misc/scaffold.txt", "misc/template.rb", "tasks/hammock_tasks.rake", "test/hammock_test.rb"]
|
14
14
|
s.has_rdoc = true
|
15
15
|
s.homepage = %q{http://github.com/benhoskings/hammock}
|
16
16
|
s.rdoc_options = ["--main", "README.rdoc"]
|
@@ -18,7 +18,6 @@ Gem::Specification.new do |s|
|
|
18
18
|
s.rubyforge_project = %q{hammock}
|
19
19
|
s.rubygems_version = %q{1.3.1}
|
20
20
|
s.summary = %q{Hammock is a Rails plugin that eliminates redundant code in a very RESTful manner}
|
21
|
-
s.test_files = ["test/rails_root/test/test_helper.rb"]
|
22
21
|
|
23
22
|
if s.respond_to? :specification_version then
|
24
23
|
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
data/lib/hammock.rb
CHANGED
@@ -8,13 +8,13 @@ Dir.glob("#{File.dirname __FILE__}/hammock/**/*.rb").each {|dep|
|
|
8
8
|
} if defined?(RAILS_ROOT) # Loading Hammock components under 'rake package' fails.
|
9
9
|
|
10
10
|
module Hammock
|
11
|
-
VERSION = '0.2.
|
11
|
+
VERSION = '0.2.6'
|
12
12
|
|
13
13
|
def self.included base # :nodoc:
|
14
14
|
Hammock.constants.map {|constant_name|
|
15
15
|
Hammock.const_get constant_name
|
16
16
|
}.select {|constant|
|
17
|
-
constant.is_a?
|
17
|
+
constant.is_a?(Module) && !constant.is_a?(Class)
|
18
18
|
}.partition {|mod|
|
19
19
|
mod.constants.include?('LoadFirst') && mod::LoadFirst
|
20
20
|
}.flatten.each {|mod|
|
data/lib/hammock/ajaxinate.rb
CHANGED
@@ -133,7 +133,7 @@ module Hammock
|
|
133
133
|
private
|
134
134
|
|
135
135
|
def link_class_for verb, record, attribute = nil
|
136
|
-
[verb, record.
|
136
|
+
[verb, record.description, attribute].compact.join('_')
|
137
137
|
end
|
138
138
|
|
139
139
|
def clean_snippet snippet
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Hammock
|
2
|
+
|
3
|
+
class Callback < ActiveSupport::Callbacks::Callback
|
4
|
+
private
|
5
|
+
|
6
|
+
def evaluate_method method, *args, &block
|
7
|
+
if method.is_a? Proc
|
8
|
+
# puts "was a Hammock::Callback proc within #{args.first.class}."
|
9
|
+
method.bind(args.shift).call(*args, &block)
|
10
|
+
else
|
11
|
+
super
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
data/lib/hammock/callbacks.rb
CHANGED
@@ -28,19 +28,6 @@ module Hammock
|
|
28
28
|
|
29
29
|
module ClassMethods
|
30
30
|
|
31
|
-
class HammockCallback < ActiveSupport::Callbacks::Callback
|
32
|
-
private
|
33
|
-
|
34
|
-
def evaluate_method method, *args, &block
|
35
|
-
if method.is_a? Proc
|
36
|
-
# puts "was a HammockCallback proc within #{args.first.class}."
|
37
|
-
method.bind(args.shift).call(*args, &block)
|
38
|
-
else
|
39
|
-
super
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
31
|
def define_hammock_callbacks *callbacks
|
45
32
|
callbacks.each do |callback|
|
46
33
|
class_eval <<-"end_eval"
|
@@ -54,7 +41,7 @@ module Hammock
|
|
54
41
|
raise ArgumentError, "Inline callback definitions require a description as their sole argument."
|
55
42
|
else
|
56
43
|
# logger.info "defining \#{methods.first} on \#{name} with method \#{block.inspect}."
|
57
|
-
[
|
44
|
+
[Hammock::Callback.new(:#{callback}, block, :identifier => methods.first)]
|
58
45
|
end || []
|
59
46
|
end
|
60
47
|
# log callbacks
|
data/lib/hammock/constants.rb
CHANGED
@@ -31,15 +31,6 @@ module Hammock
|
|
31
31
|
def find_on_create
|
32
32
|
write_inheritable_attribute :find_on_create, true
|
33
33
|
end
|
34
|
-
|
35
|
-
# Use +find_column+ to specify the name of an alternate column with which record lookups should be performed.
|
36
|
-
#
|
37
|
-
# This is useful for controllers that are indexed by primary key, but are accessed with URLs containing some other unique attribute of the resource, like a randomly-generated key.
|
38
|
-
# find_column :key
|
39
|
-
def find_column column_name
|
40
|
-
# TODO define to_param on model.
|
41
|
-
write_inheritable_attribute :find_column, column_name
|
42
|
-
end
|
43
34
|
end
|
44
35
|
|
45
36
|
module InstanceMethods
|
@@ -57,10 +48,6 @@ module Hammock
|
|
57
48
|
def findable_on_create?
|
58
49
|
self.class.read_inheritable_attribute :find_on_create
|
59
50
|
end
|
60
|
-
|
61
|
-
def find_column_name
|
62
|
-
self.class.read_inheritable_attribute(:find_column) || :id
|
63
|
-
end
|
64
51
|
end
|
65
52
|
end
|
66
53
|
end
|
@@ -9,24 +9,39 @@ module Hammock
|
|
9
9
|
|
10
10
|
module ClassMethods
|
11
11
|
|
12
|
+
def route_by attribute
|
13
|
+
write_inheritable_attribute :routing_attribute, attribute.to_sym
|
14
|
+
define_method :to_param do
|
15
|
+
send self.class.routing_attribute
|
16
|
+
end
|
17
|
+
end
|
18
|
+
def nest_within *attributes
|
19
|
+
write_inheritable_attribute :nestable_routing_resources, attributes
|
20
|
+
end
|
12
21
|
def has_defaults attrs
|
13
|
-
write_inheritable_attribute
|
22
|
+
write_inheritable_attribute :default_attributes, (default_attributes || {}).merge(attrs)
|
14
23
|
end
|
15
24
|
def attr_accessible_on_create *attributes
|
16
|
-
write_inheritable_attribute
|
25
|
+
write_inheritable_attribute :attr_accessible_on_create, Set.new(attributes.map(&:to_s)) + (accessible_attributes_on_create || [])
|
17
26
|
end
|
18
27
|
def attr_accessible_on_update *attributes
|
19
|
-
write_inheritable_attribute
|
28
|
+
write_inheritable_attribute :attr_accessible_on_update, Set.new(attributes.map(&:to_s)) + (accessible_attributes_on_update || [])
|
20
29
|
end
|
21
30
|
|
31
|
+
def routing_attribute
|
32
|
+
read_inheritable_attribute(:routing_attribute) || :id
|
33
|
+
end
|
34
|
+
def nestable_routing_resources
|
35
|
+
read_inheritable_attribute(:nestable_routing_resources)
|
36
|
+
end
|
22
37
|
def default_attributes
|
23
|
-
read_inheritable_attribute(
|
38
|
+
read_inheritable_attribute(:default_attributes) || {}
|
24
39
|
end
|
25
40
|
def accessible_attributes_on_create
|
26
|
-
read_inheritable_attribute
|
41
|
+
read_inheritable_attribute :attr_accessible_on_create
|
27
42
|
end
|
28
43
|
def accessible_attributes_on_update
|
29
|
-
read_inheritable_attribute
|
44
|
+
read_inheritable_attribute :attr_accessible_on_update
|
30
45
|
end
|
31
46
|
|
32
47
|
end
|
@@ -39,10 +39,18 @@ module Hammock
|
|
39
39
|
base_class.to_s.pluralize.underscore
|
40
40
|
end
|
41
41
|
|
42
|
+
def param_key
|
43
|
+
"#{base_model}_id"
|
44
|
+
end
|
45
|
+
|
42
46
|
def base_model
|
43
47
|
base_class.to_s.underscore
|
44
48
|
end
|
45
49
|
|
50
|
+
def description
|
51
|
+
base_model
|
52
|
+
end
|
53
|
+
|
46
54
|
def record?; false end
|
47
55
|
def resource?; true end
|
48
56
|
|
@@ -122,12 +130,8 @@ module Hammock
|
|
122
130
|
end
|
123
131
|
end
|
124
132
|
|
125
|
-
def
|
126
|
-
new_record? ?
|
127
|
-
end
|
128
|
-
|
129
|
-
def new_record_description
|
130
|
-
attributes.map {|k,v| "#{k}-#{(v.to_s || '')[0..10]}" }.join("_")
|
133
|
+
def description
|
134
|
+
new_record? ? "new_#{base_model}" : "#{base_model}_#{id}"
|
131
135
|
end
|
132
136
|
|
133
137
|
def base_model
|
@@ -20,179 +20,7 @@ module Hammock
|
|
20
20
|
private
|
21
21
|
|
22
22
|
def initialize_hammock_route_map
|
23
|
-
self.route_map =
|
24
|
-
end
|
25
|
-
|
26
|
-
class HammockResource < ActionController::Resources::Resource
|
27
|
-
class HammockRoutePiece
|
28
|
-
attr_reader :resource, :routeable_as, :verb, :entity, :parent
|
29
|
-
|
30
|
-
def initialize resource
|
31
|
-
@resource = resource
|
32
|
-
end
|
33
|
-
|
34
|
-
def for verb, entity
|
35
|
-
routeable_as = resource.routeable_as(verb, entity)
|
36
|
-
|
37
|
-
if !routeable_as
|
38
|
-
raise "The verb '#{verb}' can't be applied to " + (entity.record? ? "#{entity.resource} records" : "the #{entity.resource} resource") + "."
|
39
|
-
elsif (:record == routeable_as) && entity.new_record?
|
40
|
-
raise "The verb '#{verb}' requires a #{entity.resource} with an ID (i.e. not a new record)."
|
41
|
-
elsif (:build == routeable_as) && entity.record? && !entity.new_record?
|
42
|
-
raise "The verb '#{verb}' requires either the #{entity.resource} resource, or a #{entity.resource} without an ID (i.e. a new record)."
|
43
|
-
else
|
44
|
-
@verb, @entity, @routeable_as = verb, entity, routeable_as
|
45
|
-
end
|
46
|
-
|
47
|
-
self
|
48
|
-
end
|
49
|
-
|
50
|
-
def within parent
|
51
|
-
@parent = parent
|
52
|
-
self
|
53
|
-
end
|
54
|
-
|
55
|
-
def setup?
|
56
|
-
!@entity.nil?
|
57
|
-
end
|
58
|
-
|
59
|
-
def path params = nil
|
60
|
-
raise_unless_setup_while_trying_to 'render a path'
|
61
|
-
|
62
|
-
buf = '/'
|
63
|
-
buf << entity.resource_name
|
64
|
-
buf << '/' + entity.to_param if entity.record? && !entity.new_record?
|
65
|
-
buf << '/' + verb.to_s unless verb.nil? or implied_verb?(verb)
|
66
|
-
|
67
|
-
buf = parent.path + buf unless parent.nil?
|
68
|
-
buf << param_str(params)
|
69
|
-
|
70
|
-
buf
|
71
|
-
end
|
72
|
-
|
73
|
-
def http_method
|
74
|
-
raise_unless_setup_while_trying_to 'extract the HTTP method'
|
75
|
-
resource.send("#{routeable_as}_routes")[verb]
|
76
|
-
end
|
77
|
-
|
78
|
-
def fake_http_method
|
79
|
-
http_method.in?(:get, :post) ? http_method : :post
|
80
|
-
end
|
81
|
-
|
82
|
-
def get?; :get == http_method end
|
83
|
-
def post?; :post == http_method end
|
84
|
-
def put?; :put == http_method end
|
85
|
-
def delete?; :delete == http_method end
|
86
|
-
|
87
|
-
def safe?
|
88
|
-
get? && !verb.in?(Hammock::Constants::ImpliedUnsafeActions)
|
89
|
-
end
|
90
|
-
|
91
|
-
private
|
92
|
-
|
93
|
-
def implied_verb? verb
|
94
|
-
verb.in? :index, :create, :show, :update, :destroy
|
95
|
-
end
|
96
|
-
|
97
|
-
def raise_unless_setup_while_trying_to task
|
98
|
-
raise "You have to call for(verb, entity) (and optionally within(parent)) on this HammockRoutePiece before you can #{task}." unless setup?
|
99
|
-
end
|
100
|
-
|
101
|
-
def param_str params
|
102
|
-
link_params = entity.record? ? entity.unsaved_attributes.merge(params || {}) : params
|
103
|
-
|
104
|
-
if link_params.blank?
|
105
|
-
''
|
106
|
-
else
|
107
|
-
'?' + {entity.base_model => link_params}.to_query
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
end
|
112
|
-
|
113
|
-
DefaultRecordVerbs = {
|
114
|
-
:show => :get,
|
115
|
-
:edit => :get,
|
116
|
-
:update => :put,
|
117
|
-
:destroy => :delete
|
118
|
-
}.freeze
|
119
|
-
DefaultResourceVerbs = {
|
120
|
-
:index => :get
|
121
|
-
}.freeze
|
122
|
-
DefaultBuildVerbs = {
|
123
|
-
:new => :get,
|
124
|
-
:create => :post
|
125
|
-
}.freeze
|
126
|
-
|
127
|
-
attr_reader :mdl, :parent, :children, :record_routes, :resource_routes, :build_routes
|
128
|
-
|
129
|
-
def initialize entity = nil, options = {}
|
130
|
-
@mdl = entity if entity.is_a?(Symbol)
|
131
|
-
@parent = options[:parent]
|
132
|
-
@children = {}
|
133
|
-
define_routes options
|
134
|
-
end
|
135
|
-
|
136
|
-
def ancestry
|
137
|
-
parent.nil? ? [] : parent.ancestry.push(self)
|
138
|
-
end
|
139
|
-
|
140
|
-
def for verb, entities, options
|
141
|
-
raise "HammockResource#for requires an explicitly specified verb as its first argument." unless verb.is_a?(Symbol)
|
142
|
-
raise "You have to supply at least one record or resource." if entities.empty?
|
143
|
-
|
144
|
-
entity = entities.shift
|
145
|
-
|
146
|
-
if entities.empty?
|
147
|
-
piece_for verb, entity
|
148
|
-
else
|
149
|
-
children[entity.resource_sym].for(verb, entities, options).within piece_for(nil, entity)
|
150
|
-
end
|
151
|
-
end
|
152
|
-
|
153
|
-
def add entity, options, steps = nil
|
154
|
-
if steps.nil?
|
155
|
-
add entity, options, (options[:name_prefix] || '').chomp('_').split('_').map {|i| i.pluralize.underscore.to_sym }
|
156
|
-
elsif steps.empty?
|
157
|
-
add_child entity, options
|
158
|
-
else
|
159
|
-
children[steps.shift].add entity, options, steps
|
160
|
-
end
|
161
|
-
end
|
162
|
-
|
163
|
-
def routeable_as verb, entity
|
164
|
-
if entity.record? && record_routes[verb || :show]
|
165
|
-
:record
|
166
|
-
elsif entity.resource? && resource_routes[verb || :index]
|
167
|
-
:resource
|
168
|
-
elsif !verb.nil? && build_routes[verb]
|
169
|
-
:build
|
170
|
-
end
|
171
|
-
end
|
172
|
-
|
173
|
-
private
|
174
|
-
|
175
|
-
def define_routes options
|
176
|
-
@record_routes = DefaultRecordVerbs.dup.update(options[:member] || {})
|
177
|
-
@resource_routes = DefaultResourceVerbs.dup.update(options[:collection] || {})
|
178
|
-
@build_routes = DefaultBuildVerbs.dup.update(options[:build] || {})
|
179
|
-
end
|
180
|
-
|
181
|
-
def add_child entity, options
|
182
|
-
child = HammockResource.new entity, options.merge(:parent => self)
|
183
|
-
children[child.mdl] = child
|
184
|
-
end
|
185
|
-
|
186
|
-
def piece_for verb, entity
|
187
|
-
child = children[entity.resource_sym]
|
188
|
-
|
189
|
-
if child.nil?
|
190
|
-
raise "No routes are defined for #{entity.resource}#{' within ' + ancestry.map {|r| r.mdl.to_s }.join(', ') unless ancestry.empty?}."
|
191
|
-
else
|
192
|
-
HammockRoutePiece.new(child).for(verb, entity)
|
193
|
-
end
|
194
|
-
end
|
195
|
-
|
23
|
+
self.route_map = Hammock::RouteNode.new
|
196
24
|
end
|
197
25
|
|
198
26
|
end
|
@@ -15,10 +15,10 @@ module Hammock
|
|
15
15
|
find_record :find_with_deleted
|
16
16
|
end
|
17
17
|
|
18
|
-
def find_record
|
18
|
+
def find_record
|
19
19
|
result = if !callback(:before_find)
|
20
20
|
# callbacks failed
|
21
|
-
elsif (record = retrieve_record
|
21
|
+
elsif (record = retrieve_record).nil?
|
22
22
|
log "#{mdl}<#{params[:id]}> doesn't exist within #{requester_name.possessive} #{action_name} scope."
|
23
23
|
:not_found
|
24
24
|
elsif :ok != (verbability = can_verb_record?(action_name.to_sym, record))
|
@@ -44,11 +44,11 @@ module Hammock
|
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
47
|
-
def retrieve_record
|
47
|
+
def retrieve_record
|
48
48
|
if (scope = current_scope).nil?
|
49
49
|
|
50
50
|
else
|
51
|
-
record = scope.send
|
51
|
+
record = scope.send :find, :first, :conditions => {mdl.routing_attribute => params[:id]}
|
52
52
|
record || required_callback(:after_failed_find)
|
53
53
|
end
|
54
54
|
end
|
@@ -142,7 +142,7 @@ module Hammock
|
|
142
142
|
|
143
143
|
def find_record_on_create
|
144
144
|
if findable_on_create?
|
145
|
-
if record =
|
145
|
+
if record = current_nest_scope.find(:first, :conditions => params_for(mdl.symbolize))
|
146
146
|
log "suitable record already exists: #{record}"
|
147
147
|
assign_entity record
|
148
148
|
else
|
@@ -29,8 +29,10 @@ module Hammock
|
|
29
29
|
@hammock_cached_mdl_name ||= self.class.to_s.sub('Controller', '').singularize.underscore
|
30
30
|
end
|
31
31
|
|
32
|
-
|
33
|
-
|
32
|
+
# Returns the node in the Hammock routing map corresponding to the (possibly nested) resource handling the current request.
|
33
|
+
def current_hammock_resource
|
34
|
+
nesting_resources = params.keys.select {|k| /_id$/ =~ k }.map {|k| k.gsub(/_id$/, '').pluralize }
|
35
|
+
ActionController::Routing::Routes.route_map.base_for nesting_resources.push(mdl.resource_name).map(&:to_sym)
|
34
36
|
end
|
35
37
|
|
36
38
|
# Returns true if the current action represents an edit on +record+.
|
@@ -57,7 +59,7 @@ module Hammock
|
|
57
59
|
elsif record_or_records.is_a? ActiveRecord::Base
|
58
60
|
instance_variable_set "@#{mdl_name}", (@record = record_or_records)
|
59
61
|
elsif record_or_records.is_a? Ambition::Context
|
60
|
-
|
62
|
+
log "Unkicked query: #{record_or_records.to_hash.inspect}"
|
61
63
|
instance_variable_set "@#{mdl_name.pluralize}", (@records = record_or_records)
|
62
64
|
elsif record_or_records.is_a? Array
|
63
65
|
instance_variable_set "@#{mdl_name.pluralize}", (@records = record_or_records)
|
@@ -65,15 +67,25 @@ module Hammock
|
|
65
67
|
raise "Unknown record(s) type #{record_or_records.class}."
|
66
68
|
end
|
67
69
|
|
68
|
-
if
|
69
|
-
@entity
|
70
|
-
else
|
71
|
-
escort :not_found
|
72
|
-
end
|
70
|
+
@entity if assign_nesting_entities
|
73
71
|
end
|
74
72
|
|
75
73
|
private
|
76
74
|
|
75
|
+
def assign_nesting_entities
|
76
|
+
results = nesting_scope_list.map &:kick
|
77
|
+
|
78
|
+
if results.all? {|records| records.length == 1 }
|
79
|
+
results.map {|records|
|
80
|
+
records.first
|
81
|
+
}.all? {|record|
|
82
|
+
log "nested record #{record.concise_inspect} assigned to @#{record.base_model}."
|
83
|
+
add_nested_entity record
|
84
|
+
instance_variable_set "@#{record.base_model}", record
|
85
|
+
}
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
77
89
|
def make_new_record resource = mdl
|
78
90
|
resource.new_with(params_for(resource.symbolize))
|
79
91
|
end
|
@@ -92,39 +104,24 @@ module Hammock
|
|
92
104
|
end
|
93
105
|
end
|
94
106
|
|
95
|
-
def assign_nestable_resources
|
96
|
-
@current_nested_records, @current_nested_resources = [], []
|
97
|
-
params.symbolize_keys.dragnet(*nestable_resources.keys).all? {|param_name,column_name|
|
98
|
-
constant_name = param_name.to_s.sub(/_id$/, '').camelize
|
99
|
-
constant = Object.const_get constant_name rescue nil
|
100
|
-
|
101
|
-
if constant.nil?
|
102
|
-
log "'#{constant_name}' is not available for #{param_name}."
|
103
|
-
elsif (record = constant.find_by_id(params[param_name])).nil?
|
104
|
-
log "#{constant}<#{params[param_name]}> not found."
|
105
|
-
else
|
106
|
-
@current_nested_records << record
|
107
|
-
@current_nested_resources << record.class
|
108
|
-
@record.send "#{nestable_resources[param_name]}=", params[param_name] unless @record.nil?
|
109
|
-
# log "Assigning @#{constant.name.underscore} with #{record.inspect}."
|
110
|
-
instance_variable_set "@#{constant_name.underscore}", record
|
111
|
-
end
|
112
|
-
}
|
113
|
-
end
|
114
|
-
|
115
107
|
def current_nested_records
|
116
|
-
@current_nested_records
|
108
|
+
(@current_nested_records || []).dup
|
117
109
|
end
|
118
110
|
|
119
111
|
def current_nested_resources
|
120
|
-
@current_nested_resources
|
112
|
+
(@current_nested_resources || []).dup
|
113
|
+
end
|
114
|
+
|
115
|
+
def add_nested_entity entity
|
116
|
+
(@current_nested_records ||= []).push entity
|
117
|
+
(@current_nested_resources ||= []).push entity.resource
|
121
118
|
end
|
122
119
|
|
123
120
|
def nested_within? record_or_resource
|
124
121
|
if record_or_resource.is_a? ActiveRecord::Base
|
125
|
-
|
122
|
+
current_nested_records.include? record_or_resource
|
126
123
|
else
|
127
|
-
|
124
|
+
current_nested_resources.include? record_or_resource
|
128
125
|
end
|
129
126
|
end
|
130
127
|
|
@@ -136,8 +133,15 @@ module Hammock
|
|
136
133
|
@editing = @record
|
137
134
|
end
|
138
135
|
|
136
|
+
# TODO process /^creating_\w+_id$/ as well
|
139
137
|
def set_creator_id_if_appropriate
|
140
|
-
|
138
|
+
if @record.respond_to?(:creator_id=)
|
139
|
+
if @current_account.nil?
|
140
|
+
log "Warning: @#{@record.base_model}.creator_id isn't being set, since @current_account was nil."
|
141
|
+
else
|
142
|
+
@record.creator_id = @current_account.id
|
143
|
+
end
|
144
|
+
end
|
141
145
|
end
|
142
146
|
|
143
147
|
def partial_exists? name, extension = nil
|
data/lib/hammock/route_for.rb
CHANGED
@@ -47,7 +47,7 @@ module Hammock
|
|
47
47
|
def nested_route_for *resources
|
48
48
|
resources.delete_if &:nil?
|
49
49
|
requested_verb = resources.shift if resources.first.is_a?(Symbol)
|
50
|
-
args =
|
50
|
+
args = current_nested_records.concat(resources)
|
51
51
|
|
52
52
|
args.unshift(requested_verb) unless requested_verb.nil?
|
53
53
|
route_for *args
|
@@ -0,0 +1,159 @@
|
|
1
|
+
module Hammock
|
2
|
+
class RouteNode < ActionController::Resources::Resource
|
3
|
+
|
4
|
+
DefaultRecordVerbs = {
|
5
|
+
:show => :get,
|
6
|
+
:edit => :get,
|
7
|
+
:update => :put,
|
8
|
+
:destroy => :delete
|
9
|
+
}.freeze
|
10
|
+
DefaultResourceVerbs = {
|
11
|
+
:index => :get
|
12
|
+
}.freeze
|
13
|
+
DefaultBuildVerbs = {
|
14
|
+
:new => :get,
|
15
|
+
:create => :post
|
16
|
+
}.freeze
|
17
|
+
|
18
|
+
attr_reader :mdl, :resource, :parent, :children, :routing_parent, :record_routes, :resource_routes, :build_routes
|
19
|
+
|
20
|
+
def initialize entity = nil, options = {}
|
21
|
+
@parent = options[:parent]
|
22
|
+
@children = {}
|
23
|
+
unless root?
|
24
|
+
@mdl = entity if entity.is_a?(Symbol)
|
25
|
+
@routing_parent = determine_routing_parent
|
26
|
+
define_routes options
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def resource
|
31
|
+
# TODO performance
|
32
|
+
Object.const_get mdl.to_s.classify rescue nil
|
33
|
+
end
|
34
|
+
|
35
|
+
def root?
|
36
|
+
parent.nil?
|
37
|
+
end
|
38
|
+
|
39
|
+
def ancestry
|
40
|
+
root? ? [] : parent.ancestry.push(self)
|
41
|
+
end
|
42
|
+
|
43
|
+
def for verb, entities, options
|
44
|
+
raise "Hammock::RouteNode#for requires an explicitly specified verb as its first argument." unless verb.is_a?(Symbol)
|
45
|
+
raise "You have to supply an Array of at least one record or resource." if entities.empty? unless entities.is_a?(Array)
|
46
|
+
|
47
|
+
entity = entities.shift
|
48
|
+
|
49
|
+
if entities.empty?
|
50
|
+
steps_for verb, entity
|
51
|
+
else
|
52
|
+
children[entity.resource_sym].for(verb, entities, options).within steps_for(nil, entity)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def base_for resources
|
57
|
+
# puts "base_for<#{mdl}>: resources=#{resources.inspect}."
|
58
|
+
if resources.empty?
|
59
|
+
self
|
60
|
+
else
|
61
|
+
match = nil
|
62
|
+
children.values.detect {|child|
|
63
|
+
# puts " Trying #{child.ancestry.map(&:mdl).inspect} for #{resources.inspect}"
|
64
|
+
if !resources.include?(child.mdl)
|
65
|
+
# puts " Can't match #{resources.inspect} against #{child.mdl}."
|
66
|
+
nil
|
67
|
+
else
|
68
|
+
# puts " Matched #{child.mdl} from #{resources.inspect}."
|
69
|
+
match = child.base_for resources.discard(child.mdl)
|
70
|
+
end
|
71
|
+
} #|| raise("There is no routing path for #{resources.map(&:inspect).inspect}.")
|
72
|
+
match
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def nesting_scope_list_for params
|
77
|
+
if root?
|
78
|
+
[ ]
|
79
|
+
else
|
80
|
+
parent.nesting_scope_list_for(params).push nesting_scope_segment_for(params)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def nesting_scope_segment_for params
|
85
|
+
raise "The root of the route map isn't associated with a resource." if root?
|
86
|
+
puts "is this undefined? #{resource.accessible_attributes_on_create.inspect}"
|
87
|
+
value = params.delete resource.param_key
|
88
|
+
puts "resource.select {|r| r.#{resource.routing_attribute} == value }"
|
89
|
+
eval "resource.select {|r| r.#{resource.routing_attribute} == value }"
|
90
|
+
end
|
91
|
+
|
92
|
+
def add entity, options, steps = nil
|
93
|
+
if steps.nil?
|
94
|
+
add entity, options, (options[:name_prefix] || '').chomp('_').split('_').map {|i| i.pluralize.underscore.to_sym }
|
95
|
+
elsif steps.empty?
|
96
|
+
add_child entity, options
|
97
|
+
else
|
98
|
+
children[steps.shift].add entity, options, steps
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def routeable_as verb, entity
|
103
|
+
if entity.record? && record_routes[verb || :show]
|
104
|
+
:record
|
105
|
+
elsif entity.resource? && resource_routes[verb || :index]
|
106
|
+
:resource
|
107
|
+
elsif !verb.nil? && build_routes[verb]
|
108
|
+
:build
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
private
|
113
|
+
|
114
|
+
def define_routes options
|
115
|
+
@record_routes = DefaultRecordVerbs.dup.update(options[:member] || {})
|
116
|
+
@resource_routes = DefaultResourceVerbs.dup.update(options[:collection] || {})
|
117
|
+
@build_routes = DefaultBuildVerbs.dup.update(options[:build] || {})
|
118
|
+
end
|
119
|
+
|
120
|
+
def determine_routing_parent
|
121
|
+
puts "\ndetermine_routing_parent: #{mdl}:"
|
122
|
+
if parent.nil? || parent.resource.nil?
|
123
|
+
puts "Resource for #{mdl} has either no parent or no resource - not nestable."
|
124
|
+
nil
|
125
|
+
else
|
126
|
+
puts "reflections: #{resource.reflections.keys.inspect}"
|
127
|
+
puts "nestable_routing_resources: #{resource.nestable_routing_resources.inspect}"
|
128
|
+
scannable_reflections = resource.nestable_routing_resources.nil? ? resource.reflections : resource.reflections.dragnet(*resource.nestable_routing_resources)
|
129
|
+
puts "scannable reflections: #{scannable_reflections.keys.inspect}"
|
130
|
+
valid_reflections = scannable_reflections.selekt {|k,v| puts "#{v.klass}<#{v.object_id}> == #{parent.resource}<#{parent.resource.object_id}> #=> #{v.klass == parent.resource}"; v.klass == parent.resource }
|
131
|
+
puts "valid reflections: #{valid_reflections.keys.inspect}"
|
132
|
+
|
133
|
+
if valid_reflections.keys.length < 1
|
134
|
+
raise "The routing table specifies that #{mdl} is nested within #{parent.mdl}, but there is no ActiveRecord association linking #{resource} to #{parent.resource}. Example: 'belongs_to :#{parent.resource.base_model}' in the #{resource} model."
|
135
|
+
elsif valid_reflections.keys.length > 1
|
136
|
+
raise "#{resource} defines more than one association to #{parent.resource} (#{valid_reflections.keys.map(&:to_s).join(', ')}). That's fine, but you need to use #{resource}.nest_within to specify the one Hammock should nest scopes through. For example, 'nest_within #{valid_reflections.keys.first.inspect}' in the #{resource} model."
|
137
|
+
end
|
138
|
+
|
139
|
+
valid_reflections.keys.first
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def add_child entity, options
|
144
|
+
child = RouteNode.new entity, options.merge(:parent => self)
|
145
|
+
children[child.mdl] = child
|
146
|
+
end
|
147
|
+
|
148
|
+
def steps_for verb, entity
|
149
|
+
child = children[entity.resource_sym]
|
150
|
+
|
151
|
+
if child.nil?
|
152
|
+
raise "No routes are defined for #{entity.resource}#{' within ' + ancestry.map {|r| r.mdl.to_s }.join(', ') unless ancestry.empty?}."
|
153
|
+
else
|
154
|
+
RouteStep.new(child).for(verb, entity)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
end
|
159
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
module Hammock
|
2
|
+
class RouteStep
|
3
|
+
attr_reader :resource, :routeable_as, :verb, :entity, :parent
|
4
|
+
|
5
|
+
def initialize resource
|
6
|
+
@resource = resource
|
7
|
+
end
|
8
|
+
|
9
|
+
def for verb, entity
|
10
|
+
routeable_as = resource.routeable_as(verb, entity)
|
11
|
+
|
12
|
+
if !routeable_as
|
13
|
+
raise "The verb '#{verb}' can't be applied to " + (entity.record? ? "#{entity.resource} records" : "the #{entity.resource} resource") + "."
|
14
|
+
elsif (:record == routeable_as) && entity.new_record?
|
15
|
+
raise "The verb '#{verb}' requires a #{entity.resource} with an ID (i.e. not a new record)."
|
16
|
+
elsif (:build == routeable_as) && entity.record? && !entity.new_record?
|
17
|
+
raise "The verb '#{verb}' requires either the #{entity.resource} resource, or a #{entity.resource} without an ID (i.e. a new record)."
|
18
|
+
else
|
19
|
+
@verb, @entity, @routeable_as = verb, entity, routeable_as
|
20
|
+
end
|
21
|
+
|
22
|
+
self
|
23
|
+
end
|
24
|
+
|
25
|
+
def within parent
|
26
|
+
@parent = parent
|
27
|
+
self
|
28
|
+
end
|
29
|
+
|
30
|
+
def setup?
|
31
|
+
!@entity.nil?
|
32
|
+
end
|
33
|
+
|
34
|
+
def path params = nil
|
35
|
+
raise_unless_setup_while_trying_to 'render a path'
|
36
|
+
|
37
|
+
buf = '/'
|
38
|
+
buf << entity.resource_name
|
39
|
+
buf << '/' + entity.to_param if entity.record? && !entity.new_record?
|
40
|
+
buf << '/' + verb.to_s unless verb.nil? or implied_verb?(verb)
|
41
|
+
|
42
|
+
buf = parent.path + buf unless parent.nil?
|
43
|
+
buf << param_str(params)
|
44
|
+
|
45
|
+
buf
|
46
|
+
end
|
47
|
+
|
48
|
+
def http_method
|
49
|
+
raise_unless_setup_while_trying_to 'extract the HTTP method'
|
50
|
+
resource.send("#{routeable_as}_routes")[verb]
|
51
|
+
end
|
52
|
+
|
53
|
+
def fake_http_method
|
54
|
+
http_method.in?(:get, :post) ? http_method : :post
|
55
|
+
end
|
56
|
+
|
57
|
+
def get?; :get == http_method end
|
58
|
+
def post?; :post == http_method end
|
59
|
+
def put?; :put == http_method end
|
60
|
+
def delete?; :delete == http_method end
|
61
|
+
|
62
|
+
def safe?
|
63
|
+
get? && !verb.in?(Hammock::Constants::ImpliedUnsafeActions)
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def implied_verb? verb
|
69
|
+
verb.in? :index, :create, :show, :update, :destroy
|
70
|
+
end
|
71
|
+
|
72
|
+
def raise_unless_setup_while_trying_to task
|
73
|
+
raise "You have to call for(verb, entity) (and optionally within(parent)) on this RouteStep before you can #{task}." unless setup?
|
74
|
+
end
|
75
|
+
|
76
|
+
def param_str params
|
77
|
+
link_params = entity.record? ? entity.unsaved_attributes.merge(params || {}) : params
|
78
|
+
|
79
|
+
if link_params.blank?
|
80
|
+
''
|
81
|
+
else
|
82
|
+
'?' + {entity.base_model => link_params}.to_query
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
end
|
data/lib/hammock/scope.rb
CHANGED
@@ -62,7 +62,7 @@ module Hammock
|
|
62
62
|
end
|
63
63
|
end
|
64
64
|
|
65
|
-
def
|
65
|
+
def current_verb_scope
|
66
66
|
if @current_account && (scope_name = account_verb_scope?)
|
67
67
|
# log "got an account_verb_scope #{scope_name}."
|
68
68
|
mdl.send scope_name, @current_account
|
@@ -75,17 +75,24 @@ module Hammock
|
|
75
75
|
end
|
76
76
|
end
|
77
77
|
|
78
|
-
def
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
78
|
+
def nesting_scope_list
|
79
|
+
@hammock_cached_nesting_scope_list = current_hammock_resource.parent.nesting_scope_list_for params.selekt {|k,v| /_id$/ =~ k }
|
80
|
+
end
|
81
|
+
|
82
|
+
def current_nest_scope
|
83
|
+
nesting_scope_list.reverse.inject {|acc,scope| acc.within scope }
|
83
84
|
end
|
84
85
|
|
85
86
|
def current_scope
|
86
|
-
|
87
|
+
log "#{current_hammock_resource.mdl}, #{current_hammock_resource.ancestry.map(&:mdl).inspect}"
|
88
|
+
if (verb_scope = current_verb_scope).nil?
|
89
|
+
nil
|
90
|
+
elsif (resultant_scope = verb_scope.within(current_nest_scope, current_hammock_resource.routing_parent)).nil?
|
87
91
|
nil
|
88
92
|
else
|
93
|
+
# puts "nest: #{current_nest_scope.clauses.inspect}"
|
94
|
+
# puts "verb: #{current_verb_scope.clauses.inspect}"
|
95
|
+
puts "chained in (#{resultant_scope.owner}) current_scope: #{resultant_scope.clauses.inspect}"
|
89
96
|
resultant_scope = resultant_scope.chain(custom_scope) unless custom_scope.nil?
|
90
97
|
resultant_scope.sort_by &mdl.sorter
|
91
98
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: benhoskings-hammock
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ben Hoskings
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-03-05 00:00:00 -08:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -63,6 +63,7 @@ files:
|
|
63
63
|
- hammock.gemspec
|
64
64
|
- lib/hammock.rb
|
65
65
|
- lib/hammock/ajaxinate.rb
|
66
|
+
- lib/hammock/callback.rb
|
66
67
|
- lib/hammock/callbacks.rb
|
67
68
|
- lib/hammock/canned_scopes.rb
|
68
69
|
- lib/hammock/constants.rb
|
@@ -91,6 +92,8 @@ files:
|
|
91
92
|
- lib/hammock/restful_support.rb
|
92
93
|
- lib/hammock/route_drawing_hooks.rb
|
93
94
|
- lib/hammock/route_for.rb
|
95
|
+
- lib/hammock/route_node.rb
|
96
|
+
- lib/hammock/route_step.rb
|
94
97
|
- lib/hammock/scope.rb
|
95
98
|
- lib/hammock/suggest.rb
|
96
99
|
- lib/hammock/utils.rb
|
@@ -98,7 +101,6 @@ files:
|
|
98
101
|
- misc/template.rb
|
99
102
|
- tasks/hammock_tasks.rake
|
100
103
|
- test/hammock_test.rb
|
101
|
-
- test/rails_root/test/test_helper.rb
|
102
104
|
has_rdoc: true
|
103
105
|
homepage: http://github.com/benhoskings/hammock
|
104
106
|
post_install_message:
|
@@ -126,5 +128,5 @@ rubygems_version: 1.2.0
|
|
126
128
|
signing_key:
|
127
129
|
specification_version: 2
|
128
130
|
summary: Hammock is a Rails plugin that eliminates redundant code in a very RESTful manner
|
129
|
-
test_files:
|
130
|
-
|
131
|
+
test_files: []
|
132
|
+
|