Rails 3 Route error - "No Route Matches" - ruby-on-rails-3

I've been reading over this resource as well as this post to try to understand Routes more (currently learning programming/Rails by doing) but am wondering how I can fix the error I'm getting, which is No route matches {:controller=>"profiles", :action=>"show"}.
I get the error working my way through a Rails 3 sign-up process using nested model forms. The sign-up process, as follows:
user = User.new
user.email = ""
user.password = ""
user.profile = Profile.new
user.profile.save
user.save
The sign-up process starts at the homepage with the following form:
<%= form_for :user, :url => signup_path, :html => {:id => 'homepage'} do |f| %>
<div>
...
</div>
<%= f.fields_for :profile do |f| %>
<% end %>
<% end %>
Then the process goes to fill in the profile, then redirect to the new User's profile after this form is completed:
<%= form_for :profile, :html => { :multipart => true } do |f| %>
<div>
...
</div>
<%= f.fields_for :user do |f| %>
<% end %>
<% end %>
I have accepts_nested_attributes_for :user and :profile in their respective models.
My rails server it gives me a bit more detail:
ActionController::RoutingError (No route matches {:controller=>"profile.save", :action=>"show"}):
app/controllers/profiles_controller.rb:15:in `create'
So in my ProfilesController in 'create':
def create
#profile = Profile.new(params[:profile])
if #profile.save
redirect_to profile_path, :notice => 'User successfully added.'
else
render :action => 'new'
end
end
Seems clear that the issue is in profile_path, so my Routes.rb:
post "/signup" => "profiles#create", :as => "signup"
match "skip/signup", :to => "info#signupskip"
match "skip/profiles/new", :to => "profiles#newskip"
root :to => "users#create"
Can anyone help shed light on what I'm doing wrong/missing in my Routes.rb file?

The redirect path should contain the specific profile to redirect to:
if #profile.save
redirect_to profile_path(#profile), :notice => 'User successfully added.'
else
.....
Also the routes should include this line:
get "/profiles/:id" => "profiles#show", as => "profile"

Related

Rails 3 Devise customization

I have an app that uses 2 type of roles: users and admins. For the users I have overwritten both the RegistrationController and PasswordsController but after adding the PasswordsController the login page for the admin(different from the user, which is custom) gives the following routing error:
Routing Error
No route matches {:action=>"create", :controller=>"password_resets", :locale=>:admin}
this is my routes.rb file:
AppName::Application.routes.draw do
devise_for :admin
namespace :backend do
root :to => "home#index"
resources :exchanges, :except => :show
resources :prices, :except => :show
resources :offers
resources :newss
resources :users, :except => :show
scope ':locale', :locale => /en|ro/ do
namespace :profile do
root :to => 'home#index'
resources :orders do
resources :items
end
end
devise_for :users, :skip => [:sessions, :registrations, :passwords]
devise_scope :user do
get 'logare' => 'registrations#logare', :as => :new_user_session
post 'logare' => 'devise/sessions#create', :as => :user_session
delete 'index' => 'devise/sessions#destroy', :as => :destroy_user_session
get 'inregistrare' => 'registrations#new', :as => :new_user_registration
post 'inregistrare' => 'registrations#create', :as => :user_registration
get 'get_city_list' => 'registrations#get_city_list', :as => :get_city_list
get 'edit' => 'registrations#edit', :as => :user_edit
post 'edit' => 'registrations#update', :as => :user_update
get 'new_password' => 'password_resets#new', :as => :password_reset
post 'new_password' => 'password_resets#create', :as => :new_password
get 'edit_password' => 'password_resets#edit', :as => :edit_password_reset
post 'edit_password' => 'password_resets#update', :as => :update_password
end
end
match '/:locale' => 'home#index'
root :to => 'Home#index'
match '*a', :to => 'errors#routing'
end
but as I was saying, this url /admin/sign_in gives the routing error mentioned.
Dunno what I'm missing. If I remove the PasswordsController, it all works again.
PS: here is the PasswordResetsController:
class PasswordResetsController < ApplicationController
def new
end
def create
user = User.find_by_email(params[:email])
user.send_password_reset if user
redirect_to new_user_session_path, :notice => t('password_reset_notice')
end
def edit
#user = User.find_by_reset_password_token!(params[:reset_token])
end
def update
#errors_user = nil
#user = User.find_by_reset_password_token!(params[:token])
if #user
if #user.reset_password_sent_at < 2.hours.ago
redirect_to password_reset_path, :alert => t('password_expired')
else
#user.password = params[:user][:password]
#user.password_confirmation = params[:user][:password_confirmation]
unless #user.save
#errors_user = #user.errors.full_messages.join(';<br/>') + '.'
end
unless #errors_user.nil?
#reset_token = params[:token]
render :edit
else
redirect_to new_user_session_path, :notice => t('password_change_success')
end
end
end
end
end
my login form (for users, for admin I use the standard devise one):
<div class='signin-container'>
<%= form_for(:user, :url => user_session_path(#user)) do |f| %>
<%= f.label :email, 'Email:', :id => 'username_label', :class => 'general-signin' %>
<%= f.text_field :email, :id => 'username-field', :class => 'general-signin' %>
<%= f.label :password, t('inregistrare.parola'), :id => 'pass_label', :class => 'general-signin' %>
<%= f.password_field :password, :size => 23, :id => 'pass-field', :class => 'general-signin' %>
<%= f.check_box :remember_me, :id => 'remember' %>
<%= f.label :remember_me, :id => 'remember-label' %>
<%= f.submit "", :class => 'general-signin', :id => 'buton-signin' %>
<% end %>
<a href=<%= new_user_registration_path %>><span class='creeaza'><%= t('logare.creeaza') %></span></a>
<a href=<%= password_reset_path %>><span class='forgot-pass'><%= t('forgot_password') %></span></a>
</div>
figured it out ... had to generate the devise views and edit shared/_links.erb
<%= link_to "Forgot your password?", new_password_path(resource_name) %><br />
became
<%= link_to "Forgot your password?", new_password_path(:locale => I18n.locale) %><br />

uninitialized constant ConfirmationsController error while trying to overide devise confirmations controller

am trying to confirm a user account without using the built in devise confirmations controller but i happen to get the following error "uninitialized constant Confirmations Controller". Below is my confirmations controller class.
class ConfirmationsController < Devise::ConfirmationsController
def show
#user = User.find_by_confirmation_token(params[:confirmation_token])
if !#user.present?
render_with_scope :new
end
end
def confirm_account
#user = User.find(params[:user][:confirmation_token])
if #user.update_attributes(params[:user]) and #user.has_password?
#user = User.confirm_by_token(#user.confirmation_token)
flash[:notice] = "Hi " + #user.first_name + " your email has been verified. You can now start shopping and recommending other users to your supplier networks."
redirect_to #user
else
render :action => "show"
end
end
end
And in my routes.rb file i have the following:
devise_for :users, :controllers => { :confirmations => "confirmations" } do
match "confirm_account", :to => "confirmations#confirm_account"
end
And finally i have the following partial:
<p>Welcome <%= #user.first_name %>,</p><br/>
<%= form_for(resource, :url => confirm_account_path) do |f| %>
<%= f.label :email %>
<%= #user.email %>
<%= f.hidden_field :confirmation_token %>
<%= f.submit 'Confirm Account' %>
<p>Thank you for joining. Before you can purchase any item from your supplier or shared network, you will need to confirm your account first. Please follow the link below in order to confirm your account.</p>
<p><%= link_to 'Confirm my account', confirmation_url(#resource, :confirmation_token => #resource.confirmation_token) %></p><br/>
<p>Yours faithfully.</p>
<%end%>
Devise is can be easily modified for your needs. Here is a similar topic, which may be helpful for you:
Override devise registrations controller

Calling two methods from one controller in nested model form

Through other posts on SO I've learned that my sign-up process using a nested model form is flawed in that I create a new User, then redirect to create its Profile. Here is the process:
user = User.new
user.email = ...
user.password = ...
user.profile = Profile.new
user.profile.first_name = ...
...
user.profile.save
user.save
It seems as if one solution is to initiate the profile method from within the UsersController create(?) action, so that I POST to both models(?) then redirect to a page with a form to fill out the rest of the profile.
But I'm not entirely sure how to do that, as I am new to programming/Rails. So can anyone give me guidance on how to introduce the Profile method within the UsersController? I gave it a go but don't think it's correct. Code for both Users/ProfilesController below:
User:
def new
#user = User.new
#user.profile = Profile.new
end
def index
#user = User.all
end
def create
#user = User.new(params[:user])
if #user.profile.save
redirect_to profile_new_path, :notice => 'User successfully added.'
else
render :action => 'new'
end
end
Profile:
def new
#user.profile = Profile.new
end
def create
#profile = Profile.new(params[:profile])
if #profile.save
redirect_to profile_path, :notice => 'User successfully added.'
else
render :action => 'new'
end
end
Routes.rb:
match '/signup' => 'profiles#new', :as => "signup"
get "signup" => "profiles#new", :as => "signup"
root :to => 'users#new'
resources :users
resources :profiles
My nested model form (the relevant parts):
<%= form_for(:user, :url => { :action => :create }, :html => {:id => 'homepage'}) do |f| %>
<%= f.text_field :email, :size=> 13, :id => "user[email]" %>
<%= f.fields_for :profile do |f| %>
<% end%>
<% end %>
If anyone could help me I'd greatly appreciate it.
You should have something like this in your models:
class User < ActiveRecord::Base
has_one :profile
accepts_nested_attributes_for :profile
end
class Profile < ActiveRecord::Base
belongs_to :user
end
...of course all backed up with proper migrations. Then while building up a form you can use fields_for helper. Here is slightly modified example from docs:
<%= form_for #user do |user_form| %>
Email: <%= user_form.text_field :email %>
<%= user_form.fields_for :profile do |profile_fields| %>
First Name: <%= profile_fields.text_field :first_name %>
<% end %>
<% end %>
And update your user and his profile in the controller in one go, thanks to accepts_nested_attributes_for :profile declaration in your model.

Nested model form not working properly - need to pinpoint POST/GET redirect

I have a nested model form that isn't functioning properly. The POST is to the proper place, but then the GET reroutes me. So I'm wondering if anyone can help explain what I'm doing wrong.
I have two models: User and Profile. Code for them below:
User:
class User < ActiveRecord::Base
attr_accessor :password, :email
has_one :profile, :dependent => :destroy
accepts_nested_attributes_for :profile
...
end
Profile:
class Profile < ActiveRecord::Base
attr_accessible :first_name, :last_name, etc.
belongs_to :user
accepts_nested_attributes_for :user
...
end
New/Create from both models:
class UsersController < ApplicationController
def new
#user = User.new
if logged_in?
redirect_to current_user.profile
end
end
def create
#user = User.new(params[:user])
if #user.save
redirect_to signup_path, :notice => 'User successfully added.'
else
render :action => 'new'
end
end
class ProfilesController < ApplicationController
def new
#profile = Profile.new
end
def create
#profile = Profile.new(params[:profile])
if #profile.save
redirect_to profile_path, :notice => 'User successfully added.'
else
render :action => 'new'
end
end
def index
#profile = current_user.profile
end
My signup (two step process) mixes the models, so as I said I'm using a nested model form in my Users new.html.erb file. Code form_for and f.fields_for below:
<%= form_for(:user, :url => signup_path, :html => {:id => 'homepage'}) do |f| %>
<%= f.fields_for :profile do |f| %>
Now when I enter data into the form, my routes.rb file seems to POST to the proper place (/signup so profile can be filled out further), but GET routes me to /login.
Routes.rb:
match '/login' => "sessions#new", :as => "login"
match '/signup' => 'profiles#new', :as => "signup"
match 'skip/signup', :to => 'info#signupskip'
match 'skip/profiles/new', :to => 'profiles#newskip'
root :to => 'users#new'
resources :users
resources :profiles
In rails server:
Started POST "/signup" for 127.0.0.1 at Sun Aug 28 19:54:11 -0400 2011
Processing by ProfilesController#new as HTML
Started GET "/login" for 127.0.0.1 at Sun Aug 28 19:54:11 -0400 2011
Processing by SessionsController#new as HTML
Rendered sessions/new.html.erb within layouts/application (32.1ms)
I'm wondering if the problem is in my layouts/application file, specifically this code:
<% if logged_in? %>
<%= render 'layouts/header_in' %>
<% else %>
<%= render 'layouts/header_out' %>
<% end %>
Can anyone help explain to me what I'm doing wrong?
UPDATE:
I deleted the if/else argument in `layouts/application' and it was still redirected. So I'm back to wondering what's going on.
I believe your problem has to do with an inherent issue (though arguably not problem) with HTTP protocol. You cannot return a redirect to a POST request. Alternatives include calling the other method from within the first controller action, or rendering the correct page directly from that action, or some mix of both.

Remote form submission not working with namespace on Rails3

I am working on a project which allow people to upload a personal profile, including projects and updates related to their project.
Everything is working fine except that I would like to submit my form using :remote => true but i have no way to get it to work. I could use classic jquery/ajax to submit the form, but the Rails3 UJS is great !
updates_controller.rb
def create
#update = Update.new(params[:update])
#update.user_id = current_user.id
#update.project_id = params[:project_id]
if #update.save
respond_to do |format|
format.js { render :nothing => true }
end
end
end
_form.html (views)
<%= form_for([#project, #update], :url => profile_project_updates_path, :remote => true) do |f| %>
I tried also
<%= form_for([:profile, #project, #update], :remote => true) do |f| %>
routes.rb
namespace :profile do
resources :projects, :only => [:show, :index, :edit] do
resources :updates
end
end
If anyone has an idea how to get the :remote => true to work here , it will be great !!
Thanks to all the Stack Overflow community for all the precious resources I found here so far.
_Clement
Did you initialized #project in new action of controller?
Try to replace
<%= form_for([#project, #update], :url => profile_project_updates_path, :remote => true) do |f| %>
with
<%= form_for([#update.project_id, #update], :url => profile_project_updates_path, :remote => true) do |f| %>
What is the server response when you submit the form?