problem with redirection in a grails in a controller.
in Controller:
def function1 = {
... do stuff ...
... go to service ...
redirect(action: "searchName", name: test)
//redirect(action: "searchName", params: [ name: test ])
}
in searchName, there are no parameters. its an empty list.
try the second way of calling the redirect and i get grails exceions (MissingMethodException), for a method that does exist.
there is nothing special that i can see, that is going on.
any help?
EDIT
the MissingMethodException is not on the searchName function, but on a method within the service. this method is there.
if i use the first redirect method, then the service method works correctly, but the redirect to searchName contains empty parameters.
if i switch the redirect method, then the service method no longer works
(with the exception, so it never gets to the redirect). with fully recompiled/cleaned code.
also, searchName is a closure. again, nothing fancy.
grab the name parameter, and work with it.
class MyWierdController {
def function1 = {
... do stuff ...
... go to service ...
String test="blah"
redirect(action: "searchName", name: test)
}
def searchName = {
if (params.name) {
log.info "its there"
} else {
log.info "its not there"
}
}
}
redirect() is a real HTTP redirect. You will have issues, because all your params will be serialized an deserialized and probably you are losing type information (e.g. Date, which will be string after the redirect.
The first version will ignore name parameter, since all parameters have to be within params.
Try
redirect(action: "searchName", params: ["name": "test"]);
// or
redirect(action: "searchName", params: params);
Since you did not quoted the parameters, groovy expects them to be a variable and tries to resolve them. Since both are undefined it is becoming params: [null: null].
However I guess, that you are searching for render(view: "searchName", params: ["name": "test"]), which will not do a HTTP redirect.
Related
I am unfortunately running an application on Rails 2.3.18 and am seeing strange behavior with the params variable within the controllers. There are some areas of the app that (for some reason) assign params to itself or an empty hash by default.
params = (params || {})
Now the params variable is initialized to be the request parameters so it should evaluate to true in a logical expression. However, in this case params gets set to {}. Why exactly is this happening?
I don't have a Rails 2.3 app to play around with but params in a controller is actually method but saying params = ... creates a local variable that shadows the standard params method. For example, try this in irb:
def x
puts 'x is being called'
{ :where_is => 'pancakes house?' }
end
x = x || { }
and you'll see that x is { } and the x method never even gets called. The code that says:
params = (params || {})
is effectively doing this:
params = nil # Declare a local variable and initialize it to nil
params = params || { }
# -------^^^^^^ the local variable above, not the method
However, if you force the RHS params to be a method call:
params = params() || { }
# -------------^^
then it should call the method but you'll still have the local params variable on the LHS of the assignment.
I think you need to figure out why the code is doing params = params || { } and refactor it so that it isn't necessary. Are these controller methods trying to work when they're not actually in a controller? Are they depending on dodgy edge cases in older versions of Ruby? Was that code added cargo-cult style by someone copying mystery code from a blog they didn't understand?
I have recently started to learn Ruby on Rails and it is really weird to get used to the syntax of Ruby.
I decided to go with all the parenthesis (that I know from other languages) that can be placed and I got stuck:
test "invalid signup information" do
get signup_path
assert_no_difference("User.count", {
user_params = { user: {
name: "",
email: "foo#invalid",
password: "foo",
password_confirmation: "bar"
}}
post(user_path, {params: user_params})
})
end
I want to pass a block into the assert_no_difference and somehow it is showing me an error during my tests. It started to show it after I places the definition of user_params. As far as I read some websites the syntax is OK, so what might be going wrong?
There's two general forms for passing in blocks. The long-form way is to use do ... end:
assert_no_difference('User.count') do
# ...
end
There's also the curly brace version:
assert_no_difference('User.count') {
# ...
}
Note that the curly brace style is generally reserved for single line operations, like this:
assert_no_difference('User.count') { post(...) }
For multi-line you generally want to use do...end since it's easier to spot. The When in Rome principle applies here, so you may need to shed some of your expectations in order to do things the Ruby way.
What you're doing wrong is passing in an argument that's presumed to be a Hash, but as it contains arbitrary code that's invalid. Unlike JavaScript the block is defined outside of the arguments to function call.
Cleaning up your code yields this:
test "invalid signup information" do
get signup_path
assert_no_difference("User.count") do
post(user_path,
params: {
user: {
name: "",
email: "foo#invalid",
password: "foo",
password_confirmation: "bar"
}
}
)
end
end
Note you can supply the arguments inline, plus any hash-style arguments specified as the last argument in a method call does not need its curly braces, they're strictly optional and usually best omitted.
I'm looking to reuse controllers while maintaining pretty links for different resources.
Let's say there are articles, users and comments in the system.
Comments controller index action takes a hash parameter named filter_params and does the filtering. So if params[:filter_params][:user_id] has value 1, it will display all comments by user with ID 1. Similarly with articles and article_id.
What I'm looking for is to have the following routes work:
/users/1/comments, to comments#index, params { filter_params: { user_id: 1 } }
/articles/1/comments, to comments#index, params { filter_params: { article_id: 1 } }
/articles/1/comments?filter_params[user_id]=1, to comments#index, params { filter_params: { article_id: 1, user_id: 1 } }
My initial idea was to use defaults option for routes and construct the default filter_params there. But that seems to accept only a static hash instead of a proc where I could access the request. And on top of that, it would not work with 3rd example, since defaults can't get overwritten and subsequently ?filter_params[user_id]=1 would get ignored.
So is there a way to make it work with only the router? Or should I give up and create a before_filter in CommentsController that stuffs params[:user_id] and params[:article_id] into params[:filter_params]?
I'm doing integration tests for controllers in grails.I need to pass query string in test case and I'm passing it as controller.request.queryString for the same.
My tests is getting failed. It's giving me null value for the query String parameter.
Controller - UserExController
Foll is the action on which i'm doing integration testing.In this I'm reading query string parameter 'uid' and getting the userInstance using GORM method
def getUser() {
//reading the query string parameter 'uid'
def userId = request.getParameter("uid")
User user = User.findByUsername(userId)
render view:'edit', model:[userInstance:user]
}
This is the test for the above written action .In this I'm passing the query string parameter and calling the action
class UserInstanceTests extends GroovyTestCase {
#Test
void testPerfSummaryApi() {
def userExController=new UserExController()
userExController.request.queryString='uid=rp123'
userExController.getUser()
def model = userExController.modelAndView.model.userInstance
assertNotNull model
}
}
I'm getting groovy.lang.MissingMethod.Exception in the foll call:
User.findByUsername(userId) //userId is comming null
Change in Controller:
def userId = request.getParameter("uid")
to
def userId = params.uid
Change in int test:
userExController.request.queryString='uid=rp123'
to
userExController.params.uid='rp123'
Grails' dynamic binding helps in binding the query parameters to params and request to request in the controller.
This should make things work for you (tested on Grails 2.0.4):
userExController.request.addParameter('uid', 'rp123')
However, I would recommend to turn to dmahapatro's suggestion and refactor your controller to use params.uid instead of request.getParameter("uid"). Or even introduce a command object. The way you are doing it now just does not seem to be the standard Grails way.
I've got myself a little stuck trying to get a quick bit of HTTP Digest authentication up and running, pretty much like suggested within the guide:
Ruby on Rails Guides: Action Controller Overview > HTTP Digest Authentication
class ApplicationController < ActionController::Base
protect_from_forgery
USERS = { "sam" => "ruby" }
before_filter :authenticate
private
def authenticate
authenticate_or_request_with_http_digest do |username|
USERS[username]
end
end
end
I get prompted for a username and password although when inputting the above the authentication seems to fail and I get prompted again. So I started to dig into the code that validates the request here:
GitHub: http_authentication.rb > validate_digest_response
def validate_digest_response(request, realm, &password_procedure)
secret_key = secret_token(request)
credentials = decode_credentials_header(request)
valid_nonce = validate_nonce(secret_key, request, credentials[:nonce])
if valid_nonce && realm == credentials[:realm] && opaque(secret_key) == credentials[:opaque]
password = password_procedure.call(credentials[:username])
return false unless password
method = request.env['rack.methodoverride.original_method'] || request.env['REQUEST_METHOD']
uri = credentials[:uri][0,1] == '/' ? request.fullpath : request.url
[true, false].any? do |password_is_ha1|
expected = expected_response(method, uri, credentials, password, password_is_ha1)
expected == credentials[:response]
end
end
end
I can't see how it is handling the password as plain text. How is password_is_ha1 being set? I'm also a little confused on how any? block is working which might not be helping :-/
Just as quick note: I know that I shouldn't really be storing passwords in plain text, and in source code like this. I'm just trying to build up an understanding and will refactor this later.
A massive thanks for all your help in advance :-D
The any? method acts like collect, except it returns true the first time its block returns true. Here, it acts like a loop over the array [true, false]:
The block is first run with password_is_ha1 set to true. If the block returns true, any? immediately returns true, and since this is the last statement of validate_digest_response, the method as a whole returns true.
Otherwise, the block is run again with password_is_ha1 set to false. If the block returns true, any? immediately returns true, and since this is the last statement of validate_digest_response, the method as a whole returns true.
If neither of those runs returned true, any? returns false. Since this is the last statement of validate_digest_response, the method as a whole returns false.
Thus, the effect of that line is to first assume it's a hashed password and check if it's valid, then assume it's a plaintext password and check if it's valid. Another, more verbose, way to write it would have been:
expected = expected_response(method, uri, credentials, password, true)
return true if expected == credentials[:response]
expected = expected_response(method, uri, credentials, password, false)
return true if expected == credentials[:response]
return false