There are similar questions but I've gone over them and none of them have applied.
I am using Devise and Devise invitations. Rails 3.2.6.
The tricky thing is I have two user models. User and a single table inheritance setup where Artist inherits from User. I have two invitations controllers to allow sending invitations separately to both Users and Artists.
The issue right now is that artists are not able to accept their invitations. Upon form submit of updating their password, they get a 406 unacceptable error.
Relevant Code:
Routing:
devise_for :users,
:class_name => User,
:controllers => { :invitations => 'user/invitations' }
namespace :artist do
# Special route for devise, artists invitation
devise_scope :user do
resource :invitation, :controller => :invitations, :only => [:create, :new, :update] do
get :accept, :action => :edit
end
end
end
Artist invitations controller
class Artist::InvitationsController < Devise::InvitationsController
respond_to :html
# PUT /resource/invitation
def update
self.resource = Artist.accept_invitation!(params[resource_name])
if resource.errors.empty?
resource.pending
flash[:notice] = "Welcome, complete your artist agreement to get started"
sign_in(:user, resource)
respond_with resource, :location => after_accept_path_for(resource)
else
respond_with_navigational(resource){ render :edit }
end
end
end
Form description. edit.html.erb.
<%= form_for resource, :as => resource_name, :url => artist_invitation_path(resource_name), :html => { :method => :put } do |f| %>
<%= f.hidden_field :invitation_token %>
<%= f.label :password, class: 'control-label' %>
<%= f.password_field :password, :placeholder => 'Enter a password' %>
<%= f.label :password_confirmation, class: 'control-label' %>
<%= f.password_field :password_confirmation, :placeholder => 'Confirm your password' %>
<%= f.submit "Set my password", :'data-disable-with' => "Hang on..." %>
<% end %>
Accept headers
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Cache-Control:max-age=0
Connection:keep-alive
Content-Length:236
Content-Type:application/x-www-form-urlencoded
Returns
Request URL:http://localhost:3000/artist/invitation.user
Request Method:POST
Status Code:406 Not Acceptable
I can see that something in the format must be off because of the response adding in that .user to the end. I can not for the life of me see why or where that is happening. Please let me know if there's any info I left out which could help.
Got it, finally.
The key is to look precisely at what resource_name is giving you throughout the form and controller actions. In my case it continued to fallback to :user when it needed to be :artist and as Frost mentioned in a comment, the generated form html changes greatly if you pay attention to where resource_name is used. The update action in the controller needed to be overridden to use :artist directly and the form_for needed to be tweaked to remove resource_name from arguments and the :as argument.
Related
routes are correct, not sure what else is off?
upon "updating" page (when it routes to update) I get the error
param is missing or the value is empty: user
This is my second custom view page for devise the other is working with similar code.
routes-
devise_for :users, controllers: {registrations: 'users/registrations'} as :user do
end
root 'home#home'
get 'users/discovery_settings' => 'users#discovery_settings'
patch 'users/discovery_settings/update' => 'users#update_discovery'
My user controller-
def update_discovery
#user = User.find(current_user.id)
if #user.update(user_params2)
# Sign in the user by passing validation in case their password changed
sign_in #user, :bypass => true
redirect_to root_path
else
render "edit"
end
end
def user_params2
# NOTE: Using `strong_parameters` gem
params.require(:user).permit(:discovery, :male, :female, :min_age, :max_age)
end
Then my views form_for calls the method
<%= form_for(#user, :url => { :action => "update_discovery" }, html: {class: "form floating-label"}) do |f| %>
Figured this out on my own and posted a blog about it, here was my answer:
Out of all the problems i've had customizing devise this one probably took the longest for me to figure out. A common error you will receive from doing this incorrectly is:
param is missing or the value is empty: user
1st step is to create a controller that inherits the devise controller (essentially overriding it). This should go inside controllers/users and be called registration_controller.rb .
Insert the following code for a secondary customer edit view-
class Users::RegistrationsController < Devise::RegistrationsController
before_filter :configure_permitted_parameters
def NAMEOFVIEW
#user = current_user
if #user
render :NAMEOFVIEW
else
render file: 'public/404', status: 404, formats: [:html]
end
end
also you'll need to sanitize any custom parameters you make in your database
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up) { |u| u.permit(:username, :email, :password, :name, :user_age, :user_gender ) }
devise_parameter_sanitizer.permit(:account_update) { |u| u.permit(:username, :email, :password, :password_confirmation, :current_password, :name, :user_age, :user_gender, :user_bio ) }
end
and finally allow updates without password (by default devise forces this)
protected
def update_resource(resource, params)
resource.update_without_password(params)
end
Under routes:
Rails.application.routes.draw do
devise_for :users, controllers: {registrations: 'users/registrations'}
as :user do
match 'users/NAMEOFVIEWHERE' => 'users/registrations#NAMEOFVIEWHERE', :via => [:get], :as => 'NAMEOFVIEWHERE'
then finally any changes in your view can be done using a form_for or a form_tag, form_for example below:
<%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put, class: " html classes here" }) do |f| %>
<div class="field">
<%= f.label :Bio %><br />
<%= f.text_area :user_bio, autocomplete: "off", class: "optional html class here", rows: 3, cols: 20, name: "description", placeholder: "About" %>
</div>
<div class="optional button class here">
<button type="submit">Save</button>
</div>
<% end %>
Now restart your rails server and cross your fingers!
routes are correct, not sure what else is off?
upon "updating" page (when it routes to update) I get the error
param is missing or the value is empty: user
This is my second custom view page for devise the other is working with similar code.
routes-
devise_for :users, controllers: {registrations: 'users/registrations'} as :user do end root 'home#home'
get 'users/discovery_settings' => 'users#discovery_settings' patch 'users/discovery_settings/update' => 'users#update_discovery'
My user controller-
def update_discovery
#user = User.find(current_user.id)
if #user.update(user_params2)
# Sign in the user by passing validation in case their password changed
sign_in #user, :bypass => true
redirect_to root_path
else
render "edit"
end
end
def user_params2
# NOTE: Using `strong_parameters` gem
params.require(:user).permit(:discovery, :male, :female, :min_age, :max_age)
end
Then my views form_for calls the method
<%= form_for(#user, :url => { :action => "update_discovery" }, html: {class: "form floating-label"}) do |f| %>
Figured this out on my own and posted a blog about it, here was my answer:
Out of all the problems i've had customizing devise this one probably took the longest for me to figure out. A common error you will receive from doing this incorrectly is:
param is missing or the value is empty: user
1st step is to create a controller that inherits the devise controller (essentially overriding it). This should go inside controllers/users and be called registration_controller.rb .
Insert the following code for a secondary customer edit view-
class Users::RegistrationsController < Devise::RegistrationsController
before_filter :configure_permitted_parameters
def NAMEOFVIEW
#user = current_user
if #user
render :NAMEOFVIEW
else
render file: 'public/404', status: 404, formats: [:html]
end
end
also you'll need to sanitize any custom parameters you make in your database
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up) { |u| u.permit(:username, :email, :password, :name, :user_age, :user_gender ) }
devise_parameter_sanitizer.permit(:account_update) { |u| u.permit(:username, :email, :password, :password_confirmation, :current_password, :name, :user_age, :user_gender, :user_bio ) }
end
and finally allow updates without password (by default devise forces this)
protected
def update_resource(resource, params)
resource.update_without_password(params)
end
Under routes:
Rails.application.routes.draw do
devise_for :users, controllers: {registrations: 'users/registrations'}
as :user do
match 'users/NAMEOFVIEWHERE' => 'users/registrations#NAMEOFVIEWHERE', :via => [:get], :as => 'NAMEOFVIEWHERE'
then finally any changes in your view can be done using a form_for or a form_tag, form_for example below:
<%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put, class: " html classes here" }) do |f| %>
<div class="field">
<%= f.label :Bio %><br />
<%= f.text_area :user_bio, autocomplete: "off", class: "optional html class here", rows: 3, cols: 20, name: "description", placeholder: "About" %>
</div>
<div class="optional button class here">
<button type="submit">Save</button>
</div>
<% end %>
Now restart your rails server and cross your fingers!
I'm trying to add edit functionality to my web app, and am having some trouble. The error page I get back when I try to complete an edit of my Request object indicates that it couldn't find the right route, but the same error page contains a list of routes which includes the route it's looking for. So I'm a bit flummoxed.
The "new" method is almost identical to this edit method and the pages are almost identical as well.
The error page begins No route matches [POST] "/requests/19/edit" and then, partway down the route listing, I see this:
requests_path GET /requests(.:format) requests#index
POST /requests(.:format) requests#create
new_request_path GET /requests/new(.:format) requests#new
edit_request_path GET /requests/:id/edit(.:format) requests#edit
request_path GET /requests/:id(.:format) requests#show
PATCH /requests/:id(.:format) requests#update
PUT /requests/:id(.:format) requests#update
DELETE /requests/:id(.:format) requests#destroy
So Rails seems to be generating a request_path which expects a PATCH, not a POST, right?
routes.rb
Rails.application.routes.draw do
root "pages#index"
resources :destinations
resources :users
resources :manifests
resources :requests
:
request.rb
class Request < ActiveRecord::Base
validates_presence_of :justification
validates_presence_of :required_by
belongs_to :user
belongs_to :manifest
belongs_to :network
has_many :uploaded_files
scope :sorted, lambda{ order("required_by") }
end
edit.html.rb
<% #page_title = "Update Request" %>
<%= link_to("<< Back to List", {:action => 'index'}, :class => 'back-link') %>
<div class="requests edit">
<h2>Update Request</h2>
<%= form_for :request, url: request_path(#request) do |f| %>
<%= render(:partial => "form", :locals => {:f => f}) %>
<div class="form-buttons">
<%= submit_tag("Update Request") %>
</div>
<% end %>
</div>
requests_controller.rb
def update
#request = Request.find(params[:id])
p = {'file' => params[:request][:uploaded_file], 'request_id' => #request.id}
uf = UploadedFile.create(p)
if #request.update_attributes(request_params)
flash[:notice] = "Request updatred succesfully"
redirect_to :action => 'show', :id => #request.id
else
render 'edit'
end
end
What have I missed?
Change
<%= form_for :request, url: request_path(#request) do |f| %>
to
<%= form_for :request, url: request_path(#request), method: :patch do |f| %>
in your edit.html.erb
form_for(as you are using it) sets POST as default HTTP verb. You need to alter it by setting method :patch which responds to the update action.
You can simplify it to just
<%= form_for #request do |f| %>
Check the APIdoc for more Info.
I'm super new to Ruby on Rails. I'm trying to make an authentication system using Authlogic (following this tutorial). The error that I'm getting is right after I submit the login form:
No route matches "/user_sessions/%23%3CUserSession:0x103486aa8%3E"
Surprisingly the URL of the page right after the form is submitted which also brings up the error is:
http://localhost:3000/user_sessions/%23%3CUserSession:0x103486aa8%3E
I have no idea what I have done wrong and where that weird UserSession code thing is coming from!!!
This is how my login form looks like:
<% form_for #user_session do |f| %>
<%= f.error_messages %>
<p>
<%= f.label :username %><br />
<%= f.text_field :username%>
</p>
<p>
<%= f.label :password %><br />
<%= f.password_field :password %>
</p>
<p><%= f.submit "Submit" %></p>
<% end %>
Here is my UserSession class:
class UserSession < Authlogic::Session::Base
def to_key
new_record? ? nil : [ self.send(self.class.primary_key) ]
end
end
and the create action of my UserSessionController:
def create
#user_session = UserSession.new(params[:user_session])
if #user_session.save
flash[:notice] = "Login successful!"
redirect_back_or_default root_path
else
render :action => :new
end
end
"redirect_back_or_default" method in ApplicationController:
def redirect_back_or_default(default)
redirect_to(session[:return_to] || default)
session[:return_to] = nil
end
And lastly everything related to user_sessions in routes.rb:
resources :user_sessions
match 'login' => "user_sessions#destroy", :as => :login
match 'logout' => "user_sessions#destroy", :as => :logout
These are the codes that I thought could be involved in getting that error. If I should add some more code to make it more clear please let me know.
Ok, first, you have a bad route:
match '/login', :to => 'user_sessions#new', :as => 'login'
note the new instead of destroy
also, the to_key is not needed in later versions - I'm using rails 3 and don't have it in my UserSession Model.
Definitely need to change your route to not match login to destroy.
Here's the route setting I have... (from "Agile Web Development with Rails" example).
controller :user_sessions do
get 'login' => :new
post 'login' => :create
delete 'logout' => :destroy
end
Right now I'm building a project management app in rails, here is some background info:
Right now i have 2 models, one is User and the other one is Client. Clients and Users have a one-to-one relationship (client -> has_one and user -> belongs_to which means that the foreign key it's in the users table)
So what I'm trying to do it's once you add a client you can actually add credentials (add an user) to that client, in order to do so all the clients are being displayed with a link next to that client's name meaning that you can actually create credentials for that client.
So in order to do that I'm using a helper the link to helper like this.
<%= link_to "Credentials",
{:controller => 'user', :action => 'new', :client_id => client.id} %>
Meaning that he url will be constructed like this:
http://localhost:3000/clients/2/user/new
By creating the user for the client with he ID of 2.
And then capturing the info into the controller like this:
#user = User.new(:client_id => params[:client_id])
EDIT: This is what i currently have in my View/Controller and Routes
I keep getting this error: No route matches "/clients//user" with {:method=>:post}
Routes
ActionController::Routing::Routes.draw do |map|
map.resources :users
map.resources :clients, :has_one => :user
map.connect ':controller/:action/:id'
map.connect ':controller/:action/:id.:format'
end
Controller
class UsersController < ApplicationController
before_filter :load_client
def new
#user = User.new
#client = Client.new
end
def load_client
#client = Client.find(params[:client_id])
end
def create
#user = User.new(params[:user])
#user.client_id = #client.id
if #user.save
flash[:notice] = "Credentials created"
render :new
else
flash[:error] = "Credentials created failed"
render :new
end
end
View
<% form_for #user, :url => client_user_url(#client) do |f| %>
<p>
<%= f.label :login, "Username" %>
<%= f.text_field :login %>
</p>
<p>
<%= f.label :password, "Password" %>
<%= f.password_field :password %>
</p>
<p>
<%= f.label :password_confirmation, "Password Confirmation" %>
<%= f.password_field :password_confirmation %>
</p>
<%= f.submit "Create", :disable_with => 'Please Wait...' %>
<% end %>
Your form tag is wrong, you are posting to /users without the :client_id.
Try this:
<% form_for #user, :url => {:controller => 'users', :action => 'new', :client_id => #client.id} do |f| >
Alternatively, you could use nested resources:
config/routes.rb
map.resources :clients do |clients|
clients.resources :users
end
Controller
class UsersController < ApplicationController
before_filter :load_client
def load_client
#client = Client.find(params[:client_id])
end
# Your stuff here
end
View
<% form_for [#client, #user] do |f| %>
I solved this by using nested attributes, by including the user model, when creating the client. And it works flawlessly.
In case any of you guys need more info here's the two screencasts that helped me come up with as solution:
http://railscasts.com/episodes/196-nested-model-form-part-1
http://railscasts.com/episodes/196-nested-model-form-part-2