Skip to content

Commit 4a4b244

Browse files
committed
Clean up how we map between Rails actions and default associated template files
1 parent abc283e commit 4a4b244

File tree

3 files changed

+33
-15
lines changed

3 files changed

+33
-15
lines changed

ql/src/codeql_ruby/frameworks/ActionController.qll

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -64,20 +64,14 @@ class ActionControllerActionMethod extends Method, HTTP::Server::RequestHandler:
6464

6565
/**
6666
* Establishes a mapping between a method within the file
67-
* `<source_prefix>/app/controllers/<subpath>_controller.rb` and the
67+
* `<sourcePrefix>app/controllers/<subpath>_controller.rb` and the
6868
* corresponding template file at
69-
* `<source_prefix>/app/views/<subpath>/<method_name>.html.erb`.
69+
* `<sourcePrefix>app/views/<subpath>/<method_name>.html.erb`.
7070
*/
7171
// TODO: result should be `ErbFile`
7272
File getDefaultTemplateFile() {
73-
exists(string templatePath, string sourcePrefix, string subPath, string controllerPath |
74-
controllerPath = this.getLocation().getFile().getAbsolutePath() and
75-
sourcePrefix = controllerPath.regexpCapture("^(.*)/app/controllers/.*$", 1) and
76-
controllerPath = sourcePrefix + "/app/controllers/" + subPath + "_controller.rb" and
77-
templatePath = sourcePrefix + "/app/views/" + subPath + "/" + this.getName() + ".html.erb"
78-
|
79-
result.getAbsolutePath() = templatePath
80-
)
73+
controllerTemplatesFolder(this.getControllerClass(), result.getParentContainer()) and
74+
result.getBaseName() = this.getName() + ".html.erb"
8175
}
8276

8377
// params come from `params` method rather than a method parameter
@@ -183,13 +177,31 @@ class ActionControllerHelperMethod extends Method {
183177
/**
184178
* Gets an `ActionControllerControllerClass` associated with the given `ErbFile`
185179
* according to Rails path conventions.
180+
* For instance, a template file at `app/views/foo/bar/baz.html.erb` will be
181+
* mapped to a controller class in `app/controllers/foo/bar/baz_controller.rb`,
182+
* if such a controller class exists.
186183
*/
187184
// TODO: parameter should be `ErbFile`
188185
ActionControllerControllerClass getAssociatedControllerClass(File f) {
189-
exists(string localPrefix, string sourcePrefix, string controllerPath |
190-
controllerPath = result.getLocation().getFile().getAbsolutePath() and
191-
sourcePrefix = f.getAbsolutePath().regexpCapture("^(.*)/app/views/(?:.*?)/(?:[^/]*)$", 1) and
192-
localPrefix = f.getAbsolutePath().regexpCapture(".*/app/views/(.*?)/(?:[^/]*)$", 1) and
193-
controllerPath = sourcePrefix + "/app/controllers/" + localPrefix + "_controller.rb"
186+
controllerTemplatesFolder(result, f.getParentContainer())
187+
}
188+
189+
/**
190+
* Holds if `templatesFolder` is in the correct location to contain template
191+
* files "belonging" to the given `ActionControllerControllerClass`, according
192+
* to Rails conventions.
193+
*
194+
* In particular, this means that an action method in `cls` will by default
195+
* render a correspondingly named template file within `templatesFolder`.
196+
*/
197+
predicate controllerTemplatesFolder(ActionControllerControllerClass cls, Folder templatesFolder) {
198+
exists(string templatesPath, string sourcePrefix, string subPath, string controllerPath |
199+
controllerPath = cls.getLocation().getFile().getRelativePath() and
200+
templatesPath = templatesFolder.getRelativePath() and
201+
// `sourcePrefix` is either a prefix path ending in a slash, or empty if
202+
// the rails app is at the source root
203+
sourcePrefix = [controllerPath.regexpCapture("^(.*/)app/controllers/(?:.*?)/(?:[^/]*)$", 1), ""] and
204+
controllerPath = sourcePrefix + "app/controllers/" + subPath + "_controller.rb" and
205+
templatesPath = sourcePrefix + "app/views/" + subPath
194206
)
195207
}

ql/test/library-tests/frameworks/ActionController.expected

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,3 +55,5 @@ actionControllerHelperMethods
5555
getAssociatedControllerClasses
5656
| app/controllers/foo/bars_controller.rb:1:1:20:3 | BarsController | app/views/foo/bars/_widget.html.erb:0:0:0:0 | app/views/foo/bars/_widget.html.erb |
5757
| app/controllers/foo/bars_controller.rb:1:1:20:3 | BarsController | app/views/foo/bars/show.html.erb:0:0:0:0 | app/views/foo/bars/show.html.erb |
58+
controllerTemplatesFolders
59+
| app/controllers/foo/bars_controller.rb:1:1:20:3 | BarsController | folder://app/views/foo/bars | app/views/foo/bars |

ql/test/library-tests/frameworks/ActionController.ql

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,7 @@ query predicate actionControllerHelperMethods(ActionControllerHelperMethod m) {
1818
query predicate getAssociatedControllerClasses(ActionControllerControllerClass cls, File f) {
1919
cls = getAssociatedControllerClass(f)
2020
}
21+
22+
query predicate controllerTemplatesFolders(ActionControllerControllerClass cls, Folder f) {
23+
controllerTemplatesFolder(cls, f)
24+
}

0 commit comments

Comments
 (0)