nested routes and form_for and NoMethodError - ruby-on-rails

As the error message stated below, I do not use "user_profiles_path" as plural because I defined "resource :profile" in nested resource.
NoMethodError in Profiles#new
Showing /home/smileymike/rails_projects/bffmapp_v2/app/views/profiles/new.html.erb where line #20 raised:
undefined method `user_profiles_path' for #<#<Class:0x90266ac>:0xa041294>
Model:
class User < ActiveRecord::Base
has_one :profile
class Profile < ActiveRecord::Base
attr_accessible :name, :surname
belongs_to :user
routes.rb:
resources :users do
resource :profile (note: has_one)
end
view: profiles/new.html.erb
<div class="row">
<div class="span6 offset3">
<%= form_for([#user, #profile]) do |f| %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.label :surname %>
<%= f.text_field :surname %>
<%= f.submit "Create my profile", class: "btn btn-large btn-primary" %>
<% end %>
</div>
</div>
routes
user_profile POST /users/:user_id/profile(.:format) profiles#create
new_user_profile GET /users/:user_id/profile/new(.:format) profiles#new
edit_user_profile GET /users/:user_id/profile/edit(.:format) profiles#edit
GET /users/:user_id/profile(.:format) profiles#show
PUT /users/:user_id/profile(.:format) profiles#update
DELETE /users/:user_id/profile(.:format) profiles#destroy
users GET /users(.:format) users#index
POST /users(.:format) users#create
new_user GET /users/new(.:format) users#new
edit_user GET /users/:id/edit(.:format) users#edit
user GET /users/:id(.:format) users#show
PUT /users/:id(.:format) users#update
DELETE /users/:id(.:format) users#destroy
sessions POST /sessions(.:format) sessions#create
new_session GET /sessions/new(.:format) sessions#new
session DELETE /sessions/:id(.:format) sessions#destroy
root / static_pages#home
signup /signup(.:format) users#new
signin /signin(.:format) sessions#new
signout DELETE /signout(.:format) sessions#destroy
help /help(.:format) static_pages#help
about /about(.:format) static_pages#about
contact /contact(.:format) static_pages#contact
Controller:
class ProfilesController < ApplicationController
def show
end
def new
#user = current_user
#profile = current_user.build_profile()
end
def edit
end
def create
end
def update
end
def destroy
end
end
below is an illustrate of current_user in profiles_controller.rb
module SessionsHelper
def sign_in(user)
cookies.permanent[:remember_token] = user.remember_token
self.current_user = user
end
def signed_in?
!current_user.nil?
end
def current_user=(user)
#current_user = user
end
def current_user
#current_user ||= User.find_by_remember_token(cookies[:remember_token])
end
def sign_out
self.current_user = nil
cookies.delete(:remember_token)
end
end

Form for using the polymorphic routes like that will always use the pluralized path for new records. You will need to be explicit in your form:
form_for([#user, #profile], :url => user_profile_path(#user))
Good news though, the create route is the same as the update route.

Related

Rspec & Capybara: uninitialized constant SessionController

I am following along this tutorial's authentication process - currently on the section 'User Authentication':
http://larsgebhardt.de/user-authentication-with-ruby-on-rails-rspec-and-capybara/
I received the follower test failure:
1) User Management User log in
Failure/Error: login(#writer)
ActionController::RoutingError:
uninitialized constant SessionController
# ./spec/support/user_helper.rb:6:in `login'
# ./spec/features/users_spec.rb:27:in `block (2 levels) in <top (required)>'
Here is the specific test and helper file mention in the failure message, along with other files..
spec/features/users_spec.rb
require 'spec_helper'
background do
#writer = create(:user, :writer)
end
....
scenario 'User log in' do
activate(#writer)
login(#writer)
expect(page).to have_content "Successfully logged in."
end
spec/support/user_helper.rb
module UserHelper
def login(a)
visit root_path
click_link 'Log In'
fill_in 'session[email]', with: a.email
fill_in 'session[password]', with: a.password
click_button 'Log In'
end
def logout(a)
visit root_path
click_link 'Log Out'
end
def activate(a)
visit activate_path(:code => a.activation_code)
end
end
routes.rb
resources :session
sessions_controller.rb
class SessionsController < ApplicationController
def new
end
def create
user = User.find_by_email(params[:session][:email]).try(:authenticate, params[:session][:password])
if user
if user.is_active?
session[:user_id] = user.id
redirect_to (session[:target_url] || root_path)
flash[:notice] = "Successfully logged in."
else
redirect_to new_session_path
flash[:error] = "Account inactive. Please activate your account."
end
else
redirect_to new_session_path
flash[:error] = "Invalid email or password."
end
end
def destroy
session[:user_id] = nil
redirect_to root_path
flash[:notice] = "Successfully logged out."
end
end
new.html.erb
<h1>Log In</h1>
<%= form_for :session, url: sessions_path do |f| %>
<div>
<%= f.label :email %>
<%= f.text_field :email %>
</div>
<div>
<%= f.label :password %>
<%= f.password_field :password %>
</div>
<div>
<%= f.submit 'Log In' %>
</div>
<% end %>
rake routes
Prefix Verb URI Pattern Controller#Action
profiles_show GET /profiles/show(.:format) profiles#show
sessions_new GET /sessions/new(.:format) sessions#new
users_new GET /users/new(.:format) users#new
root GET / sessions#new
post_comments GET /posts/:post_id/comments(.:format) comments#index
POST /posts/:post_id/comments(.:format) comments#create
new_post_comment GET /posts/:post_id/comments/new(.:format) comments#new
edit_post_comment GET /posts/:post_id/comments/:id/edit(.:format) comments#edit
post_comment GET /posts/:post_id/comments/:id(.:format) comments#show
PATCH /posts/:post_id/comments/:id(.:format) comments#update
PUT /posts/:post_id/comments/:id(.:format) comments#update
DELETE /posts/:post_id/comments/:id(.:format) comments#destroy
posts GET /posts(.:format) posts#index
POST /posts(.:format) posts#create
new_post GET /posts/new(.:format) posts#new
edit_post GET /posts/:id/edit(.:format) posts#edit
post GET /posts/:id(.:format) posts#show
PATCH /posts/:id(.:format) posts#update
PUT /posts/:id(.:format) posts#update
DELETE /posts/:id(.:format) posts#destroy
sessions GET /sessions(.:format) sessions#index
POST /sessions(.:format) sessions#create
new_session GET /sessions/new(.:format) sessions#new
edit_session GET /sessions/:id/edit(.:format) sessions#edit
session GET /sessions/:id(.:format) sessions#show
PATCH /sessions/:id(.:format) sessions#update
PUT /sessions/:id(.:format) sessions#update
DELETE /sessions/:id(.:format) sessions#destroy
users GET /users(.:format) users#index
POST /users(.:format) users#create
new_user GET /users/new(.:format) users#new
edit_user GET /users/:id/edit(.:format) users#edit
user GET /users/:id(.:format) users#show
PATCH /users/:id(.:format) users#update
PUT /users/:id(.:format) users#update
DELETE /users/:id(.:format) users#destroy
profile_index GET /profile(.:format) profile#index
POST /profile(.:format) profile#create
new_profile GET /profile/new(.:format) profile#new
edit_profile GET /profile/:id/edit(.:format) profile#edit
profile GET /profile/:id(.:format) profile#show
PATCH /profile/:id(.:format) profile#update
PUT /profile/:id(.:format) profile#update
DELETE /profile/:id(.:format) profile#destroy
activate GET /activate/:code(.:format) users#activate
_header.html.erb
About
Services
<%= link_to "Sign Up", new_user_path %>
<%= link_to "Log In", new_session_path %>
<%= link_to "Log Out", "/session", method: :delete %>
I previously had an issue with configuring the User Helper file which was solved but incase it becomes relevant, you can see the answer and state of the config file here:
Rspec email_spec issue
You need resources :sessions, you are missing the 's'.
Edit :
You are using the delete route incorrectly, you should say
<%= link_to "Log Out",session_path(pass the current signed in user here) , method: :delete %>

Rails routing error: No route matches [GET] "/conversations/'id'/reply"

I'm having trouble replying to conversations with the Mailboxer gem in Rails 4. There isn't a whole lot of documentation on this gem, or maybe I'm just not experienced enough, but I've been stuck on this for a while now.
view/conversations/index:
(shows list of all current user's conversations)
<% #conversations.each do |conversation| %>
<%= link_to conversation.subject, reply_conversation_path(conversation.id) %>
<%= conversation.updated_at.strftime("%a, %m/%e/%Y %I:%M %p") %>
<%= link_to "Move to Trash", {:controller => "conversations", :action =>
"trash", :id => conversation.id}, :title=> "Move to Trash", :method=>'post' %>
<% end %>
When I click the first link_to in the above view, I receive the routing error: No route matches [GET] "/conversations/68/reply".
I was hoping to have it render the following view, and have the correct conversation passed to it:
view/messages/_form/
(used to reply to existing conversations)
Reply:
<%= form_for :message, url: [:reply, conversation] do |f| %>
<%= f.text_area :body %>
<%= f.submit "Send Message", class: 'btn btn-primary' %>
<%= submit_tag 'Clear Reply Box', type: :reset, class: 'btn btn-danger' %>
<% end %>
Routes:
resources :users
root to: 'profiles#index'
resources :messages do
member do
post :new
end
end
resources :conversations do
member do
post :reply
post :trash
post :untrash
end
collection do
get :trashbin
post :empty_trash
end
end
Conversations Controller:
class ConversationsController < ApplicationController
before_filter :authenticate_user!
helper_method :mailbox, :conversation
def index
#conversations ||= current_user.mailbox.inbox.all
end
def reply
current_user.reply_to_conversation(conversation, *message_params(:body, :subject))
redirect_to conversation
end
def trashbin
#trash ||= current_user.mailbox.trash.all
end
def trash
conversation.move_to_trash(current_user)
redirect_to :conversations
end
def untrash
conversation.untrash(current_user)
redirect_to :back
end
def empty_trash
current_user.mailbox.trash.each do |conversation|
conversation.receipts_for(current_user).update_all(:deleted => true)
end
redirect_to :conversations
end
private
def mailbox
#mailbox ||= current_user.mailbox
end
def conversation
#conversation ||= mailbox.conversations.find(params[:id])
end
def conversation_params(*keys)
fetch_params(:conversation, *keys)
end
def message_params(*keys)
fetch_params(:message, *keys)
end
def fetch_params(key, *subkeys)
params[key].instance_eval do
case subkeys.size
when 0 then self
when 1 then self[subkeys.first]
else subkeys.map{|k| self[k] }
end
end
end
end
Messages Controller:
class MessagesController < ApplicationController
# GET /message/new
def new
#request = Request.find(params[:request])
#message = current_user.messages.new
#user = #request.user
end
# POST /message/create
def create
#user = User.find(params[:user])
#body = params[:body]
#subject = params[:subject]
current_user.send_message(#user, params[:body], params[:subject])
flash[:notice] = "Message has been sent!"
redirect_to :conversations
end
end
relevant rake routes:
users GET /users(.:format) users#index
POST /users(.:format) users#create
new_user GET /users/new(.:format) users#new
edit_user GET /users/:id/edit(.:format) users#edit
user GET /users/:id(.:format) users#show
PATCH /users/:id(.:format) users#update
PUT /users/:id(.:format) users#update
DELETE /users/:id(.:format) users#destroy
root GET / profiles#index
message POST /messages/:id(.:format) messages#new
messages GET /messages(.:format) messages#index
POST /messages(.:format) messages#create
new_message GET /messages/new(.:format) messages#new
edit_message GET /messages/:id/edit(.:format) messages#edit
GET /messages/:id(.:format) messages#show
PATCH /messages/:id(.:format) messages#update
PUT /messages/:id(.:format) messages#update
DELETE /messages/:id(.:format) messages#destroy
reply_conversation POST /conversations/:id/reply(.:format) conversations#reply
trash_conversation POST /conversations/:id/trash(.:format) conversations#trash
untrash_conversation POST /conversations/:id/untrash(.:format) conversations#untrash
trashbin_conversations GET /conversations/trashbin(.:format) conversations#trashbin
empty_trash_conversations POST /conversations/empty_trash(.:format) conversations#empty_trash
conversations GET /conversations(.:format) conversations#index
POST /conversations(.:format) conversations#create
new_conversation GET /conversations/new(.:format) conversations#new
edit_conversation GET /conversations/:id/edit(.:format) conversations#edit
conversation GET /conversations/:id(.:format) conversations#show
PATCH /conversations/:id(.:format) conversations#update
PUT /conversations/:id(.:format) conversations#update
DELETE /conversations/:id(.:format) conversations#destroy
I've been following this tutorial: http://jamestansley.com/2014/02/22/customizing-the-mailboxer-ruby-gem-2/
In case I've left anything out, here's my github repo:
https://github.com/portOdin/GoFavorIt-Heroku/tree/stackflow/app.
The route is a post route:
resources :conversations do
member do
post :reply
Your form needs to use an HTTP POST request, and because you haven't specified a method, it's defaulting to a GET request.
Replace this...
<%= form_for :message, url: [:reply, conversation] do |f| %>
with this:
<%= form_for :message, url: [:reply, conversation], method: :post do |f| %>
Your rake routes shows reply_conversation POST /conversations/:id/reply(.:format) conversations#reply but your link_to will send a get request. You need to change your route to make it a get request.

Rails: Routing error when rendering AJAX partial

I am encountering a routing error when I try to render a partial in an ajax call:
Routing Error
No route matches {:action=>"destroy", :controller=>"relationships", :user_id=>#<User id: 2, username: .....
Within my app, I have a list of followers for a user displayed on the profile page. Instead of paginating the followers, I would like to try to return the next offset of followers from the server through AJAX. My view already utilizes partials for displaying a list of these followers (limited to 5 records).
My goal is to use an AJAX call to return this partial with the next offset of records formated (I haven't implemented the functionality to return offset records yet - I'm just trying to get the ajax working first). The partials work fine when I visit the profile page in my browser (and view the first 5 records), the error occurs when I make the AJAX call.
Here is the form in the view where the ajax call originates:
<%= form_tag user_relationships_path(#user), method: :get, remote: true do %>
<%= submit_tag 'load more...' %>
<% end %>
Here is the route:
resources :users, only: [:index, :show, :new, :create, :edit, :update, :destroy] do
resources :relationships, only: [:create, :destroy, :index]
end
Here is my controller action (relationships#index) which responds to the request:
def index
#user = User.find_by_username(params[:user_id])
respond_to do |format|
format.js { render 'load_followers' }
end
end
The load_followers.js.erb partial:
$('ul#followers').append("<%= render 'users/following_items', users: #user.followers %>")
The users/following_items.html.erb partial:
<% users.each do |user| %>
<li class="clearfix">
<div class="box-gravatar pull-left">
<%= link_to user do %>
<%= gravatar_for user, 40 %>
<% end %>
</div>
<div class="pull-right">
<%= render 'relationships/follow', user: user %>
</div>
<%= link_to user.username, user %>
<div class="box-author">joined <%= join_date_for user %></div>
</li>
<% end %>
And finally the relationships/follow.html.erb partial:
<% unless current_user?(user) %>
<% if current_user.following? user %>
<p><%= link_to 'unfollow', user_relationship_path(user), method: :delete, class: "btn" %></p>
<% else %>
<p><%= link_to 'follow', user_relationships_path(user), method: :post, class: "btn btn-primary" %></p>
<% end %>
<% end %>
I have tracked down the offending code to the relationships/follow.html.erb partial. When that is removed, the ajax call works fine and the partial is appended to the end of the ul. Clearly it has to do with rails having an issue with the link_to to the relationships#destroy method - however, nothing I've tried seems to work.
Edit: Here are the results of running rake routes:
root / posts#index
posts_test /posts/test(.:format) posts#test
submit /submit(.:format) posts#new
signup /signup(.:format) users#new
login /login(.:format) sessions#new
logout DELETE /logout(.:format) sessions#destroy
about /about(.:format) about#index
search /search(.:format) search#index
sessions POST /sessions(.:format) sessions#create
new_session GET /sessions/new(.:format) sessions#new
session DELETE /sessions/:id(.:format) sessions#destroy
post_comments POST /posts/:post_id/comments(.:format) comments#create
post_votes POST /posts/:post_id/votes(.:format) votes#create
posts GET /posts(.:format) posts#index
POST /posts(.:format) posts#create
new_post GET /posts/new(.:format) posts#new
post GET /posts/:id(.:format) posts#show
user_relationships GET /users/:user_id/relationships(.:format) relationships#index
POST /users/:user_id/relationships(.:format) relationships#create
new_user_relationship GET /users/:user_id/relationships/new(.:format) relationships#new
edit_user_relationship GET /users/:user_id/relationships/:id/edit(.:format) relationships#edit
user_relationship GET /users/:user_id/relationships/:id(.:format) relationships#show
PUT /users/:user_id/relationships/:id(.:format) relationships#update
DELETE /users/:user_id/relationships/:id(.:format) relationships#destroy
users GET /users(.:format) users#index
POST /users(.:format) users#create
new_user GET /users/new(.:format) users#new
edit_user GET /users/:id/edit(.:format) users#edit
user GET /users/:id(.:format) users#show
PUT /users/:id(.:format) users#update
DELETE /users/:id(.:format) users#destroy
categories GET /categories(.:format) categories#index
POST /categories(.:format) categories#create
new_category GET /categories/new(.:format) categories#new
category GET /categories/:id(.:format) categories#show
/:category(.:format) posts#index
Thanks!
Notices your rake routes outputted this line:
DELETE /users/:user_id/relationships/:id(.:format)
This means your named route user_relationship is expecting both user and relationship IDs. Reason being, relationship is a nested resource of user.
So for instance you currently have this in your link to:
= link_to 'unfollow', user_relationship_path(user), method: :delete, class: "btn"
Instead it should be something like:
= link_to 'unfollow', user_relationship_path(user, relationship), method: :delete, class: "btn"

Error (RoR Tutorial) -dropdown not firing w/bootstrap- session destroy path incorrect?

Error in Rails Tutorial (Hartl) v3.2
I'm on chapter 8 and all tests pass correctly prior to the exercises. Except two issues (I think they're related).
The dropdown-menu is not firing with bootstrap as the session destroy path appears to be incorrect. I'm also attempting to use the form_tag in place of the form_for tag and I keep getting the following error:
undefined method `[]' for nil:NilClass
Here is the new_html.erb under app/views/sessions:
<% provide(:title, "Sign in") %>
<h1>Sign in</h1>
<div class="row">
<div class="span6 offset3">
<%= form_tag sessions_path do %>
<%= label_tag :email %>
<%= text_field_tag :email %>
<%= label_tag :password %>
<%= password_field_tag :password %>
<%= submit_tag "Sign in", :class => "btn btn-large btn-primary" %>
<% end %>
<p>New user? <%= link_to "Sign up now!", signup_path %></p>
</div>
</div>
Here's the sessions_controller.rb:
class SessionsController < ApplicationController
def new
end
def create
user = User.find_by_email(params[:session][:email])
if user && user.authenticate(params[:session][:password])
sign_in user
redirect_to user
else
flash.now[:error] = 'Invalid email/password combination' # Not quite right!
render 'new'
end
end
def destroy
sign_out
redirect_to root_path
end
end
Finally, here's the rake routes output:
users GET /users(.:format) users#index
POST /users(.:format) users#create
new_user GET /users/new(.:format) users#new
edit_user GET /users/:id/edit(.:format) users#edit
user GET /users/:id(.:format) users#show
PUT /users/:id(.:format) users#update
DELETE /users/:id(.:format) users#destroy
sessions POST /sessions(.:format) sessions#create
new_session GET /sessions/new(.:format) sessions#new
session DELETE /sessions/:id(.:format) sessions#destroy
signup /signup(.:format) users#new
signin /signin(.:format) sessions#new
signout DELETE /signout(.:format) sessions#destroy
help /help(.:format) static_pages#help
about /about(.:format) static_pages#about
contact /contact(.:format) static_pages#contact
root / static_pages#home
Any help would be great.
Edit:
cbright had it. I had to modify the sessions_controller. The following two lines work as intended.
user = User.find_by_email(params[:email])
if user && user.authenticate(params[:password])
The session symbol used with form_for is no longer being used, so replace params[:session][:email] and params[:session][:password] with params[:email] params[:password].

Create Session in Rails 3.1 Hartl Tutorial

This question is admittedly long. So I appreciate any support from the rubytutorial community. I am in Chapter 9, attempting to create a session for a logged-in user.
I've done the tutorial already in < Rails 3.1. Since I am now using Rails 3.1, I headed on over to Chapter 13 and linked to the (very good) Railscasts (#270) on the subject. I was able to rewrite my user sign up pretty easily thanks to has_secure_password.
When I try to log in with a user in the database I see this in the console):
No route matches {:action=>"show", :controller=>"users"}
Seems like I need to create a route and it should work. But if that is the case, why can I go 'users/1' and the view appear? I am using the route user_path(#user), #user in my sessions and users controllers (below).
Here is what I did.
Pass a form to the Session controller new action (note: I use form_tag and not form_for)
<%= form_tag sessions_path do %>
<div class="field">
<%= label_tag :email %><br />
<%= text_field_tag :email, params[:email] %>
</div>
<div class="field">
<%= label_tag :password %><br />
<%= password_field_tag :password %>
</div>
<div class="actions">
<%= submit_tag "Sign In" %>
</div>
<% end %>
Then, create action in sessions_controller.rb
def create
#Assign object by email attribute
user = User.find_by_email(params[:email])
# User is present and has access, must be true otherwise nil object
if user && user.authenticate(params[:password])
session[:user_id] = user.id
RIGHT HERE IS THE PROBLEM
redirect_to user_path(#user), :notice => "Logged in!"
else
#Use flash.now on render not flash[]
flash.now.alert = "Invalid email or password"
render "new"
end
end
And finally Create action for users_controller.rb, which works fine.
def create
#user = User.new(params[:user])
if #user.save
flash[:success] = "Welcome to the Sample App!"
redirect_to #user
else
render "new"
#user.password.clear
#user.password_confirmation.clear
end
end
Leaving my User model:
attr_accessible :name, :email, :password, :password_confirmation
email_regex = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
has_secure_password
Oh and here is my current routes.rb file
resources :users
resources :sessions, only: [:create, :new, :destroy]
root to: "pages#home"
match "/about", to: "pages#about"
match "/contact", to: "pages#contact"
match "/help", to: "pages#help"
match "/signup", to: "users#new"
match "/signin", to: "sessions#new"
match "/signout", to: "sessions#destroy"
And finally my output when I run rake routes:
users GET /users(.:format) {:action=>"index", :controller=>"users"}
POST /users(.:format) {:action=>"create", :controller=>"users"}
new_user GET /users/new(.:format) {:action=>"new", :controller=>"users"}
edit_user GET /users/:id/edit(.:format) {:action=>"edit", :controller=>"users"}
user GET /users/:id(.:format) {:action=>"show", :controller=>"users"}
PUT /users/:id(.:format) {:action=>"update", :controller=>"users"}
DELETE /users/:id(.:format) {:action=>"destroy", :controller=>"users"}
sessions POST /sessions(.:format) {:action=>"create", :controller=>"sessions"}
new_session GET /sessions/new(.:format) {:action=>"new", :controller=>"sessions"}
session DELETE /sessions/:id(.:format) {:action=>"destroy", :controller=>"sessions"}
root / {:controller=>"pages", :action=>"home"}
about /about(.:format) {:controller=>"pages", :action=>"about"}
contact /contact(.:format) {:controller=>"pages", :action=>"contact"}
help /help(.:format) {:controller=>"pages", :action=>"help"}
signup /signup(.:format) {:controller=>"users", :action=>"new"}
signin /signin(.:format) {:controller=>"sessions", :action=>"new"}
signout /signout(.:format) {:controller=>"sessions", :action=>"destroy"}
It's your redirect_to #user and/or user_path(#user) lines. They generate requests to /users/:id, which apparently isn't in your routes.rb.
#user is nil in your example - you're assigning to user. What rails is telling you in a not very helpful way is that it can't route to :controller => 'users', :action => 'show' without a user.

Resources