resourcelogic 0.0.12 → 0.9.0
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/{LICENSE → MIT-LICENSE} +0 -0
- data/Manifest.txt +21 -0
- data/README.rdoc +41 -73
- data/Rakefile +18 -47
- data/lib/resourcelogic.rb +1 -3
- data/lib/resourcelogic/accessors.rb +1 -1
- data/lib/resourcelogic/actions.rb +52 -19
- data/lib/resourcelogic/base.rb +3 -33
- data/lib/resourcelogic/child.rb +73 -33
- data/lib/resourcelogic/context.rb +61 -24
- data/lib/resourcelogic/parent.rb +100 -68
- data/lib/resourcelogic/response_collector.rb +2 -7
- data/lib/resourcelogic/self.rb +123 -87
- data/lib/resourcelogic/sibling.rb +46 -4
- data/lib/resourcelogic/singleton.rb +55 -37
- data/lib/resourcelogic/urligence.rb +59 -77
- data/lib/resourcelogic/version.rb +51 -0
- metadata +23 -18
- data/.gitignore +0 -7
- data/VERSION.yml +0 -4
- data/lib/resourcelogic/aliases.rb +0 -134
- data/lib/resourcelogic/context_options.rb +0 -5
- data/lib/resourcelogic/scope.rb +0 -36
- data/lib/resourcelogic/sub_views.rb +0 -98
- data/resourcelogic.gemspec +0 -62
@@ -1,60 +1,57 @@
|
|
1
1
|
module Resourcelogic
|
2
2
|
module Urligence
|
3
|
-
def
|
4
|
-
|
3
|
+
def smart_url(*objects)
|
4
|
+
url_params = objects.extract_options!
|
5
|
+
objects.push(:url)
|
6
|
+
objects.push(url_params)
|
7
|
+
urligence(*objects)
|
5
8
|
end
|
6
|
-
|
7
|
-
def
|
8
|
-
url_params =
|
9
|
-
|
10
|
-
|
11
|
-
urligence(*
|
9
|
+
|
10
|
+
def smart_path(*objects)
|
11
|
+
url_params = objects.extract_options!
|
12
|
+
objects.push(:path)
|
13
|
+
objects.push(url_params)
|
14
|
+
urligence(*objects)
|
12
15
|
end
|
13
|
-
|
14
|
-
def
|
15
|
-
|
16
|
-
url_parts.push(:path)
|
17
|
-
url_parts.push(url_params)
|
18
|
-
urligence(*url_parts)
|
16
|
+
|
17
|
+
def hash_for_smart_url(*objects)
|
18
|
+
urligence(*objects.unshift(:hash_for).push(:url).push({:type => :hash}))
|
19
19
|
end
|
20
|
-
|
21
|
-
def
|
22
|
-
urligence(*
|
20
|
+
|
21
|
+
def hash_for_smart_path(*objects)
|
22
|
+
urligence(*objects.unshift(:hash_for).push(:path).push({:type => :hash}))
|
23
23
|
end
|
24
|
+
|
25
|
+
def urligence(*objects)
|
26
|
+
objects = cleanup_url_objects(objects)
|
27
|
+
url_fragments = extract_url_fragments(objects)
|
28
|
+
url_objects = extract_url_objects(objects)
|
24
29
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
private
|
30
|
-
def urligence(*url_parts)
|
31
|
-
url_parts = cleanup_url_parts(url_parts)
|
32
|
-
method_name_fragments = extract_method_name_fragments(url_parts)
|
33
|
-
method_arguments = extract_method_arguments(url_parts)
|
34
|
-
|
35
|
-
if url_parts.first != :hash_for
|
36
|
-
send method_name_fragments.join("_"), *method_arguments
|
30
|
+
begin
|
31
|
+
if objects.first != :hash_for
|
32
|
+
send url_fragments.join("_"), *url_objects
|
37
33
|
else
|
38
|
-
url_params =
|
34
|
+
url_params = url_objects.extract_options!
|
39
35
|
params = {}
|
40
|
-
|
41
|
-
key = i == (
|
42
|
-
:id :
|
43
|
-
(obj.is_a?(Array) ? "#{obj.first}_id".to_sym : "#{obj.class.name.underscore}_id".to_sym)
|
36
|
+
url_objects.each_with_index do |obj, i|
|
37
|
+
key = i == (url_objects.size - 1) ? :id : (obj.is_a?(Array) ? "#{obj.first}_id".to_sym : "#{obj.class.name.underscore}_id".to_sym)
|
44
38
|
params.merge!((obj.is_a?(Array)) ? {key => obj[1].to_param} : {key => obj.to_param})
|
45
39
|
end
|
46
|
-
|
40
|
+
|
47
41
|
params.merge!(url_params)
|
48
|
-
send
|
42
|
+
send url_fragments.join("_"), params
|
49
43
|
end
|
44
|
+
rescue NoMethodError
|
45
|
+
raise objects.inspect
|
50
46
|
end
|
51
|
-
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
52
50
|
# The point of this method is to replace any object if a url param is passed. For example:
|
53
51
|
#
|
54
|
-
# [:
|
52
|
+
# [:user, user_object], {:user_id => 4}
|
55
53
|
#
|
56
|
-
# The "user_object" should be replaced by user with id 4
|
57
|
-
# The last part is the url_params.
|
54
|
+
# The "user_object" should be replaced by user with id 4.
|
58
55
|
#
|
59
56
|
# This also pluralizes path names if the obj is nil. Example:
|
60
57
|
#
|
@@ -70,35 +67,31 @@ module Resourcelogic
|
|
70
67
|
# payments/credit_cards
|
71
68
|
#
|
72
69
|
# You can manage and select a credit card from the credit cards resource but a payment object
|
73
|
-
# is not needed.
|
74
|
-
def
|
75
|
-
|
76
|
-
url_params =
|
77
|
-
|
78
|
-
|
79
|
-
|
70
|
+
# is not needed.
|
71
|
+
def cleanup_url_objects(objects)
|
72
|
+
objects = objects.compact
|
73
|
+
url_params = objects.last.is_a?(Hash) ? objects.last : {}
|
74
|
+
non_symbol_object_total = objects.select { |object| !object.is_a?(Symbol) }.size - 1
|
75
|
+
non_symbol_object_count = 0
|
76
|
+
new_objects = []
|
77
|
+
objects.each do |object|
|
78
|
+
non_symbol_object_count += 1 if !object.is_a?(Symbol)
|
80
79
|
if !object.is_a?(Array)
|
81
|
-
|
82
|
-
new_url_parts << object
|
80
|
+
new_objects << object
|
83
81
|
else
|
84
|
-
# Let's try to
|
85
82
|
klass = object.first.to_s.camelize.constantize rescue nil
|
86
|
-
|
87
|
-
|
88
|
-
obj =
|
89
|
-
|
90
|
-
else
|
91
|
-
object[1]
|
92
|
-
end
|
93
|
-
new_url_parts << [object.first, obj]
|
94
|
-
#new_url_parts << (obj.nil? ? object.first.to_s.pluralize.to_sym : [object.first, obj])
|
83
|
+
klass_name = klass ? klass.name.underscore : nil
|
84
|
+
key = (non_symbol_object_count == non_symbol_object_total) ? :id : "#{object.first}_id".to_sym
|
85
|
+
obj = (url_params.key?(key) ? ((!klass && url_params[key]) || (url_params[key] && klass.find(url_params.delete(key)))) : object[1])
|
86
|
+
new_objects << (obj.nil? ? object.first.to_s.pluralize.to_sym : [object.first, obj])
|
95
87
|
end
|
96
88
|
end
|
97
|
-
|
89
|
+
new_objects
|
98
90
|
end
|
99
|
-
|
100
|
-
|
101
|
-
|
91
|
+
|
92
|
+
|
93
|
+
def extract_url_fragments(objects)
|
94
|
+
fragments = objects.collect do |obj|
|
102
95
|
if obj.is_a?(Symbol)
|
103
96
|
obj
|
104
97
|
elsif obj.is_a?(Array)
|
@@ -109,20 +102,9 @@ module Resourcelogic
|
|
109
102
|
end
|
110
103
|
fragments.compact
|
111
104
|
end
|
112
|
-
|
113
|
-
def
|
114
|
-
|
115
|
-
end
|
116
|
-
|
117
|
-
def method_missing(method, *args, &block)
|
118
|
-
if method.to_s =~ /^((.*)_)?(child_collection|parent_collection|sibling|sibling_collection)_(path|url)$/ || method.to_s =~ /^((.*)_)?(child|collection|object|parent)_(path|url)$/
|
119
|
-
action = $2.blank? ? nil : $2.to_sym
|
120
|
-
target = $3
|
121
|
-
url_type = $4
|
122
|
-
send("smart_#{url_type}", *send("#{target}_url_parts", action, *args))
|
123
|
-
else
|
124
|
-
super
|
125
|
-
end
|
105
|
+
|
106
|
+
def extract_url_objects(objects)
|
107
|
+
objects.flatten.select { |obj| !obj.is_a?(Symbol) }
|
126
108
|
end
|
127
109
|
end
|
128
110
|
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Resourcelogic # :nodoc:
|
2
|
+
# A class for describing the current version of a library. The version
|
3
|
+
# consists of three parts: the +major+ number, the +minor+ number, and the
|
4
|
+
# +tiny+ (or +patch+) number.
|
5
|
+
class Version
|
6
|
+
include Comparable
|
7
|
+
|
8
|
+
# A convenience method for instantiating a new Version instance with the
|
9
|
+
# given +major+, +minor+, and +tiny+ components.
|
10
|
+
def self.[](major, minor, tiny)
|
11
|
+
new(major, minor, tiny)
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_reader :major, :minor, :tiny
|
15
|
+
|
16
|
+
# Create a new Version object with the given components.
|
17
|
+
def initialize(major, minor, tiny)
|
18
|
+
@major, @minor, @tiny = major, minor, tiny
|
19
|
+
end
|
20
|
+
|
21
|
+
# Compare this version to the given +version+ object.
|
22
|
+
def <=>(version)
|
23
|
+
to_i <=> version.to_i
|
24
|
+
end
|
25
|
+
|
26
|
+
# Converts this version object to a string, where each of the three
|
27
|
+
# version components are joined by the '.' character. E.g., 2.0.0.
|
28
|
+
def to_s
|
29
|
+
@to_s ||= [@major, @minor, @tiny].join(".")
|
30
|
+
end
|
31
|
+
|
32
|
+
# Converts this version to a canonical integer that may be compared
|
33
|
+
# against other version objects.
|
34
|
+
def to_i
|
35
|
+
@to_i ||= @major * 1_000_000 + @minor * 1_000 + @tiny
|
36
|
+
end
|
37
|
+
|
38
|
+
def to_a
|
39
|
+
[@major, @minor, @tiny]
|
40
|
+
end
|
41
|
+
|
42
|
+
MAJOR = 0
|
43
|
+
MINOR = 9
|
44
|
+
TINY = 0
|
45
|
+
|
46
|
+
# The current version as a Version instance
|
47
|
+
CURRENT = new(MAJOR, MINOR, TINY)
|
48
|
+
# The current version as a String
|
49
|
+
STRING = CURRENT.to_s
|
50
|
+
end
|
51
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: resourcelogic
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ben Johnson of Binary Logic
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-04-02 00:00:00 -04:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -22,49 +22,54 @@ dependencies:
|
|
22
22
|
- !ruby/object:Gem::Version
|
23
23
|
version: "0"
|
24
24
|
version:
|
25
|
-
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: hoe
|
27
|
+
type: :development
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.11.0
|
34
|
+
version:
|
35
|
+
description: Making an API a byproduct of good design.
|
26
36
|
email: bjohnson@binarylogic.com
|
27
37
|
executables: []
|
28
38
|
|
29
39
|
extensions: []
|
30
40
|
|
31
41
|
extra_rdoc_files:
|
32
|
-
-
|
42
|
+
- Manifest.txt
|
43
|
+
- CHANGELOG.rdoc
|
33
44
|
- README.rdoc
|
34
45
|
files:
|
35
|
-
- .gitignore
|
36
46
|
- CHANGELOG.rdoc
|
37
|
-
- LICENSE
|
47
|
+
- MIT-LICENSE
|
48
|
+
- Manifest.txt
|
38
49
|
- README.rdoc
|
39
50
|
- Rakefile
|
40
|
-
- VERSION.yml
|
41
51
|
- init.rb
|
42
52
|
- lib/resourcelogic.rb
|
43
53
|
- lib/resourcelogic/accessors.rb
|
44
54
|
- lib/resourcelogic/action_options.rb
|
45
55
|
- lib/resourcelogic/actions.rb
|
46
|
-
- lib/resourcelogic/aliases.rb
|
47
56
|
- lib/resourcelogic/base.rb
|
48
57
|
- lib/resourcelogic/child.rb
|
49
58
|
- lib/resourcelogic/context.rb
|
50
|
-
- lib/resourcelogic/context_options.rb
|
51
59
|
- lib/resourcelogic/failable_action_options.rb
|
52
60
|
- lib/resourcelogic/parent.rb
|
53
61
|
- lib/resourcelogic/response_collector.rb
|
54
|
-
- lib/resourcelogic/scope.rb
|
55
62
|
- lib/resourcelogic/self.rb
|
56
63
|
- lib/resourcelogic/sibling.rb
|
57
64
|
- lib/resourcelogic/singleton.rb
|
58
|
-
- lib/resourcelogic/sub_views.rb
|
59
65
|
- lib/resourcelogic/urligence.rb
|
60
|
-
- resourcelogic.
|
66
|
+
- lib/resourcelogic/version.rb
|
61
67
|
has_rdoc: true
|
62
68
|
homepage: http://github.com/binarylogic/resourcelogic
|
63
|
-
licenses: []
|
64
|
-
|
65
69
|
post_install_message:
|
66
70
|
rdoc_options:
|
67
|
-
- --
|
71
|
+
- --main
|
72
|
+
- README.rdoc
|
68
73
|
require_paths:
|
69
74
|
- lib
|
70
75
|
required_ruby_version: !ruby/object:Gem::Requirement
|
@@ -82,9 +87,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
82
87
|
requirements: []
|
83
88
|
|
84
89
|
rubyforge_project: resourcelogic
|
85
|
-
rubygems_version: 1.3.
|
90
|
+
rubygems_version: 1.3.1
|
86
91
|
signing_key:
|
87
|
-
specification_version:
|
88
|
-
summary:
|
92
|
+
specification_version: 2
|
93
|
+
summary: Making an API a byproduct of good design.
|
89
94
|
test_files: []
|
90
95
|
|
data/.gitignore
DELETED
data/VERSION.yml
DELETED
@@ -1,134 +0,0 @@
|
|
1
|
-
module Resourcelogic
|
2
|
-
# This module let's you define various aliases for your controller. For example,
|
3
|
-
# lets say you have the following routes:
|
4
|
-
#
|
5
|
-
# /account/addresses => UsersController
|
6
|
-
# /admin/users/5/addresses => UsersController
|
7
|
-
#
|
8
|
-
# Here is how your AddressesController would look:
|
9
|
-
#
|
10
|
-
# class AddressesController < ResourceController
|
11
|
-
# belongs_to :user
|
12
|
-
# end
|
13
|
-
#
|
14
|
-
# The problem is that sometimes the parent object is called user, sometimes its
|
15
|
-
# called account. So the solution is to do:
|
16
|
-
#
|
17
|
-
# class ResourceController < ApplicationController
|
18
|
-
# route_alias :account, :user
|
19
|
-
# end
|
20
|
-
#
|
21
|
-
# Now ResourceLogic knows that when it see account in the URL it will know the grab
|
22
|
-
# the User model.
|
23
|
-
#
|
24
|
-
# Now I know an alternative could be to do somethig like:
|
25
|
-
#
|
26
|
-
# belongs_to :user, :alias => :account
|
27
|
-
#
|
28
|
-
# The above presents a problem. Take the following URL:
|
29
|
-
#
|
30
|
-
# /productos/1/pictures/4/comments
|
31
|
-
#
|
32
|
-
# In order for Resourcelogic to do its magic relative URLs, it needs to know what
|
33
|
-
# model "productos" should be using. Which should be the Product model, yet we
|
34
|
-
# can't define that in the CommentsController because it's 2 levels above, and we
|
35
|
-
# only specify the parent.
|
36
|
-
#
|
37
|
-
# Now a lot of people say you should never nest more than 2 levels deep, and this
|
38
|
-
# is absolutely true 95% of the time. But what if I want to link back to the parent
|
39
|
-
# object from the comments controller and preserve it's context? In order to do
|
40
|
-
# this I have to go 3 levels deep, because maybe context for the PicturesController
|
41
|
-
# is really important / required. The only way to preserve context is with the URL.
|
42
|
-
#
|
43
|
-
# Sorry for rambling, this documentation is really more of an internal note for me
|
44
|
-
# and to hopefully clarify why I took this approach.
|
45
|
-
module Aliases
|
46
|
-
def self.included(klass)
|
47
|
-
klass.class_eval do
|
48
|
-
extend Config
|
49
|
-
include InstanceMethods
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
module Config
|
54
|
-
def path_alias(alias_name, model_name)
|
55
|
-
current_aliases = path_aliases
|
56
|
-
model_name = model_name.to_sym
|
57
|
-
current_aliases[model_name] ||= []
|
58
|
-
current_aliases[model_name] << alias_name.to_sym
|
59
|
-
write_inheritable_attribute(:path_aliases, current_aliases)
|
60
|
-
end
|
61
|
-
|
62
|
-
def path_aliases
|
63
|
-
read_inheritable_attribute(:path_aliases) || {}
|
64
|
-
end
|
65
|
-
|
66
|
-
def route_alias(alias_name, model_name)
|
67
|
-
current_aliases = route_aliases
|
68
|
-
model_name = model_name.to_sym
|
69
|
-
current_aliases[model_name] ||= []
|
70
|
-
current_aliases[model_name] << alias_name.to_sym
|
71
|
-
write_inheritable_attribute(:route_aliases, current_aliases)
|
72
|
-
end
|
73
|
-
|
74
|
-
def route_aliases
|
75
|
-
read_inheritable_attribute(:route_aliases) || {}
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
module InstanceMethods
|
80
|
-
private
|
81
|
-
def model_name_from_route_alias(alias_name)
|
82
|
-
route_aliases.each do |model_name, aliases|
|
83
|
-
return model_name if aliases.include?(alias_name.to_sym)
|
84
|
-
end
|
85
|
-
nil
|
86
|
-
end
|
87
|
-
|
88
|
-
def route_aliases
|
89
|
-
self.class.route_aliases
|
90
|
-
end
|
91
|
-
|
92
|
-
def model_name_from_path_alias(alias_name)
|
93
|
-
path_aliases.each do |model_name, aliases|
|
94
|
-
return model_name if aliases.include?(alias_name.to_sym)
|
95
|
-
end
|
96
|
-
nil
|
97
|
-
end
|
98
|
-
|
99
|
-
def path_aliases
|
100
|
-
self.class.path_aliases
|
101
|
-
end
|
102
|
-
|
103
|
-
def possible_model_names(model_name)
|
104
|
-
[model_name] + (route_aliases[model_name] || []) + (path_aliases[model_name] || [])
|
105
|
-
end
|
106
|
-
|
107
|
-
# The point of this method is to determine what the part of a url is really referring to.
|
108
|
-
# For example, let's say you did this:
|
109
|
-
#
|
110
|
-
# map.resources :users, :as => :accounts
|
111
|
-
#
|
112
|
-
# Resource logic looks at the request.path. It's going to see "accounts" in the urls. How
|
113
|
-
# is it to know that by "accounts" you are referring to the "users" resource. That's the
|
114
|
-
# point of this method, to say "hey, accounts is mapped to users".
|
115
|
-
def model_name_from_path_part(part)
|
116
|
-
part = part.to_s.singularize
|
117
|
-
model_name_from_route_alias(part) || model_name_from_path_alias(part) || part.to_sym
|
118
|
-
end
|
119
|
-
|
120
|
-
# The point of this method is to determine the name used in the route method. For example,
|
121
|
-
# let's say you did this:
|
122
|
-
#
|
123
|
-
# map.resources :accounts, :controller => "users"
|
124
|
-
#
|
125
|
-
# You would want to use "account" in your path and url helper, not "user".
|
126
|
-
def route_name_from_path_part(part)
|
127
|
-
part = part.to_s.singularize
|
128
|
-
model_name = model_name_from_path_alias(part)
|
129
|
-
return model_name if model_name
|
130
|
-
part.to_sym
|
131
|
-
end
|
132
|
-
end
|
133
|
-
end
|
134
|
-
end
|