I'm trying to make a custom edit form for devise user, but when I submit the form shell throw me this error:
No route matches [POST] "/profile/12/edit"
Here is my form:
= simple_form_for(:user), html: { method: :put }) do |f|
= f.input :email
= f.input :username
= f.input :phone
= f.input :password, autocomplete: "off", required: false
= f.input :password_confirmation, required: false
= f.input :current_password, required: true
= f.button :submit, 'Update'
Here is my profile_controller
class ProfileController < ApplicationController
def show
#client = Client.find(params[:id])
end
def edit
#user = User.find(params[:id])
end
def update
#user = User.find(params[:id])
if #user.update_attributes(params[:user])
redirect_to root_path
end
end
end
And my routes.rb :
Rails.application.routes.draw do
root 'home#index'
devise_for :users
resources :profile
end
What I'm doing wrong?
This is how I would do it:
= simple_form_for #user,
:url => url_for(:action => 'edit', :controller => 'profiles'),
:method => 'put' do |f|
Here you are submitting a PUT (update) request to the edit action of your ProfilesController.
Also notice the difference here between ProfileController and what I wrote ProfilesController. The convention in Rails and as for DHH is that your model names should be singular and your controller plural.
model
class Profile < ActiveRecord::Base
end
controller
class ProfilesController < ApplicationController
end
Replace:
= simple_form_for(:user), html: { method: :put }) do |f|
with:
= simple_form_for #user, method: :put, url: "/profile" do |f|
Some of the mistakes:
if you want to edit an object, provide it, not a mere symbol
the path must be adjusted to point to /profile
method not an html property, it creates a hidden field intercepted by rails in order to know the received post should be understood as a put
we feel like there is a typo: controller should be pluralized
Related
I have a problem in my contact form_for,
I have one contact form and I want to render my contact form in my product view.
If I make that I have a problem with my require params
My contact_params work in my ContactController:
def contact_params
params.require(:contact).permit(:name, :email, :body)
end
I have add in my ApplicationController
def set_contact
#contact = Contact.new params[:contact] || {}
end
and that in my ProductsControler
show
#contact = :set_contact
end
my route are:
get 'contact', to: 'contacts#new', as: 'new_contact'
post 'contact', to: 'contacts#create', as: 'create_contact'
my render is same that:
<%= render :partial => "contacts/contact" %>
and my view in _contact.html.erb:
<%= form_for #contact, url: create_contact_url do |f| %>
<%= f.text_field :name %>
<%= f.email_field :email %>
<%= f.text_area :body %>
<%= f.submit 'Send' %>
Rails say me:
ActionController::ParameterMissing (param is missing or the value is empty: contact):
If I delete require(:contact) that not work rails say me:
Unpermitted parameter: :contact
Thanks
You have typo in method #show of ProductsControler #contact = :set_contact, you should call method set_contact without :
Right code: #contact = set_contact
Try to merge Params with product params
params[:product].merge!(:contact)
e.g
def company_params
params[:company].merge!(users_attributes: {'0': user_params.to_h })
params.require(:company).permit(
:name, :contact_person_name, :email,
:contact_person_number, :terms_and_conditions )
end
Hear users_attributes is from my other form.
Works for me.
Good luck.
I've created a contact form in Rails 4 with this example.
But I want to display this contact form on the main/show page of my application. How can I do this?
routes.rb.
Rails.application.routes.draw do
resources :projects
resources :contacts, only: [:new, :create]
get 'welcome/index'
root 'welcome#index'
end
contacts_controller.rb
class ContactsController < ApplicationController
def new
#contact = Contact.new
end
def create
#contact = Contact.new(params[:contact])
#contact.request = request
if #contact.deliver
flash.now[:error] = nil
else
flash.now[:error] = 'Cannot send message.'
render :new
end
end
end
Thanks.
And easy and clean way would be to create a partial
_contact_form.html.erb (Partials always starts with an underscore)
.container
%h1 Contact
= simple_form_for #contact, :html => {:class => 'form-horizontal' } do |f|
= f.input :name, :required => true
= f.input :email, :required => true
= f.input :message, :as => :text, :required => false, :input_html => {:rows => 10}
.hidden
= f.input :nickname, :hint => 'Leave this field blank!'
.form-actions
= f.button :submit, 'Send message', :class=> "btn btn-primary"
Then, in your index page:
<%= render "contacts/contact_form" %>
and in your controller index action( I don't know if 'welcome/index' is on project's controller or contacts controller)
def index
#your code
#contact = Contact.new
end
Finally, you seem quite new to rails, I'd like to recommend a free Ruby on Rails Tutorial
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!
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