thumblemonks-load_model 0.1.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/HISTORY.markdown +4 -0
- data/MIT-LICENSE +24 -0
- data/README.markdown +102 -0
- data/Rakefile +22 -0
- data/lib/load_model.rb +202 -0
- data/load_model.gemspec +52 -0
- data/rails/app/controllers/application.rb +2 -0
- data/rails/config/boot.rb +109 -0
- data/rails/config/database.yml +3 -0
- data/rails/config/environment.rb +71 -0
- data/rails/config/environments/test.rb +19 -0
- data/rails/config/routes.rb +5 -0
- data/rails/db/schema.rb +21 -0
- data/test/functional/controller_helper.rb +82 -0
- data/test/functional/keys_controller_test.rb +26 -0
- data/test/functional/load_model_test.rb +85 -0
- data/test/functional/require_model_controller_test.rb +45 -0
- data/test/functional/restrict_options_controller_test.rb +34 -0
- data/test/functional/string_key_load_model_test.rb +52 -0
- data/test/functional/through_controller_test.rb +61 -0
- data/test/test_helper.rb +27 -0
- metadata +83 -0
data/HISTORY.markdown
ADDED
data/MIT-LICENSE
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
MIT License
|
2
|
+
--------------------------------------------------------------------------------
|
3
|
+
Copyright (c) 2007 Thumble Monks, Justin Knowlden
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person
|
6
|
+
obtaining a copy of this software and associated documentation
|
7
|
+
files (the "Software"), to deal in the Software without
|
8
|
+
restriction, including without limitation the rights to use,
|
9
|
+
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
10
|
+
copies of the Software, and to permit persons to whom the
|
11
|
+
Software is furnished to do so, subject to the following
|
12
|
+
conditions:
|
13
|
+
|
14
|
+
The above copyright notice and this permission notice shall be
|
15
|
+
included in all copies or substantial portions of the Software.
|
16
|
+
|
17
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
18
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
19
|
+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
20
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
21
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
22
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
23
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
24
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
data/README.markdown
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
# Load Model
|
2
|
+
|
3
|
+
A glorified before_filter that loads an instance of an `ActiveRecord` object as the result of searching for said object against a model defined by a given model name. The value of the HTTP request parameter `:id` will be used as the default lookup value. `LoadModel` will give you the ability to require an instance be found and/or override several other default behaviors.
|
4
|
+
|
5
|
+
Example
|
6
|
+
|
7
|
+
class SillyFellowController < Application
|
8
|
+
load_model :silly_fellow
|
9
|
+
def action
|
10
|
+
@silly_fellow.do_something
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
You can require that a model instance be found for all actions or given actions. Default behavior is to not require that a model instance be found. When require is on and a record is not found, a `ThumbleMonks::RequiredRecordNotFound` Exception is thrown; which extends from ActiveRecord::RecordNotFound, for your convenience.
|
15
|
+
|
16
|
+
To turn require on for all actions, simply pass *true* to a provided `:require` attribute, like so:
|
17
|
+
|
18
|
+
Example
|
19
|
+
|
20
|
+
load_model :silly_fellow, :require => true
|
21
|
+
|
22
|
+
To turn require on for specific actions, pass an array of action names to `:require`. The model will be loaded for all actions, regardless of whether or not required is provided, but the exception will only be raised when an record is not found for the provided actions.
|
23
|
+
|
24
|
+
Example
|
25
|
+
|
26
|
+
load_model :silly_fellow, :require => [:show, :update]
|
27
|
+
|
28
|
+
To use a different parameter key and model than the default, you can provide the values in the `:paramater_key` and `:class` options (though not necessary to provide them together), like the following:
|
29
|
+
|
30
|
+
Example
|
31
|
+
|
32
|
+
load_model :foo, :class => :user, :parameter_key => :bar_id
|
33
|
+
|
34
|
+
In the above example, `load_model` will assume the parameter_key and the model's primary/foreign key are both the same. For instance, the above example would result in a call like the following:
|
35
|
+
|
36
|
+
@foo = User.find_by_bar_id(params[:bar_id])
|
37
|
+
|
38
|
+
If you want to use a different lookup/foreign key than the default, you can also provide that key name using the `:foreign_key` parameter; like so:
|
39
|
+
|
40
|
+
Example
|
41
|
+
|
42
|
+
load_model :foo, :class => :user, :parameter_key => :bar_id,
|
43
|
+
:foreign_key => :baz_id
|
44
|
+
|
45
|
+
Which would result in a call similar to the following:
|
46
|
+
|
47
|
+
@foo = User.find_by_baz_id(params[:bar_id])
|
48
|
+
|
49
|
+
If you want to only use `load_model` for some actions, you can still name them as you would with a `before_filter` using `:only` or `:except`. If you provide an `:only` and an `:except` value. `:only` will always win out over `:except` when there are collisions (i.e. you provide both in the same call)
|
50
|
+
|
51
|
+
Example
|
52
|
+
|
53
|
+
load_model :foo, :only => [:show]
|
54
|
+
load_model :bar, :except => [:create]
|
55
|
+
|
56
|
+
Finally, load_model supports a :through option. With :through, you can load a model via the association of an existing loaded model. This is especially useful for RESTful controllers.
|
57
|
+
|
58
|
+
Example
|
59
|
+
|
60
|
+
load_model :user, :require => true, :parameter_key => :user_id
|
61
|
+
load_model :post, :through => :user
|
62
|
+
|
63
|
+
In this example, a @post record will be loaded through the @user record with essentially the following code:
|
64
|
+
|
65
|
+
@user.posts.find_by_id(params[:id])
|
66
|
+
|
67
|
+
All of the previously mentioned options still apply (:parameter_key, :foreign_key, :require, :only, and :except) except for the :class option. Meaning you could really mess around!
|
68
|
+
|
69
|
+
Example
|
70
|
+
|
71
|
+
load_model :user, :require => true, :parameter_key => :user_id
|
72
|
+
load_model :post, :through => :person, :parameter_key => :foo_id,
|
73
|
+
:foreign_key => :baz_id
|
74
|
+
|
75
|
+
Would result in a call similar to the following:
|
76
|
+
|
77
|
+
@person.posts.find_by_baz_id(params[:foo_id])
|
78
|
+
|
79
|
+
Require works as you would expect.
|
80
|
+
|
81
|
+
The only current caveat is that load_model assumes a has_many association exists on the :through model and is named in the pluralized form. In essence, in the above example, there is no way to tell load_model not look for the "posts" association. Perhaps a future change.
|
82
|
+
|
83
|
+
## Installation
|
84
|
+
|
85
|
+
sudo gem install thumblemonks-load_model
|
86
|
+
|
87
|
+
## Requirements
|
88
|
+
|
89
|
+
1. Ruby 1.8.6 or higher
|
90
|
+
2. Rails 2.x or higher
|
91
|
+
|
92
|
+
## Acknowledgements
|
93
|
+
|
94
|
+
Anyone who developed, discussed, or any other way participated in HTTP, REST, and Rails.
|
95
|
+
|
96
|
+
## Contact
|
97
|
+
|
98
|
+
Justin Knowlden <gus@gusg.us>
|
99
|
+
|
100
|
+
## License
|
101
|
+
|
102
|
+
See MIT-LICENSE
|
data/Rakefile
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rake/rdoctask'
|
4
|
+
|
5
|
+
desc 'Default: run unit tests.'
|
6
|
+
task :default => :test
|
7
|
+
|
8
|
+
desc 'Test the load_model plugin.'
|
9
|
+
Rake::TestTask.new(:test) do |t|
|
10
|
+
t.libs << 'lib'
|
11
|
+
t.pattern = 'test/**/*_test.rb'
|
12
|
+
t.verbose = true
|
13
|
+
end
|
14
|
+
|
15
|
+
desc 'Generate documentation for the load_model plugin.'
|
16
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
17
|
+
rdoc.rdoc_dir = 'rdoc'
|
18
|
+
rdoc.title = 'LoadModel'
|
19
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
20
|
+
rdoc.rdoc_files.include('README')
|
21
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
22
|
+
end
|
data/lib/load_model.rb
ADDED
@@ -0,0 +1,202 @@
|
|
1
|
+
module ThumbleMonks #:nodoc:
|
2
|
+
module LoadModel
|
3
|
+
|
4
|
+
class RequiredRecordNotFound < ActiveRecord::RecordNotFound; end
|
5
|
+
|
6
|
+
def self.included(klass)
|
7
|
+
klass.extend(ClassMethods)
|
8
|
+
end
|
9
|
+
|
10
|
+
module ClassMethods #:nodoc
|
11
|
+
# A glorified before_filter that loads an instance of an ActiveRecord
|
12
|
+
# object as# the result of searching for said object against a model
|
13
|
+
# defined by a given model name. The value of the HTTP request parameter
|
14
|
+
# :id will be used as the default lookup value. LoadModel will give you
|
15
|
+
# the ability to require an instance be found and/or override several
|
16
|
+
# other default behaviors.
|
17
|
+
#
|
18
|
+
# Example
|
19
|
+
# class SillyFellowController < Application
|
20
|
+
# load_model :silly_fellow
|
21
|
+
# def action
|
22
|
+
# @silly_fellow.do_something
|
23
|
+
# end
|
24
|
+
# ens
|
25
|
+
#
|
26
|
+
# You can require that a model instance be found for all actions or given
|
27
|
+
# actions. Default behavior is to not require that a model instance be
|
28
|
+
# found. When require is on and a record is not found, a
|
29
|
+
# ThumbleMonks::RequiredRecordNotFound Exception is thrown; which does
|
30
|
+
# conveniently extend ActiveRecord::RecordNotFound.
|
31
|
+
#
|
32
|
+
# To turn require on for all actions, simply pass _true_ to a provided
|
33
|
+
# <em>:require</em> attribute, like so:
|
34
|
+
#
|
35
|
+
# Example
|
36
|
+
# load_model :silly_fellow, :require => true
|
37
|
+
#
|
38
|
+
# To turn require on for specific actions, pass an array of action names
|
39
|
+
# to <em>:require</em>. The model will be loaded for all actions,
|
40
|
+
# regardless of whether or not required is provided, but the exception
|
41
|
+
# will only be raised when an record is not found for the provided
|
42
|
+
# actions.
|
43
|
+
#
|
44
|
+
# Example
|
45
|
+
# load_model :silly_fellow, :require => [:show, :update]
|
46
|
+
#
|
47
|
+
# To use a different parameter key and model than the default, you can
|
48
|
+
# provide the values in the :paramater_key and :class options (though not
|
49
|
+
# necessary to provide them together), like the following:
|
50
|
+
#
|
51
|
+
# Example
|
52
|
+
# load_model :foo, :class => :user, :parameter_key => :bar_id
|
53
|
+
#
|
54
|
+
# In the above example, _load_model_ will assume the parameter_key is
|
55
|
+
# :bar_id while assuming the model's primary/foreign is still :id. For
|
56
|
+
# instance, the above example would result in a call like the following:
|
57
|
+
#
|
58
|
+
# @foo = User.find_by_id(params[:bar_id])
|
59
|
+
#
|
60
|
+
# If you want to use a different lookup/foreign key than the default, you
|
61
|
+
# can also provide that key name using the :foreign_key parameter; like
|
62
|
+
# so:
|
63
|
+
#
|
64
|
+
# Example
|
65
|
+
# load_model :foo, :class => :user, :parameter_key => :bar_id,
|
66
|
+
# :foreign_key => :baz_id
|
67
|
+
#
|
68
|
+
# Which would result in a call similar to the following:
|
69
|
+
#
|
70
|
+
# @foo = User.find_by_baz_id(params[:bar_id])
|
71
|
+
#
|
72
|
+
# If you want to only use load_model for some actions, you can still name
|
73
|
+
# them as you would with a before_filter using :only or :except. If you
|
74
|
+
# provide an :only and an :except value. :except will always win out over
|
75
|
+
# :only in the event of a collision.
|
76
|
+
#
|
77
|
+
# Example
|
78
|
+
# load_model :foo, :only => [:show]
|
79
|
+
# load_model :bar, :except => [:create]
|
80
|
+
#
|
81
|
+
# Finally, load_model supports a :through option. With :through, you can
|
82
|
+
# load a model via the association of an existing loaded model. This is
|
83
|
+
# especially useful for RESTful controllers.
|
84
|
+
#
|
85
|
+
# Example
|
86
|
+
# load_model :user, :require => true, :parameter_key => :user_id
|
87
|
+
# load_model :post, :through => :user
|
88
|
+
#
|
89
|
+
# In this example, a @post record will be loaded through the @user record
|
90
|
+
# with essentially the following code:
|
91
|
+
#
|
92
|
+
# @user.posts.find_by_id(params[:id])
|
93
|
+
#
|
94
|
+
# All of the previously mentioned options still apply (:parameter_key,
|
95
|
+
# :foreign_key, :require, :only, and :except) except for the :class
|
96
|
+
# option. Meaning you could really mess around!
|
97
|
+
#
|
98
|
+
# Example
|
99
|
+
# load_model :user, :require => true, :parameter_key => :user_id
|
100
|
+
# load_model :post, :through => :person, :parameter_key => :foo_id,
|
101
|
+
# :foreign_key => :baz_id
|
102
|
+
#
|
103
|
+
# Would result in a call similar to the following:
|
104
|
+
#
|
105
|
+
# @person.posts.find_by_baz_id(params[:foo_id])
|
106
|
+
#
|
107
|
+
# Require works as you would expect
|
108
|
+
#
|
109
|
+
# The only current caveat is that load_model assumes a has_many
|
110
|
+
# association exists on the :through model and is named in the pluralized
|
111
|
+
# form. In essence, in the above example, there is no way to tell
|
112
|
+
# load_model not look for the "posts" association. Perhaps a future
|
113
|
+
# change.
|
114
|
+
#
|
115
|
+
def load_model(name, opts={})
|
116
|
+
unless loaders
|
117
|
+
self.class_eval { before_filter :load_specified_models }
|
118
|
+
write_inheritable_attribute(:loaders, [])
|
119
|
+
end
|
120
|
+
loaders << (opts[:through] ? ThroughModelLoader : ModelLoader).new(name, opts)
|
121
|
+
end
|
122
|
+
|
123
|
+
def loaders; self.read_inheritable_attribute(:loaders); end
|
124
|
+
|
125
|
+
class ModelLoader #:nodoc
|
126
|
+
attr_reader :assigns_to, :load_through, :parameter_key, :foreign_key,
|
127
|
+
:except, :only, :requires
|
128
|
+
|
129
|
+
def initialize(name, opts={})
|
130
|
+
config = {:require => false, :parameter_key => :id,
|
131
|
+
:foreign_key => :id, :class => name}.merge(opts)
|
132
|
+
@assigns_to = "@#{name}".to_sym
|
133
|
+
@load_through = config[:class].to_s.classify.constantize
|
134
|
+
@parameter_key = config[:parameter_key].to_s
|
135
|
+
@foreign_key = config[:foreign_key].to_s
|
136
|
+
@requires = parse_required_actions(config[:require])
|
137
|
+
@except = stringify_array(config[:except])
|
138
|
+
@only = stringify_array(config[:only])
|
139
|
+
end
|
140
|
+
|
141
|
+
def action_allowed?(action)
|
142
|
+
return false if except.include?(action)
|
143
|
+
only.empty? ? true : only.include?(action)
|
144
|
+
end
|
145
|
+
|
146
|
+
def action_required?(action)
|
147
|
+
requires == true || requires.include?(action)
|
148
|
+
end
|
149
|
+
|
150
|
+
def load_model(controller)
|
151
|
+
begin
|
152
|
+
lookup = parameter_value(controller)
|
153
|
+
source(controller).send("find_by_#{foreign_key}", lookup)
|
154
|
+
rescue ActiveRecord::StatementInvalid
|
155
|
+
nil
|
156
|
+
end
|
157
|
+
end
|
158
|
+
private
|
159
|
+
def source(controller) load_through; end
|
160
|
+
|
161
|
+
def parse_required_actions(actions)
|
162
|
+
actions == true ? true : stringify_array(actions)
|
163
|
+
end
|
164
|
+
|
165
|
+
def parameter_value(controller) controller.params[parameter_key]; end
|
166
|
+
|
167
|
+
def stringify_array(value) Array(value).map(&:to_s); end
|
168
|
+
end # ModelLoader
|
169
|
+
|
170
|
+
class ThroughModelLoader < ModelLoader #:nodoc
|
171
|
+
attr_reader :load_through, :association
|
172
|
+
def initialize(name, opts={})
|
173
|
+
super(name, opts)
|
174
|
+
@load_through = "@#{opts[:through]}".to_sym
|
175
|
+
@association = opts[:association] || name.to_s.pluralize
|
176
|
+
end
|
177
|
+
private
|
178
|
+
def source(controller)
|
179
|
+
controller.instance_variable_get(load_through).send(association)
|
180
|
+
end
|
181
|
+
end # ThroughModelLoader
|
182
|
+
|
183
|
+
end # ClassMethods
|
184
|
+
|
185
|
+
private
|
186
|
+
|
187
|
+
def load_specified_models
|
188
|
+
self.class.loaders.each do |loader|
|
189
|
+
if loader.action_allowed?(action_name)
|
190
|
+
obj = loader.load_model(self)
|
191
|
+
if obj.nil? && loader.action_required?(action_name)
|
192
|
+
raise RequiredRecordNotFound
|
193
|
+
end
|
194
|
+
instance_variable_set(loader.assigns_to, obj)
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
end # LoadModel
|
200
|
+
end # ThumbleMonks
|
201
|
+
|
202
|
+
ActionController::Base.send(:include, ThumbleMonks::LoadModel)
|
data/load_model.gemspec
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = "load_model"
|
3
|
+
s.version = "0.1.0"
|
4
|
+
s.date = "2009-01-03"
|
5
|
+
s.summary = "Rails Controller plugin that provides easy and useful macros for tying models and requests together"
|
6
|
+
s.email = %w[gus@gusg.us gabriel.gironda@gmail.com]
|
7
|
+
s.homepage = "http://github.com/thumblemonks/load_model"
|
8
|
+
s.description = "Rails Controller plugin that provides easy and useful macros for tying models and requests together"
|
9
|
+
s.authors = %w[Justin\ Knowlden Gabriel\ Gironda]
|
10
|
+
|
11
|
+
s.rubyforge_project = %q{load_model}
|
12
|
+
|
13
|
+
s.has_rdoc = true
|
14
|
+
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Load Model", "--main", "README.markdown"]
|
15
|
+
s.extra_rdoc_files = ["HISTORY.markdown", "README.markdown"]
|
16
|
+
|
17
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to?(:required_rubygems_version=)
|
18
|
+
s.rubygems_version = "1.3.1"
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
# run git ls-files to get an updated list
|
22
|
+
s.files = %w[
|
23
|
+
HISTORY.markdown
|
24
|
+
MIT-LICENSE
|
25
|
+
README.markdown
|
26
|
+
Rakefile
|
27
|
+
lib/load_model.rb
|
28
|
+
load_model.gemspec
|
29
|
+
]
|
30
|
+
|
31
|
+
s.test_files = %w[
|
32
|
+
rails/app/controllers/application.rb
|
33
|
+
rails/config/boot.rb
|
34
|
+
rails/config/database.yml
|
35
|
+
rails/config/environment.rb
|
36
|
+
rails/config/environments/test.rb
|
37
|
+
rails/config/routes.rb
|
38
|
+
rails/db/schema.rb
|
39
|
+
rails/db/test.db
|
40
|
+
rails/log/test.log
|
41
|
+
test/functional/controller_helper.rb
|
42
|
+
test/functional/keys_controller_test.rb
|
43
|
+
test/functional/load_model_test.rb
|
44
|
+
test/functional/require_model_controller_test.rb
|
45
|
+
test/functional/restrict_options_controller_test.rb
|
46
|
+
test/functional/string_key_load_model_test.rb
|
47
|
+
test/functional/through_controller_test.rb
|
48
|
+
test/test_helper.rb
|
49
|
+
]
|
50
|
+
|
51
|
+
s.post_install_message = %q{Choosy prima donnas choose Thumble Monks}
|
52
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
# Don't change this file!
|
2
|
+
# Configure your app in config/environment.rb and config/environments/*.rb
|
3
|
+
|
4
|
+
RAILS_ROOT = "#{File.dirname(__FILE__)}/.." unless defined?(RAILS_ROOT)
|
5
|
+
|
6
|
+
module Rails
|
7
|
+
class << self
|
8
|
+
def boot!
|
9
|
+
unless booted?
|
10
|
+
preinitialize
|
11
|
+
pick_boot.run
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def booted?
|
16
|
+
defined? Rails::Initializer
|
17
|
+
end
|
18
|
+
|
19
|
+
def pick_boot
|
20
|
+
(vendor_rails? ? VendorBoot : GemBoot).new
|
21
|
+
end
|
22
|
+
|
23
|
+
def vendor_rails?
|
24
|
+
File.exist?("#{RAILS_ROOT}/vendor/rails")
|
25
|
+
end
|
26
|
+
|
27
|
+
def preinitialize
|
28
|
+
load(preinitializer_path) if File.exist?(preinitializer_path)
|
29
|
+
end
|
30
|
+
|
31
|
+
def preinitializer_path
|
32
|
+
"#{RAILS_ROOT}/config/preinitializer.rb"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
class Boot
|
37
|
+
def run
|
38
|
+
load_initializer
|
39
|
+
Rails::Initializer.run(:set_load_path)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class VendorBoot < Boot
|
44
|
+
def load_initializer
|
45
|
+
require "#{RAILS_ROOT}/vendor/rails/railties/lib/initializer"
|
46
|
+
Rails::Initializer.run(:install_gem_spec_stubs)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
class GemBoot < Boot
|
51
|
+
def load_initializer
|
52
|
+
self.class.load_rubygems
|
53
|
+
load_rails_gem
|
54
|
+
require 'initializer'
|
55
|
+
end
|
56
|
+
|
57
|
+
def load_rails_gem
|
58
|
+
if version = self.class.gem_version
|
59
|
+
gem 'rails', version
|
60
|
+
else
|
61
|
+
gem 'rails'
|
62
|
+
end
|
63
|
+
rescue Gem::LoadError => load_error
|
64
|
+
$stderr.puts %(Missing the Rails #{version} gem. Please `gem install -v=#{version} rails`, update your RAILS_GEM_VERSION setting in config/environment.rb for the Rails version you do have installed, or comment out RAILS_GEM_VERSION to use the latest version installed.)
|
65
|
+
exit 1
|
66
|
+
end
|
67
|
+
|
68
|
+
class << self
|
69
|
+
def rubygems_version
|
70
|
+
Gem::RubyGemsVersion if defined? Gem::RubyGemsVersion
|
71
|
+
end
|
72
|
+
|
73
|
+
def gem_version
|
74
|
+
if defined? RAILS_GEM_VERSION
|
75
|
+
RAILS_GEM_VERSION
|
76
|
+
elsif ENV.include?('RAILS_GEM_VERSION')
|
77
|
+
ENV['RAILS_GEM_VERSION']
|
78
|
+
else
|
79
|
+
parse_gem_version(read_environment_rb)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def load_rubygems
|
84
|
+
require 'rubygems'
|
85
|
+
min_version = '1.1.1'
|
86
|
+
unless rubygems_version >= min_version
|
87
|
+
$stderr.puts %Q(Rails requires RubyGems >= #{min_version} (you have #{rubygems_version}). Please `gem update --system` and try again.)
|
88
|
+
exit 1
|
89
|
+
end
|
90
|
+
|
91
|
+
rescue LoadError
|
92
|
+
$stderr.puts %Q(Rails requires RubyGems >= #{min_version}. Please install RubyGems and try again: http://rubygems.rubyforge.org)
|
93
|
+
exit 1
|
94
|
+
end
|
95
|
+
|
96
|
+
def parse_gem_version(text)
|
97
|
+
$1 if text =~ /^[^#]*RAILS_GEM_VERSION\s*=\s*["']([!~<>=]*\s*[\d.]+)["']/
|
98
|
+
end
|
99
|
+
|
100
|
+
private
|
101
|
+
def read_environment_rb
|
102
|
+
File.read("#{RAILS_ROOT}/config/environment.rb")
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
# All that for this:
|
109
|
+
Rails.boot!
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# Be sure to restart your server when you modify this file
|
2
|
+
|
3
|
+
# Uncomment below to force Rails into production mode when
|
4
|
+
# you don't control web/app server and can't set it the proper way
|
5
|
+
# ENV['RAILS_ENV'] ||= 'production'
|
6
|
+
|
7
|
+
# Specifies gem version of Rails to use when vendor/rails is not present
|
8
|
+
RAILS_GEM_VERSION = '2.2.2' unless defined? RAILS_GEM_VERSION
|
9
|
+
|
10
|
+
# Bootstrap the Rails environment, frameworks, and default configuration
|
11
|
+
require File.join(File.dirname(__FILE__), 'boot')
|
12
|
+
|
13
|
+
Rails::Initializer.run do |config|
|
14
|
+
# Settings in config/environments/* take precedence over those specified here.
|
15
|
+
# Application configuration should go into files in config/initializers
|
16
|
+
# -- all .rb files in that directory are automatically loaded.
|
17
|
+
# See Rails::Configuration for more options.
|
18
|
+
|
19
|
+
# Skip frameworks you're not going to use. To use Rails without a database
|
20
|
+
# you must remove the Active Record framework.
|
21
|
+
# config.frameworks -= [ :active_record, :active_resource, :action_mailer ]
|
22
|
+
|
23
|
+
# Specify gems that this application depends on.
|
24
|
+
# They can then be installed with "rake gems:install" on new installations.
|
25
|
+
# config.gem "bj"
|
26
|
+
# config.gem "hpricot", :version => '0.6', :source => "http://code.whytheluckystiff.net"
|
27
|
+
# config.gem "aws-s3", :lib => "aws/s3"
|
28
|
+
config.gem 'thoughtbot-shoulda', :lib => 'shoulda/rails',
|
29
|
+
:source => 'http://gems.github.com'
|
30
|
+
|
31
|
+
# Only load the plugins named here, in the order given. By default, all plugins
|
32
|
+
# in vendor/plugins are loaded in alphabetical order.
|
33
|
+
# :all can be used as a placeholder for all plugins not explicitly named
|
34
|
+
# config.plugins = [ :exception_notification, :ssl_requirement, :all ]
|
35
|
+
|
36
|
+
# Add additional load paths for your own custom dirs
|
37
|
+
# config.load_paths += %W( #{RAILS_ROOT}/extras )
|
38
|
+
|
39
|
+
# Force all environments to use the same logger level
|
40
|
+
# (by default production uses :info, the others :debug)
|
41
|
+
# config.log_level = :debug
|
42
|
+
|
43
|
+
# Make Time.zone default to the specified zone, and make Active Record store time values
|
44
|
+
# in the database in UTC, and return them converted to the specified local zone.
|
45
|
+
# Run "rake -D time" for a list of tasks for finding time zone names. Comment line to use default local time.
|
46
|
+
# config.time_zone = ENV['TZ'] = 'UTC'
|
47
|
+
|
48
|
+
# Your secret key for verifying cookie session data integrity.
|
49
|
+
# If you change this key, all old sessions will become invalid!
|
50
|
+
# Make sure the secret is at least 30 characters and all random,
|
51
|
+
# no regular words or you'll be exposed to dictionary attacks.
|
52
|
+
# config.action_controller.session = {
|
53
|
+
# :session_key => '_load_model_session',
|
54
|
+
# :secret => '731d6426b38a848657211af3650ea99dc064a830ec15fd20565d71ba62498382132872b2d9b549eeb5a016025c119eb821d8e66794cd380888120aa0b857386d'
|
55
|
+
# }
|
56
|
+
|
57
|
+
# Use the database for sessions instead of the cookie-based default,
|
58
|
+
# which shouldn't be used to store highly confidential information
|
59
|
+
# (create the session table with "rake db:sessions:create")
|
60
|
+
# config.action_controller.session_store = :active_record_store
|
61
|
+
|
62
|
+
# Use SQL instead of Active Record's schema dumper when creating the test database.
|
63
|
+
# This is necessary if your schema can't be completely dumped by the schema dumper,
|
64
|
+
# like if you have constraints or database-specific column types
|
65
|
+
# config.active_record.schema_format = :sql
|
66
|
+
|
67
|
+
# Activate observers that should always be running
|
68
|
+
# config.active_record.observers = :cacher, :garbage_collector
|
69
|
+
end
|
70
|
+
|
71
|
+
require 'ruby-debug'
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# Settings specified here will take precedence over those in config/environment.rb
|
2
|
+
|
3
|
+
# The test environment is used exclusively to run your application's
|
4
|
+
# test suite. You never need to work with it otherwise. Remember that
|
5
|
+
# your test database is "scratch space" for the test suite and is wiped
|
6
|
+
# and recreated between test runs. Don't rely on the data there!
|
7
|
+
config.cache_classes = true
|
8
|
+
|
9
|
+
# Log error messages when you accidentally call methods on nil.
|
10
|
+
config.whiny_nils = true
|
11
|
+
|
12
|
+
# Show full error reports and disable caching
|
13
|
+
config.action_controller.consider_all_requests_local = true
|
14
|
+
config.action_controller.perform_caching = false
|
15
|
+
|
16
|
+
# Tell ActionMailer not to deliver emails to the real world.
|
17
|
+
# The :test delivery method accumulates sent emails in the
|
18
|
+
# ActionMailer::Base.deliveries array.
|
19
|
+
config.action_mailer.delivery_method = :test
|
data/rails/db/schema.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
ActiveRecord::Schema.define(:version => 1) do
|
2
|
+
create_table 'users', :force => true do |t|
|
3
|
+
t.column :name, :string
|
4
|
+
end
|
5
|
+
|
6
|
+
create_table 'posts', :force => true do |t|
|
7
|
+
t.column :user_id, :integer
|
8
|
+
t.column :published, :boolean, :default => true
|
9
|
+
t.column :name, :string
|
10
|
+
end
|
11
|
+
|
12
|
+
create_table 'alternates', :force => true do |t|
|
13
|
+
t.column :alternate_id, :integer
|
14
|
+
t.column :name, :string
|
15
|
+
end
|
16
|
+
|
17
|
+
create_table 'fuzzles', :force => true do |t|
|
18
|
+
t.column :fuzzle_id, :integer
|
19
|
+
t.column :name, :string
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
class BasicController < ActionController::Base
|
2
|
+
load_model :user
|
3
|
+
load_model :alternate, :parameter_key => :alternate_id,
|
4
|
+
:foreign_key => :alternate_id
|
5
|
+
load_model :chameleon, :class => :user
|
6
|
+
load_model :flamingo, :class => User
|
7
|
+
load_model :tucan, :class => :alternate, :parameter_key => :alternate_id,
|
8
|
+
:foreign_key => :alternate_id
|
9
|
+
|
10
|
+
def index; render :text => 'hello'; end
|
11
|
+
end
|
12
|
+
class BasicController; def rescue_action(e) raise e end; end
|
13
|
+
|
14
|
+
# Has strings for values
|
15
|
+
|
16
|
+
class StringKeyController < ActionController::Base
|
17
|
+
load_model 'user'
|
18
|
+
load_model 'alternate', :parameter_key => 'alternate_id',
|
19
|
+
:foreign_key => 'alternate_id'
|
20
|
+
load_model 'chameleon', :class => 'user'
|
21
|
+
|
22
|
+
def index; render :text => 'goodbye'; end
|
23
|
+
end
|
24
|
+
class StringKeyController; def rescue_action(e) raise e end; end
|
25
|
+
|
26
|
+
# Requires values
|
27
|
+
|
28
|
+
class RequireModelController < ActionController::Base
|
29
|
+
load_model :stuser, :class => :alternate, :parameter_key => :alternate_id,
|
30
|
+
:foreign_key => :alternate_id, :require => nil # never required
|
31
|
+
load_model :fuzzle, :parameter_key => :fuzzle_id, :foreign_key => :fuzzle_id,
|
32
|
+
:require => [:newer] # required for newer action
|
33
|
+
load_model :user, :require => true # required for all actions
|
34
|
+
|
35
|
+
def index; render :text => 'whatever'; end
|
36
|
+
def new; render :text => 'whatever 2'; end
|
37
|
+
def newer; render :text => 'whatever 3'; end
|
38
|
+
end
|
39
|
+
class RequireModelController; def rescue_action(e) raise e end; end
|
40
|
+
|
41
|
+
# Restriction options
|
42
|
+
|
43
|
+
class RestrictOptionsController < ActionController::Base
|
44
|
+
load_model :user, :only => [:index]
|
45
|
+
load_model :alternate, :except => [:index], :parameter_key => :alternate_id,
|
46
|
+
:foreign_key => :alternate_id
|
47
|
+
|
48
|
+
def index; render :text => 'ran index'; end
|
49
|
+
def show; render :text => 'ran show'; end
|
50
|
+
end
|
51
|
+
class RequireModelController; def rescue_action(e) raise e end; end
|
52
|
+
|
53
|
+
class KeysController < ActionController::Base
|
54
|
+
# Expects to use fuzzle_id as parameter key against User class with FK of :id
|
55
|
+
load_model :user, :parameter_key => :fuzzle_id
|
56
|
+
|
57
|
+
# Expects to use :fuzzle_id as FK and parameter key against Fuzzle class
|
58
|
+
# (normal operation)
|
59
|
+
load_model :fuzzler, :parameter_key => :fuzzle_id, :foreign_key => :fuzzle_id,
|
60
|
+
:class => :fuzzle
|
61
|
+
|
62
|
+
def index; render :text => 'hello'; end
|
63
|
+
end
|
64
|
+
class KeysController; def rescue_action(e) raise e end; end
|
65
|
+
|
66
|
+
# Load model through existing model
|
67
|
+
class ThroughController < ActionController::Base
|
68
|
+
load_model :user, :parameter_key => :user_id
|
69
|
+
load_model :post, :through => :user, :except => [:show]
|
70
|
+
# proving that except and only work
|
71
|
+
load_model :post, :through => :user, :parameter_key => 'weird_id',
|
72
|
+
:require => true, :only => [:show]
|
73
|
+
|
74
|
+
load_model :post, :through => :user, :association => :unpublished_posts,
|
75
|
+
:require => true, :only => [:show_unpublished]
|
76
|
+
|
77
|
+
def index; render :text => 'index'; end
|
78
|
+
def show; render :text => 'show'; end
|
79
|
+
def show_unpublished; render :text => 'unpublished'; end
|
80
|
+
|
81
|
+
end
|
82
|
+
class ThroughController; def rescue_action(e) raise e end; end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
2
|
+
|
3
|
+
class KeysControllerTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
super
|
7
|
+
@request = ActionController::TestRequest.new
|
8
|
+
@response = ActionController::TestResponse.new
|
9
|
+
@controller = KeysController.new
|
10
|
+
@user = User.create!(:name => 'Foo')
|
11
|
+
@fuzzler = Fuzzle.create!(:name => 'Bar', :fuzzle_id => 300)
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_should_find_user_using_fuzzle_id_as_param_key
|
15
|
+
get :index, :fuzzle_id => @user.id
|
16
|
+
assert_equal @user.id, assigns(:user).id
|
17
|
+
assert_nil assigns(:fuzzler)
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_should_find_fuzzler_using_fuzzle_id_as_param_and_foreign_key
|
21
|
+
get :index, :fuzzle_id => @fuzzler.fuzzle_id
|
22
|
+
assert_equal @fuzzler.id, assigns(:fuzzler).id
|
23
|
+
assert_nil assigns(:user)
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
2
|
+
|
3
|
+
class LoadModelTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
super
|
7
|
+
@request = ActionController::TestRequest.new
|
8
|
+
@response = ActionController::TestResponse.new
|
9
|
+
@controller = BasicController.new
|
10
|
+
@foo = User.create!(:name => 'Foo')
|
11
|
+
end
|
12
|
+
|
13
|
+
def teardown
|
14
|
+
Alternate.delete_all
|
15
|
+
User.delete_all
|
16
|
+
end
|
17
|
+
|
18
|
+
context "when parameter" do
|
19
|
+
context "is provided" do
|
20
|
+
setup { get :index, :id => @foo.id }
|
21
|
+
should("find record") { assert_equal @foo.id, assigns(:user).id }
|
22
|
+
end # is provided
|
23
|
+
|
24
|
+
context "is not provided" do
|
25
|
+
setup { get :index }
|
26
|
+
should("not assign any record") { assert_nil assigns(:user) }
|
27
|
+
end # is not provided
|
28
|
+
|
29
|
+
context "does not match existing record" do
|
30
|
+
setup { get :index, :id => (@foo.id + 1) }
|
31
|
+
should("not assign any record") { assert_nil assigns(:user) }
|
32
|
+
end # does not match existing record
|
33
|
+
end # when parameter
|
34
|
+
|
35
|
+
def test_should_find_record_with_alternate_id_as_expected_param_key
|
36
|
+
alt = Alternate.create!(:name => 'Alternate', :alternate_id => 100)
|
37
|
+
get :index, :alternate_id => alt.alternate_id
|
38
|
+
assert_equal alt.id, assigns(:alternate).id
|
39
|
+
assert_equal alt.alternate_id, assigns(:alternate).alternate_id
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_should_find_nothing_when_alternate_id_does_not_match_record
|
43
|
+
alt = Alternate.create!(:name => 'Alternate', :alternate_id => 99)
|
44
|
+
get :index, :alternate_id => 100
|
45
|
+
assert_nil assigns(:alternate)
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_should_find_chameleon_in_user_table
|
49
|
+
get :index, :id => @foo.id
|
50
|
+
assert_equal @foo.id, assigns(:chameleon).id
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_should_not_find_chameleon_in_user_table_with_nonexistent_id
|
54
|
+
get :index, :id => (@foo.id + 1)
|
55
|
+
assert_nil assigns(:chameleon)
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_should_find_flamingo_in_user_table_even_when_class_name_is_constant
|
59
|
+
get :index, :id => @foo.id
|
60
|
+
assert_equal @foo.id, assigns(:flamingo).id
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_should_not_find_flamingo_in_user_table_when_class_name_is_constant
|
64
|
+
get :index, :id => (@foo.id + 1)
|
65
|
+
assert_nil assigns(:flamingo)
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_should_find_tucan_in_users_with_alternate_class_and_key
|
69
|
+
alt = Alternate.create!(:name => 'Alternate', :alternate_id => 100)
|
70
|
+
get :index, :alternate_id => alt.alternate_id
|
71
|
+
assert_equal alt.id, assigns(:tucan).id
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_should_not_find_tucan_in_users_with_alternate_class_and_key
|
75
|
+
alt = Alternate.create!(:name => 'Alternate', :alternate_id => 100)
|
76
|
+
get :index, :alternate_id => (alt.alternate_id + 1)
|
77
|
+
assert_nil assigns(:tucan)
|
78
|
+
end
|
79
|
+
|
80
|
+
def test_should_not_find_record_if_key_value_is_not_an_integer
|
81
|
+
get :index, :id => 'abc'
|
82
|
+
assert_nil assigns(:user)
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
2
|
+
require File.dirname(__FILE__) + '/controller_helper'
|
3
|
+
|
4
|
+
class RequireModelControllerTest < Test::Unit::TestCase
|
5
|
+
|
6
|
+
def setup
|
7
|
+
super
|
8
|
+
@request = ActionController::TestRequest.new
|
9
|
+
@response = ActionController::TestResponse.new
|
10
|
+
@controller = RequireModelController.new
|
11
|
+
@foo = User.create!(:name => 'Foo')
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_should_find_record_if_required_to_find_record_and_record_is_found
|
15
|
+
get :index, :id => @foo.id
|
16
|
+
assert_equal @foo.id, assigns(:user).id
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_should_not_require_value_if_required_is_nil
|
20
|
+
get :new, :id => @foo.id
|
21
|
+
assert_equal @foo.id, assigns(:user).id
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_should_not_require_value_if_required_is_for_different_action
|
25
|
+
fuzz = Fuzzle.create!(:name => 'Fuzzy', :fuzzle_id => 200)
|
26
|
+
get :new, :id => @foo.id, :fuzzle_id => fuzz.id
|
27
|
+
assert_equal @foo.id, assigns(:user).id
|
28
|
+
assert_nil assigns(:stuser)
|
29
|
+
assert_nil assigns(:fuzzle)
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_should_raise_error_if_required_is_scoped_and_record_not_found
|
33
|
+
fuzz = Fuzzle.create!(:name => 'Fuzzy', :fuzzle_id => 200)
|
34
|
+
assert_raise(ThumbleMonks::LoadModel::RequiredRecordNotFound) do
|
35
|
+
get :newer, :id => @foo.id, :fuzzle_id => (fuzz.id + 1)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_should_raise_error_if_required_is_true_and_record_not_found
|
40
|
+
assert_raise(ThumbleMonks::LoadModel::RequiredRecordNotFound) do
|
41
|
+
get :new, :id => (@foo.id + 1)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
2
|
+
|
3
|
+
class RestrictOptionsControllerTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
super
|
7
|
+
@request = ActionController::TestRequest.new
|
8
|
+
@response = ActionController::TestResponse.new
|
9
|
+
@controller = RestrictOptionsController.new
|
10
|
+
@foo = User.create!(:name => 'Foo')
|
11
|
+
@alt = Alternate.create!(:name => 'Bar', :alternate_id => 100)
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_should_load_user_for_index
|
15
|
+
get :index, :id => @foo.id, :alternate_id => @alt.id
|
16
|
+
assert_equal @foo.id, assigns(:user).id
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_should_not_load_alternate_for_index
|
20
|
+
get :index, :id => @foo.id, :alternate_id => @alt.alternate_id
|
21
|
+
assert_nil assigns(:alternate)
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_should_load_alternate_for_show
|
25
|
+
get :show, :id => @foo.id, :alternate_id => @alt.alternate_id
|
26
|
+
assert_equal @alt, assigns(:alternate)
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_should_not_load_user_for_show
|
30
|
+
get :show, :id => @foo.id, :alternate_id => @alt.alternate_id
|
31
|
+
assert_nil assigns(:user)
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
2
|
+
require File.dirname(__FILE__) + '/controller_helper'
|
3
|
+
|
4
|
+
class StringKeyLoadModelTest < Test::Unit::TestCase
|
5
|
+
|
6
|
+
def setup
|
7
|
+
super
|
8
|
+
@request = ActionController::TestRequest.new
|
9
|
+
@response = ActionController::TestResponse.new
|
10
|
+
@controller = StringKeyController.new
|
11
|
+
@foo = User.create!(:name => 'Foo')
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_should_find_record_and_assign_to_instance_variable_if_param_provided
|
15
|
+
get :index, :id => @foo.id
|
16
|
+
assert_equal @foo.id, assigns(:user).id
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_should_return_nil_if_expected_param_not_provided
|
20
|
+
get :index
|
21
|
+
assert_nil assigns(:user)
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_should_return_nil_if_expected_param_does_not_match_record
|
25
|
+
get :index, :id => (@foo.id + 1) # Should not belong to an existing user
|
26
|
+
assert_nil assigns(:user)
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_should_find_record_with_alternate_id_as_expected_param_key
|
30
|
+
alt = Alternate.create!(:name => 'Alternate', :alternate_id => 100)
|
31
|
+
get :index, :alternate_id => alt.alternate_id
|
32
|
+
assert_equal alt.id, assigns(:alternate).id
|
33
|
+
assert_equal alt.alternate_id, assigns(:alternate).alternate_id
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_should_find_nothing_when_alternate_id_does_not_match_record
|
37
|
+
alt = Alternate.create!(:name => 'Alternate', :alternate_id => 99)
|
38
|
+
get :index, :alternate_id => 100
|
39
|
+
assert_nil assigns(:alternate)
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_should_find_chameleon_in_user_table
|
43
|
+
get :index, :id => @foo.id
|
44
|
+
assert_equal @foo.id, assigns(:chameleon).id
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_should_not_find_chameleon_in_user_table_with_nonexistent_id
|
48
|
+
get :index, :id => (@foo.id + 1)
|
49
|
+
assert_nil assigns(:chameleon)
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
2
|
+
require File.dirname(__FILE__) + '/controller_helper'
|
3
|
+
|
4
|
+
class ThroughControllerTest < Test::Unit::TestCase
|
5
|
+
def setup
|
6
|
+
super
|
7
|
+
@request = ActionController::TestRequest.new
|
8
|
+
@response = ActionController::TestResponse.new
|
9
|
+
@controller = ThroughController.new
|
10
|
+
@user = User.create!(:name => 'Foo')
|
11
|
+
@post = @user.posts.create!(:name => 'Foo post')
|
12
|
+
end
|
13
|
+
|
14
|
+
context "index with valid ids" do
|
15
|
+
setup do
|
16
|
+
get :index, :user_id => @user.id, :id => @post.id
|
17
|
+
end
|
18
|
+
|
19
|
+
should_assign_to :user, :equals => "@user"
|
20
|
+
should_assign_to :post, :equals => "@post"
|
21
|
+
end # with valid ids
|
22
|
+
|
23
|
+
context "show_unpublished with valid id" do
|
24
|
+
setup do
|
25
|
+
@unpublished_post = @user.posts.create!{ |p| p.published = false }
|
26
|
+
get :show_unpublished, :user_id => @user.id, :id => @unpublished_post.id
|
27
|
+
end
|
28
|
+
|
29
|
+
should_assign_to :user, :equals => "@user"
|
30
|
+
should_assign_to :post, :equals => "@post"
|
31
|
+
end
|
32
|
+
|
33
|
+
context "index with invalid post id" do
|
34
|
+
setup do
|
35
|
+
get :index, :user_id => @user.id, :id => -1
|
36
|
+
end
|
37
|
+
|
38
|
+
should_assign_to :user, :equals => "@user"
|
39
|
+
should_not_assign_to :post
|
40
|
+
end # with invalid post id
|
41
|
+
|
42
|
+
context "show with alternative post via weird_id" do
|
43
|
+
context "has exisiting records" do
|
44
|
+
setup do
|
45
|
+
get :show, :user_id => @user.id, :weird_id => @post.id
|
46
|
+
end
|
47
|
+
|
48
|
+
should_assign_to :user, :equals => "@user"
|
49
|
+
should_assign_to :post, :equals => "@post"
|
50
|
+
end # has existing records
|
51
|
+
|
52
|
+
context "has nonexistent records for required action" do
|
53
|
+
should "flail with exception" do
|
54
|
+
assert_raise(ThumbleMonks::LoadModel::RequiredRecordNotFound) do
|
55
|
+
get :show, :user_id => @user.id, :weird_id => -1
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end # has nonexistant records for required action
|
59
|
+
end # show with alternative post via weird_id
|
60
|
+
|
61
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
ENV["RAILS_ENV"] = "test"
|
2
|
+
ENV["RAILS_ROOT"] = File.expand_path(File.join(File.dirname(__FILE__), '..', 'rails'))
|
3
|
+
require File.expand_path(File.join(ENV["RAILS_ROOT"], 'config', 'environment'))
|
4
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'load_model'))
|
5
|
+
require 'test_help'
|
6
|
+
load(File.dirname(__FILE__) + "/../rails/db/schema.rb")
|
7
|
+
|
8
|
+
class User < ActiveRecord::Base
|
9
|
+
has_many :posts, :conditions => {:published => true}
|
10
|
+
has_many :unpublished_posts, :conditions => {:published => false}, :class_name => 'Post'
|
11
|
+
end
|
12
|
+
class Post < ActiveRecord::Base
|
13
|
+
belongs_to :user
|
14
|
+
end
|
15
|
+
class Alternate < ActiveRecord::Base; end
|
16
|
+
class Fuzzle < ActiveRecord::Base; end
|
17
|
+
|
18
|
+
class Test::Unit::TestCase
|
19
|
+
def teardown
|
20
|
+
Fuzzle.delete_all
|
21
|
+
Alternate.delete_all
|
22
|
+
Post.delete_all
|
23
|
+
User.delete_all
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
require File.dirname(__FILE__) + '/functional/controller_helper'
|
metadata
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: thumblemonks-load_model
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Justin Knowlden
|
8
|
+
- Gabriel Gironda
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2009-01-03 00:00:00 -08:00
|
14
|
+
default_executable:
|
15
|
+
dependencies: []
|
16
|
+
|
17
|
+
description: Rails Controller plugin that provides easy and useful macros for tying models and requests together
|
18
|
+
email:
|
19
|
+
- gus@gusg.us
|
20
|
+
- gabriel.gironda@gmail.com
|
21
|
+
executables: []
|
22
|
+
|
23
|
+
extensions: []
|
24
|
+
|
25
|
+
extra_rdoc_files:
|
26
|
+
- HISTORY.markdown
|
27
|
+
- README.markdown
|
28
|
+
files:
|
29
|
+
- HISTORY.markdown
|
30
|
+
- MIT-LICENSE
|
31
|
+
- README.markdown
|
32
|
+
- Rakefile
|
33
|
+
- lib/load_model.rb
|
34
|
+
- load_model.gemspec
|
35
|
+
has_rdoc: true
|
36
|
+
homepage: http://github.com/thumblemonks/load_model
|
37
|
+
post_install_message: Choosy prima donnas choose Thumble Monks
|
38
|
+
rdoc_options:
|
39
|
+
- --line-numbers
|
40
|
+
- --inline-source
|
41
|
+
- --title
|
42
|
+
- Load Model
|
43
|
+
- --main
|
44
|
+
- README.markdown
|
45
|
+
require_paths:
|
46
|
+
- lib
|
47
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
48
|
+
requirements:
|
49
|
+
- - ">="
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
version: "0"
|
52
|
+
version:
|
53
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: "1.2"
|
58
|
+
version:
|
59
|
+
requirements: []
|
60
|
+
|
61
|
+
rubyforge_project: load_model
|
62
|
+
rubygems_version: 1.2.0
|
63
|
+
signing_key:
|
64
|
+
specification_version: 2
|
65
|
+
summary: Rails Controller plugin that provides easy and useful macros for tying models and requests together
|
66
|
+
test_files:
|
67
|
+
- rails/app/controllers/application.rb
|
68
|
+
- rails/config/boot.rb
|
69
|
+
- rails/config/database.yml
|
70
|
+
- rails/config/environment.rb
|
71
|
+
- rails/config/environments/test.rb
|
72
|
+
- rails/config/routes.rb
|
73
|
+
- rails/db/schema.rb
|
74
|
+
- rails/db/test.db
|
75
|
+
- rails/log/test.log
|
76
|
+
- test/functional/controller_helper.rb
|
77
|
+
- test/functional/keys_controller_test.rb
|
78
|
+
- test/functional/load_model_test.rb
|
79
|
+
- test/functional/require_model_controller_test.rb
|
80
|
+
- test/functional/restrict_options_controller_test.rb
|
81
|
+
- test/functional/string_key_load_model_test.rb
|
82
|
+
- test/functional/through_controller_test.rb
|
83
|
+
- test/test_helper.rb
|