resourcelogic 0.0.12 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
data/{LICENSE → MIT-LICENSE}
RENAMED
File without changes
|
data/Manifest.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
CHANGELOG.rdoc
|
2
|
+
MIT-LICENSE
|
3
|
+
Manifest.txt
|
4
|
+
README.rdoc
|
5
|
+
Rakefile
|
6
|
+
init.rb
|
7
|
+
lib/resourcelogic.rb
|
8
|
+
lib/resourcelogic/accessors.rb
|
9
|
+
lib/resourcelogic/action_options.rb
|
10
|
+
lib/resourcelogic/actions.rb
|
11
|
+
lib/resourcelogic/base.rb
|
12
|
+
lib/resourcelogic/child.rb
|
13
|
+
lib/resourcelogic/context.rb
|
14
|
+
lib/resourcelogic/failable_action_options.rb
|
15
|
+
lib/resourcelogic/parent.rb
|
16
|
+
lib/resourcelogic/response_collector.rb
|
17
|
+
lib/resourcelogic/self.rb
|
18
|
+
lib/resourcelogic/sibling.rb
|
19
|
+
lib/resourcelogic/singleton.rb
|
20
|
+
lib/resourcelogic/urligence.rb
|
21
|
+
lib/resourcelogic/version.rb
|
data/README.rdoc
CHANGED
@@ -1,50 +1,26 @@
|
|
1
1
|
= Resourcelogic
|
2
2
|
|
3
|
-
|
3
|
+
*Beta warning: right now this plugin is in what I like to call a "semi-beta". The only thing left to do is write documentation and add in the tests. I have already thoroughly tested this in a separate application, and am in the process of moving over the tests without having to pull over the entire rails application.*
|
4
4
|
|
5
|
-
The purpose of Resourcelogic is to support a development style I created called
|
5
|
+
The purpose of Resourcelogic is to support a development style I created called "Contextual Development" (see contextual development below). This is an idea I've had for a while and finally decided to give it a try on one of my projects. This library spawned out of the {resource_controller plugin}(http://github.com/giraffesoft/resource_controller) by James Gollick, which is an excellent plugin. I eventually made so many changes to it that it made more sense to rewrite my own.
|
6
6
|
|
7
7
|
== Helpful links
|
8
8
|
|
9
|
-
* <b>Documentation:</b> http://
|
10
|
-
* <b>Bugs / feature suggestions:</b> http://binarylogic.lighthouseapp.com/projects/28581-resourcelogic
|
9
|
+
* <b>Documentation:</b> http://resourcelogic.rubyforge.org
|
11
10
|
|
12
11
|
== Contextual Development
|
13
12
|
|
14
|
-
The idea behind contextual development is simple:
|
13
|
+
The idea behind contextual development is simple: *an API should be a be a byproduct of good design*. Meaning you should never have to explicitly build an API, it should be an "accident".
|
15
14
|
|
16
|
-
|
15
|
+
Your interface should not dictate the structure of your controllers. Instead, your controllers should represent a collection of resources that your interface can use. The problem is that rails does so much magic, and makes so many assumptions, that sometimes it distorts the basics behind the MVC pattern.
|
17
16
|
|
18
|
-
|
17
|
+
This becomes very clear when you try build an interface with {Flex}[http://www.adobe.com/products/flex/]. What this forces you to do is separate your interface from your application. A flex interface communicates with your application via XML. So when you finish an app with a Flex interface you all of a sudden have a "production ready" API as well. Which feels really good. A proper API is the foundation for growing your application. Once this is done the sky is the limit.
|
19
18
|
|
20
|
-
|
19
|
+
That being said, why can't we accomplish the same thing with an HTML interface? For one, an HTML interface isn't as cleanly decoupled from the controllers as a Flex interface. For two, rails doesn't give us all of the tools to properly accomplish this. Instead, people create work-arounds by namespacing controllers to represent context and scope. Instead, why not have a single controller that is *context aware*. Hence the name *"Contextual Development"*.
|
21
20
|
|
22
|
-
|
21
|
+
This is great because now you have a single controller that *every* request for the resource must pass through. In the same manner that all database activity passes through ORM models. You can feel confident adding controller specific logic to that resource without having to worry about duplicating it across multiple controllers. Ex: storing the user's IP address with a record.
|
23
22
|
|
24
|
-
|
25
|
-
layout Proc.new { context == :admin ? "admin" : "application" }
|
26
|
-
|
27
|
-
private
|
28
|
-
# context is irrelevant when determining scope
|
29
|
-
def scope
|
30
|
-
current_user.admin? ? Comment : current_user.comments
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
=== 2. Single point of access for resources
|
35
|
-
|
36
|
-
Having a <b>single</b> controller is great, because it represents a <b>single</b> resource. This means that <b>every</b> request for that resource must pass through that single controller. Think about it, what is an API essentially? Controlled access to your database. You don't go and create an entirely new model for every scope/context you use the model, do you? Why do the same for your API? Your API resources are the "models" for anyone using it, so it doesn't make sense to have /comments and /admin/comments.
|
37
|
-
|
38
|
-
To bring it all home, all requests for a resource should pass through a single controller, in the same manner that all database activity for a table must pass through a single model. You can feel confident adding controller specific logic to that resource without having to worry about duplicating it across multiple controllers. A very simple example: storing the user's IP address with a record.
|
39
|
-
|
40
|
-
=== 3. Relative URL and path methods
|
41
|
-
|
42
|
-
Another big problem with using the same controller in various contexts is the need to specify relative paths instead of absolute paths. When you specify resources in your routes you get all kinds of useful <b>absolute</b> path methods, but where are the relative ones? Let's say you have the following paths:
|
43
|
-
|
44
|
-
1. /articles
|
45
|
-
2. /admin/articles
|
46
|
-
|
47
|
-
Articles have many comments. What if you want to link to that article's comments? Do you use <b>article_comments_path</b> or <b>admin_article_comments_path</b>? You could use the <b>context</b> method described above to determine this, but this will get messy and annoying very fast. Instead why not use <b>child_collection_path(:comments)</b>? The paths are relative based on a tree structure. So you also get <b>parent</b> and <b>sibling</b> paths. Now you can easily nest resources without having to worry about linking to them. See the documentation for more details on the various URL and path methods that are available to you.
|
23
|
+
If it is any consolation, I am speaking from experience. I recently finished a very complex project using this method and I can say, without a doubt, it's the cleanest application I've built to date.
|
48
24
|
|
49
25
|
== Install and use
|
50
26
|
|
@@ -73,7 +49,7 @@ Your ResourceController should look something like:
|
|
73
49
|
acts_as_resource
|
74
50
|
end
|
75
51
|
|
76
|
-
Now all of your controllers that are "resources" can extend this controller. Why do this? So you can set your default behavior for resources in one spot. This idea what brought over from the resource_controller plugin. The
|
52
|
+
Now all of your controllers that are "resources" can extend this controller. Why do this? So you can set your default behavior for resources in one spot. This idea what brought over from the resource_controller plugin. The syntax resource_controller came up with is pretty cool:
|
77
53
|
|
78
54
|
class ResourceController < ApplicationController
|
79
55
|
acts_as_resource
|
@@ -100,10 +76,20 @@ Instead of namespacing your controllers, give them context. For example, let's s
|
|
100
76
|
Then in your controller use the context method to make adjustments:
|
101
77
|
|
102
78
|
class CommentsController < ResourceController
|
103
|
-
layout
|
79
|
+
layout :layout_by_context
|
80
|
+
|
81
|
+
private
|
82
|
+
def layout_by_context
|
83
|
+
case context
|
84
|
+
when :admin
|
85
|
+
"admin"
|
86
|
+
else
|
87
|
+
"application"
|
88
|
+
end
|
89
|
+
end
|
104
90
|
end
|
105
91
|
|
106
|
-
You also have the same context method in your views. Lastly, if you feel your views are getting cluttered
|
92
|
+
You also have the same context method in your views. Lastly, if you feel your views are getting cluttered you can use the contextual_views option (See Resourcelogic::Context::Config for more info). This will change your default view path to a context subfolder. Ex:
|
107
93
|
|
108
94
|
/comments
|
109
95
|
/admin
|
@@ -114,54 +100,36 @@ See the Feature Highlights section below for more options, and the documentation
|
|
114
100
|
|
115
101
|
== Feature highlights
|
116
102
|
|
117
|
-
I don't want to repeat what is already in the documentation, but there are a lot of really nice configuration and utility methods.
|
103
|
+
I don't want to repeat what is already in the documentation, but there are a lot of really nice configuration and utility methods. Here are just a few:
|
118
104
|
|
119
|
-
|
105
|
+
*Class level methods*
|
120
106
|
|
121
107
|
belongs_to :relationship_name # will check to see if the resource is being scoped by a parent and give you some nifty methods for this (see below). You can call this multiple times. Just like ActiveRecord.
|
122
|
-
contextual_views true # will split up your views into subfolders: comments/context1, comments/context2, and will change your default view path to the
|
123
|
-
|
124
|
-
<b>Instance level methods</b>
|
108
|
+
contextual_views true # will split up your views into subfolders: comments/context1, comments/context2, and will change your default view path to the respecive folder
|
125
109
|
|
126
|
-
|
110
|
+
*Instance level methods*
|
127
111
|
|
128
112
|
context # the name of the context you are in
|
129
113
|
|
130
|
-
object # current
|
131
|
-
collection # current collection
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
object_path # /products/:id
|
137
|
-
edit_object_path # /products/:id/edit
|
138
|
-
new_object_path # /products/new
|
139
|
-
collection_path # /products
|
114
|
+
object # current object
|
115
|
+
collection # current collection
|
116
|
+
object_path # /comments/:id
|
117
|
+
new_object_path # /comments/new
|
118
|
+
collection_path # /comments
|
140
119
|
|
141
|
-
|
142
|
-
|
143
|
-
parent_collection_path # /
|
144
|
-
new_parent_path # /
|
120
|
+
parent # current parent object
|
121
|
+
parent_path # /parent_name/:parent_id
|
122
|
+
parent_collection_path # /parent_name
|
123
|
+
new_parent_path # /parent_name/new
|
145
124
|
|
146
125
|
sibling_path(sibling) # /sibling_name/:id
|
147
|
-
edit_sibling_path(sibling) # /sibling_name/:id/edit
|
148
126
|
new_sibling_path(:sibling_name) # /sibling_name/new
|
149
127
|
sibling_collection_path(:sibling_name) # /sibling_name
|
150
128
|
|
151
|
-
child_path(child) # /
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
Notice you have the edit_* paths. The above paths are implemented in a very flexible manner. So you are not limited them, you can call your custom actions too:
|
157
|
-
|
158
|
-
map.resources :products, :member => [:approve], :collection => [:approve_all]
|
159
|
-
approve_object_path # /products/:id/approve
|
160
|
-
approve_all_collection_path # /products/approve
|
161
|
-
|
162
|
-
The above example is probably not the best one, but you get the point.
|
163
|
-
|
164
|
-
Lastly, all of the above can end with _url instead of _path. <b>See docs for a complete list of available methods.</b>
|
165
|
-
|
129
|
+
child_path(child) # /sibling_name/:id
|
130
|
+
new_child_path(:child_name) # /sibling_name/new
|
131
|
+
child_collection_path(:child_name) # /sibling_name
|
132
|
+
|
133
|
+
All of the above can end with _url instead of _path. See docs for a complete list of available methods.
|
166
134
|
|
167
|
-
Copyright (c) 2008 {Ben Johnson of Binary Logic}
|
135
|
+
Copyright (c) 2008 {Ben Johnson of Binary Logic}(http://www.binarylogic.com), released under the MIT license
|
data/Rakefile
CHANGED
@@ -1,49 +1,20 @@
|
|
1
|
-
|
2
|
-
require 'rake'
|
1
|
+
ENV['RDOCOPT'] = "-S -f html -T hanna"
|
3
2
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
gem.name = "resourcelogic"
|
8
|
-
gem.summary = "Removes the need to namespace controllers by adding context and relative url functions among other things."
|
9
|
-
gem.email = "bjohnson@binarylogic.com"
|
10
|
-
gem.homepage = "http://github.com/binarylogic/resourcelogic"
|
11
|
-
gem.authors = ["Ben Johnson of Binary Logic"]
|
12
|
-
gem.rubyforge_project = "resourcelogic"
|
13
|
-
gem.add_dependency "activesupport"
|
14
|
-
end
|
15
|
-
rescue LoadError
|
16
|
-
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
17
|
-
end
|
3
|
+
require "rubygems"
|
4
|
+
require "hoe"
|
5
|
+
require File.dirname(__FILE__) << "/lib/resourcelogic/version"
|
18
6
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
rescue LoadError
|
34
|
-
task :rcov do
|
35
|
-
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
task :default => :test
|
40
|
-
|
41
|
-
begin
|
42
|
-
require 'rake/contrib/sshpublisher'
|
43
|
-
namespace :rubyforge do
|
44
|
-
desc "Release gem to RubyForge"
|
45
|
-
task :release => ["rubyforge:release:gem"]
|
46
|
-
end
|
47
|
-
rescue LoadError
|
48
|
-
puts "Rake SshDirPublisher is unavailable or your rubyforge environment is not configured."
|
49
|
-
end
|
7
|
+
Hoe.new("Resourcelogic", Resourcelogic::Version::STRING) do |p|
|
8
|
+
p.name = "resourcelogic"
|
9
|
+
p.author = "Ben Johnson of Binary Logic"
|
10
|
+
p.email = 'bjohnson@binarylogic.com'
|
11
|
+
p.summary = "Making an API a byproduct of good design."
|
12
|
+
p.description = "Making an API a byproduct of good design."
|
13
|
+
p.url = "http://github.com/binarylogic/resourcelogic"
|
14
|
+
p.history_file = "CHANGELOG.rdoc"
|
15
|
+
p.readme_file = "README.rdoc"
|
16
|
+
p.extra_rdoc_files = ["CHANGELOG.rdoc", "README.rdoc"]
|
17
|
+
p.remote_rdoc_dir = ''
|
18
|
+
p.test_globs = ["test/*/test_*.rb", "test/*_test.rb", "test/*/*_test.rb"]
|
19
|
+
p.extra_deps = %w(activesupport)
|
20
|
+
end
|
data/lib/resourcelogic.rb
CHANGED
@@ -1,16 +1,14 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/resourcelogic/version"
|
1
2
|
require File.dirname(__FILE__) + "/resourcelogic/accessors"
|
2
3
|
require File.dirname(__FILE__) + "/resourcelogic/action_options"
|
3
4
|
require File.dirname(__FILE__) + "/resourcelogic/actions"
|
4
|
-
require File.dirname(__FILE__) + "/resourcelogic/aliases"
|
5
5
|
require File.dirname(__FILE__) + "/resourcelogic/child"
|
6
6
|
require File.dirname(__FILE__) + "/resourcelogic/context"
|
7
7
|
require File.dirname(__FILE__) + "/resourcelogic/failable_action_options"
|
8
8
|
require File.dirname(__FILE__) + "/resourcelogic/parent"
|
9
9
|
require File.dirname(__FILE__) + "/resourcelogic/response_collector"
|
10
|
-
require File.dirname(__FILE__) + "/resourcelogic/scope"
|
11
10
|
require File.dirname(__FILE__) + "/resourcelogic/self"
|
12
11
|
require File.dirname(__FILE__) + "/resourcelogic/sibling"
|
13
12
|
require File.dirname(__FILE__) + "/resourcelogic/singleton"
|
14
|
-
require File.dirname(__FILE__) + "/resourcelogic/sub_views"
|
15
13
|
require File.dirname(__FILE__) + "/resourcelogic/urligence"
|
16
14
|
require File.dirname(__FILE__) + "/resourcelogic/base"
|
@@ -33,7 +33,7 @@ module Resourcelogic # :nodoc:
|
|
33
33
|
write_inheritable_attribute accessor_name, start_value
|
34
34
|
|
35
35
|
class_eval <<-"end_eval", __FILE__, __LINE__
|
36
|
-
def self.#{accessor_name}(
|
36
|
+
def self.#{accessor_name}(&block)
|
37
37
|
read_inheritable_attribute(:#{accessor_name}).instance_eval(&block) if block_given?
|
38
38
|
read_inheritable_attribute(:#{accessor_name})
|
39
39
|
end
|
@@ -1,26 +1,48 @@
|
|
1
1
|
module Resourcelogic
|
2
2
|
module Actions
|
3
3
|
ACTIONS = [:index, :show, :new_action, :create, :edit, :update, :destroy].freeze
|
4
|
-
FAILABLE_ACTIONS = ACTIONS - [:index, :new_action, :edit
|
4
|
+
FAILABLE_ACTIONS = ACTIONS - [:index, :new_action, :edit].freeze
|
5
5
|
|
6
6
|
def self.included(klass)
|
7
7
|
klass.class_eval do
|
8
|
+
extend Config
|
8
9
|
ACTIONS.each do |action|
|
9
10
|
class_scoping_reader action, FAILABLE_ACTIONS.include?(action) ? FailableActionOptions.new : ActionOptions.new
|
10
11
|
end
|
11
|
-
class_scoping_reader :context, ContextOptions.new
|
12
12
|
add_acts_as_resource_module(Methods)
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
|
+
module Config
|
17
|
+
def actions(*opts)
|
18
|
+
config = {}
|
19
|
+
config.merge!(opts.pop) if opts.last.is_a?(Hash)
|
20
|
+
|
21
|
+
all_actions = (false && singleton? ? Resourcelogic::SINGLETON_ACTIONS : Resourcelogic::Actions::ACTIONS) - [:new_action] + [:new]
|
22
|
+
|
23
|
+
actions_to_remove = []
|
24
|
+
if opts.first == :none
|
25
|
+
actions_to_remove = all_actions
|
26
|
+
else
|
27
|
+
actions_to_remove += all_actions - opts unless opts.first == :all
|
28
|
+
actions_to_remove += [*config[:except]] if config[:except]
|
29
|
+
actions_to_remove.uniq!
|
30
|
+
end
|
31
|
+
|
32
|
+
actions_to_remove.each { |action| undef_method(action) if method_defined?(action) }
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
16
36
|
module Methods
|
17
37
|
def new
|
38
|
+
build_object
|
18
39
|
load_object
|
19
40
|
before :new_action
|
20
41
|
response_for :new_action
|
21
42
|
end
|
22
|
-
|
43
|
+
|
23
44
|
def create
|
45
|
+
build_object
|
24
46
|
load_object
|
25
47
|
before :create
|
26
48
|
if object.save
|
@@ -33,16 +55,16 @@ module Resourcelogic
|
|
33
55
|
response_for :create_fails
|
34
56
|
end
|
35
57
|
end
|
36
|
-
|
58
|
+
|
37
59
|
def edit
|
38
60
|
load_object
|
39
61
|
before :edit
|
40
62
|
response_for :edit
|
41
63
|
end
|
42
|
-
|
64
|
+
|
43
65
|
def update
|
44
66
|
load_object
|
45
|
-
object.attributes =
|
67
|
+
object.attributes = object_params
|
46
68
|
before :update
|
47
69
|
if object.save
|
48
70
|
after :update
|
@@ -54,7 +76,7 @@ module Resourcelogic
|
|
54
76
|
response_for :update_fails
|
55
77
|
end
|
56
78
|
end
|
57
|
-
|
79
|
+
|
58
80
|
def destroy
|
59
81
|
load_object
|
60
82
|
before :destroy
|
@@ -62,8 +84,12 @@ module Resourcelogic
|
|
62
84
|
after :destroy
|
63
85
|
set_flash :destroy
|
64
86
|
response_for :destroy
|
87
|
+
rescue DestroyNotAllowed
|
88
|
+
after :destroy_fails
|
89
|
+
set_flash :destroy_fails
|
90
|
+
response_for :destroy_fails
|
65
91
|
end
|
66
|
-
|
92
|
+
|
67
93
|
def show
|
68
94
|
load_object
|
69
95
|
before :show
|
@@ -71,7 +97,7 @@ module Resourcelogic
|
|
71
97
|
rescue ActiveRecord::RecordNotFound
|
72
98
|
response_for :show_fails
|
73
99
|
end
|
74
|
-
|
100
|
+
|
75
101
|
def index
|
76
102
|
load_collection
|
77
103
|
before :index
|
@@ -95,26 +121,26 @@ module Resourcelogic
|
|
95
121
|
rescue ActionController::DoubleRenderError
|
96
122
|
end
|
97
123
|
end
|
98
|
-
|
124
|
+
|
99
125
|
# Calls the after callbacks for the action, if one is present.
|
100
126
|
#
|
101
127
|
def after(action)
|
102
128
|
invoke_callbacks *options_for(action).after
|
103
129
|
end
|
104
|
-
|
130
|
+
|
105
131
|
# Calls the before block for the action, if one is present.
|
106
132
|
#
|
107
133
|
def before(action)
|
108
134
|
invoke_callbacks *self.class.send(action).before
|
109
135
|
end
|
110
|
-
|
136
|
+
|
111
137
|
# Sets the flash and flash_now for the action, if it is present.
|
112
138
|
#
|
113
139
|
def set_flash(action)
|
114
140
|
set_normal_flash(action)
|
115
141
|
set_flash_now(action)
|
116
142
|
end
|
117
|
-
|
143
|
+
|
118
144
|
# Sets the regular flash (i.e. flash[:notice] = '...')
|
119
145
|
#
|
120
146
|
def set_normal_flash(action)
|
@@ -122,7 +148,7 @@ module Resourcelogic
|
|
122
148
|
flash[:notice] = f.is_a?(Proc) ? instance_eval(&f) : options_for(action).flash
|
123
149
|
end
|
124
150
|
end
|
125
|
-
|
151
|
+
|
126
152
|
# Sets the flash.now (i.e. flash.now[:notice] = '...')
|
127
153
|
#
|
128
154
|
def set_flash_now(action)
|
@@ -130,7 +156,7 @@ module Resourcelogic
|
|
130
156
|
flash.now[:notice] = f.is_a?(Proc) ? instance_eval(&f) : options_for(action).flash_now
|
131
157
|
end
|
132
158
|
end
|
133
|
-
|
159
|
+
|
134
160
|
# Returns the options for an action, which is a symbol.
|
135
161
|
#
|
136
162
|
# Manages splitting things like :create_fails.
|
@@ -139,14 +165,14 @@ module Resourcelogic
|
|
139
165
|
action = action == :new_action ? [action] : "#{action}".split('_').map(&:to_sym)
|
140
166
|
options = self.class.send(action.first)
|
141
167
|
options = options.send(action.last == :fails ? :fails : :success) if Resourcelogic::Actions::FAILABLE_ACTIONS.include? action.first
|
142
|
-
|
168
|
+
|
143
169
|
options
|
144
170
|
end
|
145
|
-
|
171
|
+
|
146
172
|
def invoke_callbacks(*callbacks)
|
147
173
|
unless callbacks.empty?
|
148
174
|
callbacks.select { |callback| callback.is_a? Symbol }.each { |symbol| send(symbol) }
|
149
|
-
|
175
|
+
|
150
176
|
block = callbacks.detect { |callback| callback.is_a? Proc }
|
151
177
|
instance_eval &block unless block.nil?
|
152
178
|
end
|
@@ -156,13 +182,20 @@ module Resourcelogic
|
|
156
182
|
instance_variable_set "@#{parent_model_name}", parent_object if parent?
|
157
183
|
end
|
158
184
|
|
185
|
+
def build_object
|
186
|
+
return @object if @object
|
187
|
+
@object = end_of_association_chain.send parent? ? :build : :new
|
188
|
+
@object.attributes = object_params
|
189
|
+
@object
|
190
|
+
end
|
191
|
+
|
159
192
|
# Used internally to load the member object in to an instance variable @#{model_name} (i.e. @post)
|
160
193
|
#
|
161
194
|
def load_object
|
162
195
|
load_parent
|
163
196
|
instance_variable_set "@#{object_name}", object
|
164
197
|
end
|
165
|
-
|
198
|
+
|
166
199
|
# Used internally to load the collection in to an instance variable @#{model_name.pluralize} (i.e. @posts)
|
167
200
|
#
|
168
201
|
def load_collection
|