Devise : /login with param giving `undefined method stringify_keys` - ruby

For /login my application is working fine, but for /login?user="something" giving 500
I am using devise gem
routes.rb
devise_for :users, :controllers => { :sessions => 'devise/sessions'}, :skip => [:sessions] do
get '/login' => "devise/sessions#new", :as => :new_user_session
end
error :
Completed 500 Internal Server Error in 263ms
NoMethodError (undefined method `stringify_keys' for "\"something\"":String):
Rendered /usr/local/rvm/gems/ruby-1.9.2-head/gems/actionpack-3.1.0/lib/action_dispatch/middleware/templates/rescues/_trace.erb (2.6ms)
Rendered /usr/local/rvm/gems/ruby-1.9.2-head/gems/actionpack-3.1.0/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (1.7ms)
Rendered /usr/local/rvm/gems/ruby-1.9.2-head/gems/actionpack-3.1.0/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (7.9ms)

stringify_keys is a method that Rails mixes into the Ruby Hash class, so the problem here is that devise is expecting a hash of attribute-value pairs in the user param instead of a plain string. In other words its expecting a User model object rather than just a user name.
The convention that Rails uses for packing nested attribute value pairs into URL query string or HTML form params uses square brackets, so you probably need something like this:
/login?user[name]=someone&user[password]=secret

Related

Devise not saving custom controller 'update' action for Array attribute

I've got two devise models - User and Agent - so I've got custom controllers for each.
In the Agent controller, when updating the Agent, I'm trying to pass in user_ids, which is an Array:
def account_update_params
params["agent"]["user_ids"] = params["agent"]["user_ids"].split(",")
params.require(:agent).permit(:email, :password, :password_confirmation, :current_password, {:user_ids => [:id]})
end
Before I added [:id] to user_ids, I was receiving an 'unpermitted parameter' error message. Adding [:id] solved that issue, but now my issue is that the record is not saving at all, and user_ids remains as nil.
It is being passed in the parameters though, as you can see here:
"agent"=>{"user_ids"=>"3", "email"=>"test_agent#example.com", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]", "current_password"=>"[FILTERED]"}

Rails access request in routes.rb for dynamic routes

Our websites should allow to show different contents related to the given url .. something like a multisite in wordpress where we have one installation and serve the content according to the url.
as it is necessary to have the routes in the correct language I want to use a "dynamic route" approach to serve the right content. My problem is now that I dont find a way how to serve the proper routes in routes.rb if they are dynamic.
How can I "access" or "pass" the request object into any method inside the routes.rb file
f.e. like this
routes.rb
Frontend::Application.routes.draw do
DynamicRouter.load request
end
app/models/dynamic_router.rb
class DynamicRouter
def self.load request
current_site = Site.find_by_host(request.host)
Frontend::Application.routes.draw do
current_site.routes do |route|
get "#{route.match}", to: "#{route.to}"
end
end
end
end
this doesnt work because request is undefined in routes.rb
To answer your question: How can I "access" or "pass" the request object into any method inside the routes.rb file Obtain it as ENV object from rack middleware.See code below
# lib/dynamicrouterrequest.rb
require 'rack'
class DynamicRouterRequest
def initialize(app)
#app = app
end
def call(env)
request=Rack::Request.new(env)
ENV["OBJ_REQUEST"]=request.inspect.to_s
#app.call(env)
end
end
Grab it again in routes
# routes.rb
Frontend::Application.routes.draw do
request=ENV["OBJ_REQUEST"]
DynamicRouter.load request
end
A possible soluction is to create the default rules on routes.rb and add a rack middleware that can transform a path according to the domain
# routes.rb
get '/category/:id', :to => 'categories#show'
In the middleware you can transform a path like 'categoria/:id' to '/category/:id' if the domain matches '.es', before the application hits the router layer.
More on rack middleware: http://guides.rubyonrails.org/rails_on_rack.html

Figuring out rails routes, getting undefined method for my detail_path

My data of a datatable:
def data
theusers.map do |usermap|
[
h(usersmap.spriden_last_name),
h(usermap.spriden_first_name),
h(usermap.spriden_id),
link_to(usermap.gobtpac_username, detail_path(usermap.spriden_id))
]
end
end
the above code resides in app\datatables\helpdesk_datatable.rb
The above works mostly I know it is getting the data, the error I get is with the detail_path
Error on "undefined method" for detail_path... This means it is not building the router dynamically right, correct?
Or I am passing in the wrong thing I tried to pass in usermap.spriden.id and just banner user, same issue. I am really not sure how routes work apparently. I have a details_controller.rb in controllers that has a show method in it and i have the views/details/show.html.erb which will show the data that was passed into the route, at least I thought. But is it just an ID or an object? so if it just an id i have to look it up again in
the show method right? How do routes like this look? I am using devise and cancan too here is my routes file:
NmsuMyaccount::Application.routes.draw do
authenticated :user do
root :to => 'home#index'
match 'home', :to => 'home#index', :via => :get
end
#get 'show-details' => "details#show", as: 'show_details'
resources :details
devise_for :users
resources :users
# In order for an unauthorized user access this controller#action, this needs to be in a scope, but I don't know why.
devise_scope :user do
match 'home', :to => 'home#index', :via => :get
end
end
Also hitting the end point localhost:3000 is an error, I have to goto /home, although devise does work just fine. So thought I was close but for the life of me cannot get the detail_path to work, and I thought it was a plural issue so tried details, and just detail no path etc. No dice.
I don't believe that you have access to the route helpers that Rails provides inside your custom class. So you have to manually include the module inside your class. Something like:
link_to(usermap.gobtpac_username, Rails.application.routes.url_helpers.detail_path(usermap.spriden_id))
Or:
include Rails.application.routes.url_helpers
# Use it like you are using.
See here for more information about the subject:
Can Rails Routing Helpers (i.e. mymodel_path(model)) be Used in Models?

Rails 3 AJAX: wrong constant name

I am trying to do Ajax login with Devise, as explained here: http://jessehowarth.com/2011/04/27/ajax-login-with-devise#comment-5 (see comment from jBeasley).
My controller is attempting to return
class Users::SessionsController < Devise::SessionsController
def failure
render :json => {:success => false, :errors => ["Login failed."]}
end
end
which results in this error:
NameError (wrong constant name ["{\"success\":false,\"errors\":[\"Login failed.\"]}"]Controller):
and Firebug showing [500 Internal Server Error].
How can I fix this? I am running Rails 3.1 and devise 1.4.5.
Thanks!!
Did you do the step recommended by Jeff Poulton in comment #4? The :recall option in 1.4.5 looks to be completely incompatible to older versions. It now requires you send the controller, whereas in the tutorial you're following he just sends the action (the old way).
In your case, :recall => :failure must be changed to :recall => "users/sessions#failure" in Devise 1.4.5.
This is because of the way the controller for the failure action is determined. In older versions, it was simply pulled from the params.
def recall_controller
"#{params[:controller]}.camelize}Controller".constantize
end
# called via recall_controller.action(warden_options[:recall]).call(env)
In 1.4.5, it expects a string specifying the controller and action, in the style of routes:
def recall_app(app)
controller, action = app.split('#')
controller_name = ActiveSupport::Inflector.camelize(controller)
controlller_klass = ActiveSupport::Inflector.constantize("#{controller_name}Controller")
controller_klass.action(action)
end
# called via recall_app(warden_options[:recall]).call(env)
It would seem as though your app is actually passing the JSONified hash of options to recall_app, which, lacking a '#', isn't being split, and the entire string is concatenated to "Controller" to attempt to ascertain the failure controller's class.
You are missing the return in
def failure
return render:json => {:success => false, :errors => ["Login failed."]}
end
Does that make a difference?

ROR Devise: allowing username or email logins: undefined local variable

I've been following the tutorial on the Devise github page here: https://github.com/plataformatec/devise/wiki/How-To:-Allow-users-to-sign_in-using-their-username-or-email-address
I'm in the second part of the tutorial where we allow users to recover their password using either their username or email and there's a large block of code that the tutorial says to copy into the User model. This is the line that throws an error:
def self.find_record(login)
where(attributes).where(["username = :value OR email = :value", { :value => login }]).first
end
This is the error I get:
NameError (undefined local variable or method `attributes' for #<Class:0xa70e1a8>):
app/models/user.rb:63:in `find_record'
app/models/user.rb:44:in `find_recoverable_or_initialize_with_errors'
app/models/user.rb:30:in `send_reset_password_instructions'
Anyone know why this error is showing up?
You're not passing in any attributes, and there's no 'attributes' class method, so where(attributes) doesn't work. It doesn't look like you need to either. Change your method to:
def self.find_record(login)
where(["username = :value OR email = :value", { :value => login }]).first
end
For what it's worth, I don't see how it would have worked in the tutorial either.

Resources