I am having trouble getting my form to load, not sure why this is happening.
THE PROBLEM: When I try to load the form (/messages/new), I get a blank page, no error messages.
REASON FOR THE PROBLEM: I think the problem is that the link between message and user is not being properly established, that's why the form isn't loading properly, but not sure how to fix it.
BACKGROUND: I currently access the form through POSTS/INDEX file (attached below), but I think this is wrong because there should be a unique link for each user...e.g. if I click on the 'Contact' button for a post created by John, the message should go to John, and so on so forth for other users. I am using the Simple Private Messaging plugin.
Grateful for any feedback!
Thanks,
Faisal
MESSAGES>NEW VIEW
<% form_for #message, :url => messages_path(:user_id => #user) do |f| %>
<p>
To:<br />
<%= f.text_field :to %>
<%= error_message_on #message, :to %>
</p>
<p>
Subject:<br />
<%= f.text_field :subject %>
<%= error_message_on #message, :subject %>
</p>
<p>
Message<br />
<%= f.text_area :body %>
<%= error_message_on #message, :body %>
</p>
<p>
<%= submit_tag "Send" %>
</p>
<% end %>
MESSAGE MODEL
class Message < ActiveRecord::Base
is_private_message
attr_accessor :to
end
ROUTES.RB
Mysalary::Application.routes.draw do
resources :messages do
collection do
post :delete_selected
end
end
resources :users
resources :profiles
resources :pages
resources :posts
get "pages/home"
get "pages/about"
get "pages/legal"
get "pages/feedback"
root :to => 'posts#new'
end
MESSAGES CONTROLLER
class MessagesController < ApplicationController
before_filter :set_user
def index
if params[:mailbox] == "sent"
#messages = #user.sent_messages
else
#messages = #user.received_messages
end
end
def show
#message = Message.read_message(params[:id], current_user)
end
def new
#message = Message.new
if params[:reply_to]
#reply_to = #user.received_messages.find(params[:reply_to])
unless #reply_to.nil?
#message.to = #reply_to.sender.login
#message.subject = "Re: #{#reply_to.subject}"
#message.body = "\n\n*Original message*\n\n #{#reply_to.body}"
end
end
end
def create
#message = Message.new(params[:message])
#message.sender = #user
#message.recipient = User.find_by_login(params[:message][:to])
if #message.save
flash[:notice] = "Message sent"
redirect_to user_messages_path(#user)
else
render :action => :new
end
end
def delete_selected
if request.post?
if params[:delete]
params[:delete].each { |id|
#message = Message.find(:first, :conditions => ["messages.id = ? AND (sender_id = ? OR recipient_id = ?)", id, #user, #user])
#message.mark_deleted(#user) unless #message.nil?
}
flash[:notice] = "Messages deleted"
end
redirect_to :back
end
end
private
def set_user
#user = User.first
end
end
POSTS>INDEX VIEW
<table class="table table-striped">
<tbody>
<% #posts.each do |post| %>
<tr>
<td>I am a <%= post.title %> getting married in <%= post.job %> in <%= post.location %>, and looking for a <%= post.salary %>. My budget is <%= post.salary %>.</td>
<td> <button class="btn" data-toggle="button" onClick="javascript:location.href = '/messages/new';" />Contact</button></td>
<td><%= time_ago_in_words(post.created_at) %> ago.</td>
<!--/.
<td><%= link_to 'Show', post %></td>
<td><%= link_to 'Edit', edit_post_path(post) %></td>
<td><%= link_to 'Destroy', post, :confirm => 'Are you sure?', :method => :delete %></td>
-->
</tr>
<% end %>
</tbody>
</table>
messages/new line 1, try changing the opening ERB tag from a silent to loud tag
s/<%/<%=
sourced from http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html
Related
In my ReviewsController, I have two private methods called in before_action:
def find_course
#course = Course.where(:id=>params[:course_id]).first
end
def find_professor
#professor = Professor.where(:id=>params[:professor_id]).first
end
I'm querying Course through params, and for some reason, I get an undefined methodid' for nil:NilClass` error in my create method:
def create
#review = Review.new(review_params)
#review.course_id = #course.id
#review.professor_id = #professor.id
#review.user_id = current_user.id
if #review.save
redirect_to course_path(#course)
else
render 'new'
end
end
The create method is being called in a form partial as such:
<%= simple_form_for #review do |f| %>
<%= f.input :rating %>
<%= f.input :comment %>
<%= f.button :submit %>
<% end %>
The form is displayed through a link in the course's show template:
<h2><%= #course.name %></h2>
<table class="table">
<thead>
<tr>
<th scope="col">Professors</th>
<th scope="col">Reviews</th>
</tr>
</thead>
<tbody>
<% #course.professors.each do |professor| %>
<tr>
<td><%= professor.name %></td>
<td><%= link_to "Add Review", new_review_path(course_id: #course.id, professor_id: professor.id) %></td>
</tr>
<% end %>
</tbody>
</table>
And new_review_path as defined in routes.rb:
resources :reviews, path_names: { new: 'course/:course_id/professor/:professor_id' }
For some odd reason, if I replace #course = Course.where(:id=>params[:course_id]).first with #course = Course.find(7) (7 being an id of an existing course), the create method works perfectly fine. How do I properly retrieve the Course and Professor records with the given params?
<td><%= link_to "Add Review", new_review_path(course_id: #course.id, professor_id: professor.id) %></td>
It will go reviews/new.html.erb,
here by you will have to send course_id and professor_id with hidden field, so that you could fetch #course and #professor before create action. otherwise #course and #professor will return nil.
Modified code:-
So far as i understand you don't need to find_professor and find_course before create action as these two fields are already in Review Model, so just pass it with form_for wrapper and pass these all together in strong_params
<%= simple_form_for #review do |f| %>
<%= f.input :rating %>
<%= f.input :comment %>
<%= f.hidden_field :course_id, :value => params[:course_id]%>
<%= f.hidden_field :professor_id, :value => params[:professor_id] %>
<%= f.hidden_field :user_id, :value => current_user.id %>
<%= f.button :submit %>
<% end %>
in controller
def create
#review = Review.new(review_params)
if #review.save
course = #review.course
#redirect_to course_path(#course)
redirect_to course_path(course)
else
render 'new'
end
end
private
def review_params
params.require(:review).permit(:rating,:comment,:course_id, :professor_id, :user_id)
end
You need to check if the course and professor objects are fetched and exist before calling the .id
eg:
if #course && #professor
#review = Review.new(review_params)
#review.course_id = #course.id
#review.professor_id = #professor.id
#review.user_id = current_user.id
if #review.save
redirect_to course_path(#course)
else
render 'new'
end
end
It is good habit to use,
#course = Course.find(params[:course_id])
#professor = Professor.find(params[:professor_id])
Please go with above, you can get both properly.
When I clicked on "display your data" link it is showing me the following error.
Error:
NoMethodError in Users#show
Showing C:/Site/new/app/views/users/show.html.erb where line #10 raised:
undefined method `email' for #<User::ActiveRecord_Relation:0x2bd81e8>
My code snippets are given below.
views/users/index.html.erb
<h1>Choose your option</h1>
<%= link_to "Enter your data",users_new_path %>
<%= link_to "Display your data",users_show_path %>
views/users/new.html.erb
<h1>Enter your data here</h1>
<%= form_for #user,:url => {:action => 'create'} do |f| %>
<% if #user.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#user.errors.count, "error") %> prohibited this post from being saved:</h2>
<ul>
<% #user.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<%= f.text_field:name,placeholder:"Enter your name" %><br>
<%= f.email_field:email,placeholder:"Enter your email" %><br>
<%= f.text_field:message,placeholder:"Enter your message"%><br>
<%= f.submit "Submit" %>
<% end %>
views/users/show.html.erb
<h1>Display your data</h1>
<ul>
<li>
<p>
<strong>Name:</strong>
<%= #user.name %>
</p>
<p>
<strong>Email:</strong>
<%= #user.email %>
</p>
<p>
<strong>Message:</strong>
<%= #user.message %>
</p>
</li>
</ul>
<%= link_to "Edit",users_edit_path(:id => t.id) %><%= link_to "Delete",users_delete_path(:id => t.id),data: { confirm: 'Are you sure to delete it ?' } %>
<%= link_to "Back",users_index_path %>
controller/users_controller.rb
class UsersController < ApplicationController
def index
end
def new
#user=User.new
end
def create
#user=User.new(users_params)
if #user.save
flash[:notice]="Your data is saved succesfully"
flash[:color]="valid"
redirect_to :action => 'index'
else
flash[:alert]="You are entering wrong data"
flash[:color]="invalid"
render :new
end
end
def show
#user=User.all
end
def delete
#user=User.find(params[:id])
#user.delete
end
def edit
#edit=User.find(params[:id])
#user=User.new
end
def update
#user=User.find(params[:id])
if #user.update_attributes(update_params)
flash[:notice]="Your data has updated successfully"
flash[:color]="valid"
redirect_to :action => 'index'
else
flash[:alert]="Your data could not update..check it.."
flash[:color]="invalid"
render :edit
end
end
private
def users_params
params.require(:user).permit(:name, :email, :message,pets_attributes: [:name, :email,:message])
end
def update_params
params.require (:user).permit(:name,:email,:message,pets_attributes: [:name,:email,:message])
end
end
model/user.rb
class User < ActiveRecord::Base
has_many :pets
accepts_nested_attributes_for :pets
EMAIL_REGEX = /\A[A-Z0-9._%+-]+#[A-Z0-9.-]+\.[A-Z]{2,4}\z/i
validates :name, :presence => true,:length => { :minimum => 5 }
validates :email, :presence => true, :uniqueness => true, :format => EMAIL_REGEX
validates :message, :presence => true
end
You should fix your show action from:
def show
#user = User.all
end
to:
def show
#user = User.find(params[:id])
end
In show action, you have
#user = User.all
which assigns relation with all users to #user variable. That's why you have this error, because you can't query whole relation for email. You should have:
#user = User.find(params[:id])
User.find(params[:id]) returns single User instance.
def show
#user=User.all
end
This will return array of users instead of user, so in order to call email on it you have to iterate loop over it.
<% user in #users %> <!-- I have change #user to #users in show method -->
<h1>Display your data</h1>
<ul>
<li>
<p>
<strong>Name:</strong>
<%= user.name %>
</p>
<p>
<strong>Email:</strong>
<%= user.email %>
</p>
<p>
<strong>Message:</strong>
<%= user.message %>
</p>
</li>
</ul>
<%= link_to "Edit",users_edit_path(:id => t.id) %><%= link_to "Delete",users_delete_path(:id => t.id),data: { confirm: 'Are you sure to delete it ?' } %>
<%= link_to "Back",users_index_path %>
<% end %>
Or just change show method
#user = User.find(params[:id])
fix your show action.
replace
#user = User.all
with
#user = User.find(params[:id])
I am attempting to use a text field to search for a user email and if it is found, create a membership. if it is not found i would like to create the user based on the email address.
memberships/Index.html.erb
<%= render :partial => 'shared/logedinNav' %>
<section class="centered">
<header>Team Settings</header>
<section class="main">
<aside class="blue_nav_aside">
<nav>
<ul>
<li><%= link_to_unless_current "General", team_info_path(:id => #team.id) %></li>
<li id="bluenav"><%= link_to_unless_current "Team Members", memberships_path(:id => #team.id) %></li>
<li><%= link_to_unless_current "Tags & Categories", %></li>
<li><%= link_to_unless_current "Payments", %></li>
</ul>
</nav>
</aside>
<section class="inline_form">
<%= form_for #membership do |u|%>
<% if notice %>
<p id="notice"><%= notice %></p>
<% end %>
<% if alert %>
<p id="alert"><%= alert %></p>
<% end %>
<%= render "shared/error_messages", :target => #membership %>
<%= u.hidden_field :team_id, :value => #team.id %>
<h1><span class="pictos pictos-form-h1">g</span>Team Members</h1>
<%= u.text_field :user_email, :placeholder => " To add a team member, enter their email here..." %>
<%= u.submit "Invite", :class => "grey button" %>
<section>
<ul>
<% #memberships.each do |m|%>
<li>
<%= m.user.email %>
<% if m.team.admin_user_id != m.user_id %>
<%= link_to(membership_path(m), :confirm => 'Are you sure you want to delete this video?', :method => :delete, :class => "red_link") do %>
<span class="pictos pictos-remove">-</span> Remove
<% end %>
<% end %>
</li>
<% end %>
</ul>
</section>
<% end %>
</section>
</section>
Memberships_controller.rb
class MembershipsController < ApplicationController
def index
#team = Team.find(params[:id])
#memberships = Membership.where(:team_id => #team.id)
#membership = Membership.new
end
def create
#membership = Membership.new(params[:membership])
#team = Team.find(params[:membership][:team_id])
#membership.user = User.find_or_create_by_email(:email => params[:membership][:user_email], :password => "pass", :password_confirmation => "pass")
if #membership.save
redirect_to memberships_path(:id => #team.id), :notice => "New membership created."
else
redirect_to memberships_path(:id => #team.id), :alert => "Fail."
end
end
....
end
Membership.rb
class Membership < ActiveRecord::Base
belongs_to :team
belongs_to :user
accepts_nested_attributes_for :user
attr_accessible :user_id, :team_id
attr_accessor :user_email
validates_presence_of :user_id, on: :create
after_create :set_team_admin
def set_team_admin
self.team.set_admin_user
end
end
it works when the user is found but right now its not recognizing the create_user at all and skips to the Fail redirect.
UPDATE: this is the updated code with suggestions mentioned below.
The problem is that your membership instance doesn't know about the user_email parameter.
you could be using the rails dynamic finder methods http://api.rubyonrails.org/classes/ActiveRecord/Base.html#label-Dynamic+attribute-based+finders for creating a user?
e.g. in memberships_controller.rb
def create
#membership = Membership.new(params[:membership])
#membership.user = User.find_or_create_by_email(params[:membership][:user_email])
if #membership.save
redirect_to memberships_path(:id => #team.id), :notice => "New membership created."
else
redirect_to memberships_path(:id => #team.id), :alert => "Fail."
end
end
I am trying to add a link to my Posts>Index page which lets people send direct message (using Simple Private Messaging) to the creator of the Post.
Currently I have a link to /messages/new to do this, but this is not working - Iget the following error in my app when I try to access /messages/new.
I want to replace the link to /messages/new (in POSTS>INDEX file below) with something better that works. Let me know if you have any thoughts!!
**NoMethodError in Messages#new**
Showing /Users/fkhalid2008/loand/app/views/messages/new.html.erb where line #1 raised:
undefined method `user_messages_path' for #<#<Class:0x12a77f198>:0x12a76dce0>
Extracted source (around line #1):
1: <% form_for #message, :url => user_messages_path(#user) do |f| %>
2: <p>
3: To:<br />
4: <%= f.text_field :to %>
ADDITIONAL INFORMATION: The app itself is like Gumtree.com, where Users come and create Posts (e.g. selling my car), and people respond my sending them Messages (through the Simple Pvt Messages plugin).
Thanks!
Faisal
MESSAGES>NEW VIEW
<% form_for #message, :url => user_messages_path(#user) do |f| %>
<p>
To:<br />
<%= f.text_field :to %>
<%= error_message_on #message, :to %>
</p>
<p>
Subject:<br />
<%= f.text_field :subject %>
<%= error_message_on #message, :subject %>
</p>
<p>
Message<br />
<%= f.text_area :body %>
<%= error_message_on #message, :body %>
</p>
<p>
<%= submit_tag "Send" %>
</p>
<% end %>
MESSAGE MODEL
class Message < ActiveRecord::Base
is_private_message
attr_accessor :to
end
ROUTES.RB
Mysalary::Application.routes.draw do
resources :messages do
collection do
post :delete_selected
end
end
resources :users
resources :profiles
resources :pages
resources :posts
get "pages/home"
get "pages/about"
get "pages/legal"
get "pages/feedback"
root :to => 'posts#new'
end
MESSAGES CONTROLLER
class MessagesController < ApplicationController
before_filter :set_user
def index
if params[:mailbox] == "sent"
#messages = #user.sent_messages
else
#messages = #user.received_messages
end
end
def show
#message = Message.read_message(params[:id], current_user)
end
def new
#message = Message.new
if params[:reply_to]
#reply_to = #user.received_messages.find(params[:reply_to])
unless #reply_to.nil?
#message.to = #reply_to.sender.login
#message.subject = "Re: #{#reply_to.subject}"
#message.body = "\n\n*Original message*\n\n #{#reply_to.body}"
end
end
end
def create
#message = Message.new(params[:message])
#message.sender = #user
#message.recipient = User.find_by_login(params[:message][:to])
if #message.save
flash[:notice] = "Message sent"
redirect_to user_messages_path(#user)
else
render :action => :new
end
end
def delete_selected
if request.post?
if params[:delete]
params[:delete].each { |id|
#message = Message.find(:first, :conditions => ["messages.id = ? AND (sender_id = ? OR recipient_id = ?)", id, #user, #user])
#message.mark_deleted(#user) unless #message.nil?
}
flash[:notice] = "Messages deleted"
end
redirect_to :back
end
end
private
def set_user
#user = User.first
end
end
POSTS>INDEX VIEW
<table class="table table-striped">
<tbody>
<% #posts.each do |post| %>
<tr>
<td>I am a <%= post.title %> getting married in <%= post.job %> in <%= post.location %>, and looking for a <%= post.salary %>. My budget is <%= post.salary %>.</td>
<td> <button class="btn" data-toggle="button" onClick="javascript:location.href = '/messages/new';" />Contact</button></td>
<td><%= time_ago_in_words(post.created_at) %> ago.</td>
<!--/.
<td><%= link_to 'Show', post %></td>
<td><%= link_to 'Edit', edit_post_path(post) %></td>
<td><%= link_to 'Destroy', post, :confirm => 'Are you sure?', :method => :delete %></td>
-->
</tr>
<% end %>
</tbody>
</table>
you routes.rb doesn't define path user_messages_path, it's simple :)
If you want nested restful routes, you need something like
resources :users do
resources :messages
end
Just use
<% form_for #message do |f| %>
<% end %>
Please see UPDATES at the bottom of the question...
For reference, this problem evolved out of some fixes I made based on a previous problem I was having here: Associating Two Models in Rails (user and profile)
I'm building an app that has a user model and a profile model.
I want to associate these models such that:
- After the user creates an account, he is automatically sent to the "create profile" page, and the profile he creates is connected to only that particular user.
- Only the user who owns the profile can edit it.
I generated the user model using nifty_generators. When the user hits submit for the account creation, I redirect him to the "new profile" view to create a profile. I did this by editing the redirect path in the user controller. The user controller looks like this:
def new
#user = User.new
end
def create
#user = User.new(params[:user])
if #user.save
session[:user_id] = #user.id
flash[:notice] = "Thank you for signing up! You are now logged in."
redirect_to new_user_profile_path(:user_id => #user)
else
render :action => 'new'
end
end
When I click 'submit' to create a new user, it now sends me to the following url, which seems right: localhost:3000/users/6/profile/new. But it throws the following exception:
NoMethodError in
ProfilesController#new You have a
nil object when you didn't expect it!
The error occurred while evaluating
nil.build
The trace indicates that the problem is in the profiles controller, in the New method. The profiles controller looks like this:
def index
#user = User.find(params[:user_id])
#profile = #user.profile(:order => "created_at DESC")
end
def show
#user = User.find(params[:user_id])
#profile = #user.profile.find(params[:id])
end
def new
#user = User.find(params[:user_id])
#profile = #user.profile.build
end
def edit
#user = User.find(params[:user_id])
#profile = #user.profile.find(params[:id])
end
def create
#user = User.find(params[:user_id])
#profile = #user.profile.build(params[:profile])
if #profile.save
flash[:notice] = 'Profile was successfully created.'
redirect_to(#profile)
else
flash[:notice] = 'Error. Something went wrong.'
render :action => "new"
end
end
Additionally, the app also throws an exception when I try to view the index page of the profiles (there are currently no profiles because I can't get past the user creation step to create one). This is the exception:
ActiveRecord::RecordNotFound in ProfilesController#index
Couldn't find User without an ID
This is what the log is telling me:
Processing ProfilesController#index
[GET] Parameters:
{"action"=>"index",
"controller"=>"profiles"}
ActiveRecord::RecordNotFound (Couldn't
find User without an ID):
app/controllers/profiles_controller.rb:5:in
`index'
To give you the rest of the details on the app, the models have the following associations:
Profile belongs _to :user
User has _one :profile
I have this in the routes.rb file: map.resources :users, :has_one => :profile
In the view for the new profile page that's throwing the first exception listed above, I have this:
<% form_for([#user, #profile]) do |f| %>
<%= f.error_messages %>
....
<% end %>
In the view for the profile index that's throwing the second exception explained above, I have this:
<% #profiles.each do |profile| %>
<div class="post">
<div class="left">
<p>Store: </p>
<p>Category: </p>
</div>
<div class="right">
<p><%=h profile.name %></p>
<p><%=h profile.category %></p>
</div>
<div class="bottom">
<p><%= link_to 'Go to profile', user_profile_path(#user, profile) %></p>
<p><%= link_to 'Edit', edit_user_profile_path(#user, profile) %></p>
<p><%= link_to 'Destroy', user_profile_path(#user, profile), :confirm => 'Are you sure?', :method => :delete %></p>
</div>
I've spent hours trying to track down the problem myself as a learning exercise, but at this point I have no idea how to fix this. Appreciate the help!
UPDATE:
jdl, per your request:
profiles/new.html.erb:
<% form_for([#user, #profile]) do |f| %>
<%= f.error_messages %>
<div class="left">
<p>
<%= f.label :name %><br />
<%= f.text_field :name %>required
</p>
<p>
<%= f.label :category %><br />
<%= f.text_field :category %>required
</p>
<p>
<%= f.label :address1 %><br />
<%= f.text_field :address1 %>
</p>
<p>
<%= f.label :address2 %><br />
<%= f.text_field :address2 %>
</p>
<p>
<%= f.label :city %><br />
<%= f.text_field :city %>
</p>
<p>
<%= f.label :state %><br />
<%= f.text_field :state %>
</p>
<p>
<%= f.label :zip %><br />
<%= f.text_field :zip %>required
</p>
<p>
<%= f.label :phone %><br />
<%= f.text_field :phone %>
</p>
<p>
<%= f.label :email %><br />
<%= f.text_field :email %>
</p>
</div>
<div class="right">
<p>
<%= f.label :website %><br />
<%= f.text_field :website %>
</p>
<p>
<%= f.label :description %><br />
<%= f.text_area :description %>
</p>
</div>
<p>
<%= f.submit 'Create' %>
</p>
<% end %>
routes.rb:
ActionController::Routing::Routes.draw do |map|
map.signup 'signup', :controller => 'users', :action => 'new'
map.logout 'logout', :controller => 'sessions', :action => 'destroy'
map.login 'login', :controller => 'sessions', :action => 'new'
map.resources :sessions
map.resources :users, :has_one => :profile
map.root :controller => "home"
map.connect ':controller/:action/:id'
map.connect ':controller/:action/:id.:format'
end
PROFILES CONTROLLER (as of 8/20/09, 8pm EST)
class ProfilesController < ApplicationController
def index
#users = User.all(:order => "created_at DESC")
end
def show
#user = User.find(params[:user_id])
end
def new
#user.profile = Profile.new
end
def edit
#user = User.find(params[:user_id])
#profile = #user.profile.find(params[:id])
end
def create
#user = User.find(params[:user_id])
#profile = #user.profile.build(params[:profile])
if #profile.save
flash[:notice] = 'Profile was successfully created.'
redirect_to(#profile)
else
flash[:notice] = 'Error. Something went wrong.'
render :action => "new"
end
end
def update
#profile = Profile.find(params[:id])
if #profile.update_attributes(params[:profile])
flash[:notice] = 'Profile was successfully updated.'
redirect_to(#profile)
else
render :action => "edit"
end
end
def destroy
#profile = Profile.find(params[:id])
#profile.destroy
redirect_to(profiles_url)
end
end
Cody, the index page below is throwing the following exception:
NoMethodError in Profiles#index
Showing app/views/profiles/index.html.erb where line #14 raised:
undefined method `name' for #
<div id="posts">
<% #users.each do |profile| %>
<div class="post">
<div class="left">
<p>Store: </p>
<p>Category: </p>
</div>
<div class="right">
<p><%=h profile.name %></p>
<p><%=h profile.category %></p>
</div>
<div class="bottom">
<p><%= link_to 'Go to profile', user_profile_path(#user, profile) %></p>
<p><%= link_to 'Edit', edit_user_profile_path(#user, profile) %></p>
<p><%= link_to 'Destroy', user_profile_path(#user, profile), :confirm => 'Are you sure?', :method => :delete %></p>
</div>
</div>
The error is telling you that in this line:
#profile = #user.profile.build
#user.profile is nil.
Since you haven't created the profile yet, this makes sense. Instead, go for something like this.
#profile = Profile.new(:user_id => #user.id)
Re: The index page throwing an exception.
You are defining #users in your controller, and then referencing #user in your path helpers. Also, iterating over #users should give you User objects, not Profile objects.
It looks like you're trying to use the Profile#index action to show a list of users. That's kind-of OK, in a not-quite-pure-REST way. However, I would expect to see something more like this.
<% #users.each do |user| -%>
<% unless user.profile.blank? -%>
<%= h user.profile.name %>
<%= h user.profile.category %>
<%= link_to 'Go to profile', user_profile_path(user, user.profile) %>
<% end -%>
<% end -%>
hmm.. I thought when User has many profiles, you can then use:
#user.profiles.build
#user.profiles.create
when User has one profile, you have to use:
#user.build_profile
#user.create_profile
Can't be sure, check API
#jdl was correct in that there is no #user.profile object in ProfilesController#new so calling #user.profile.build would throw a nil exception.
You can fix this by instantiating a new Profile object by
#user.profile = Profile.new
Later if #user gets saved then it will trigger a #user.profile and the foreign keys will be set appropriately.
Also in your ProfilesController, the #index and #show actions are kind of weird. Conventionally, the #index action returns a "list of objects" and #show is to display just one object, a specific one given an ID. However, your #index returns a very specific object because it does a User.find with a specific ID. Furthermore, since a user only has one Profile object it doesnt make sense to also load up its Profile object with an ORDER BY. There should only be one so no order is necessary. On top of that, its debatable whether you need to explicitly load the profile object as you can just access it via #user.profile and ActiveRecord will load it on demand. So your new #index looks something like
def index
#users = User.paginate(:all, :order = "created_at desc", :page => 1, :per_page => 10)
end
This assumes you have the WillPaginate plugin, but the gist is that you are loading a LIST of objects, not just one. In your view, if you are iterating over #users and call .profile on an element of that list then ActiveRecord will load the associated Profile on the fly.
Pretty same thing for #show - no need to explicitly load the profile.
def show
#user = User.find(params[:user_id])
end
Do one thing
In ProfileController provide session[:user_id] not params[:user_id]
def show <br>
#user = User.find(session[:user_id])<br>
#profile = #user.profile <br>
end <br>
I hope it works!