NoMethodError in UsersController#show - ruby-on-rails

I'm getting the following error in my app when I visit a user profile page not signed into the app (I'm using Devise):
NoMethodError in UsersController#show
undefined method `connections' for nil:NilClass
app/controllers/users_controller.rb:19:in `show'
When I'm logged in the error goes away. I know why it's failing. I just need help coming up with the proper solution.
The error occurs on this line in my users controller:
def show
#connection = current_user.connections.build(user_id: current_user, otheruser_id: #user)
end
A connection form appears for users logged into the app (simply put, a button appears that asks if you would like to connect with this person as a friend). However, I'm checking if the user is logged in on the user view "show" page with <% if user_signed_in? %> before the form.
Here's the relevant code from the view:
<%= render 'connect_form' if user_signed_in? %>
connect_form
<% unless current_user == #user %>
<% if #contact.present? && user_signed_in? %>
<%= #user.first_name %> is your <%= #contact.description %> (<%= link_to "edit contact", edit_connection_path(:id => #contact.id, :user => #user) %>)<br \>
<% else %>
<% if user_signed_in? %>How do you know <%= #user.first_name %>? (<%= link_to "edit contact", new_connection_path(:user => #user) %> )
<% else %>
<% end %><br \>
<% end %>
<% end %>
connection_form (creating a new one)
<% if user_signed_in? %>
How do you know <%= #user.first_name %>?
<%= form_for(#connection) do |f| %>
<%= f.collection_select :description, Connection::CONNECTIONTYPE, :to_s, :to_s, :include_blank => true %>
<%= f.hidden_field(:otheruser_id, :value => #user.id) %>
<%= f.submit "Save", class: "btn btn-primary btn-small" %>
<% else %>
<% end %>
Why is my app trying to load a nil array `#connections even when I have the check user_signed_in? Any help is greatly appreciated!!

First thing I would do is put a check to only build the connection if the current user exist.
def show
#connection = current_user.connections.build(user_id: current_user, otheruser_id: #user) if current_user
end
The main thing to notice is the: if current_user at the end of the line

From the error message
undefined method `connections' for nil:NilClass
current_user is nil, a quickly test for this is
def show
#connection = User.new.connections.build(user_id: current_user, otheruser_id: mock_user_id)
end
For your case, maybe you didn't store the login user somewhere

Related

Allow unauthenticated users to access views that utilize current_user

I have lots of views that have elements that check if the current user isn't the same user that's being viewed, etc. For example, on the user show page there is a button that allows a user to follow another user, which doesn't appear if the user is looking at their own profile.
<% if current_user != #user %>
<div id="follow_form">
<% if current_user.following?(#user) %>
<%= render 'users/unfollow' %>
<% else %>
<%= render 'users/follow' %>
<% end %>
</div>
<% end %>
The problem arises that if you're not logged in, rails throws an error.
undefined method `id' for nil:NilClass
<% if current_user.id == #user.id %>
<%= link_to "Edit Profile", edit_user_registration_path(#user) %>
<% else %>
<%= link_to 'message', new_message_path(receiver_id: #user.id) %>
...
I don't want to have to force people to log in or sign up to view index or show pages. How can I get around this?
You should try that:
<% if user_signed_in? %>
<% if current_user != #user %>
<div id="follow_form">
<% if current_user.following?(#user) %>
<%= render 'users/unfollow' %>
<% else %>
<%= render 'users/follow' %>
<% end %>
</div>
<% end %>
<% end %>

Rails 4 - Nested Attributes form only POSTing one field

I'm new to Ruby on Rails, and I'm looking create a system where users join a house, and then can leave notes to other users in their house. Each note should have individual permissions per other users in their house. When a user creates a note, they will be greeted with a form with a text area for the Note content, and then a list of all the other users in the house, with a dropdown indicating that users level of permission on that note.
I'm attempting to use Partials to make things nicer, as Permissions are a polymorphic class and will be used in other parts of our website. Right now, when a Note is submitted as a new note, only one Permission is being POSTed, instead of a Permission for each user, e.g.
Started POST "/notes" for 127.0.0.1 at 2015-11-03 11:37:47 -0500
Processing by NotesController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"8+fSG6oBsp4C3ikKc6mSNQYIB+mM5w3+42Y5tRVi5LOZY4a1lo0EApLo0WtSVNZ6/MO0yRwGitZzgZWaYR23mg==", "note"=>{"content"=>"okay...", "permissions_attributes"=>{"0"=>{"user_id"=>"0", "level"=>"3"}}}, "commit"=>"Post"}
I've spent a while comparing my View code with partials to others, and can't figure out why it's not submitting a permission for each user. Any advice? I can confirm that the permission that is submitted is created in the NoteController and created in the database correctly. It's just that instead of creating a permission for each user in the list, it's only creating the default permission.
Note Creation GUI
_form.html.erb
<%= form_for(#note) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="field">
<%= f.text_area :content, placeholder: "Compose new Note..." %>
</div>
<%= f.fields_for :permissions do |perm| %>
<%= render 'permission_new', :f => perm %>
<% end %>
<%= f.submit "Post", class: "btn btn-primary" %>
<% end %>
_permission_new.html.erb
<% House.find(current_user.relationship.house_id).users.each do |user| %>
<%= render 'permission', :f => f, user: user %>
<% end %>
<% User.new(id: 0) do |user| %>
<%= render 'permission', :f => f, user: user %>
<% end %>
_permission.html.erb
<% if current_user.id != user.id %>
<div class="permission">
<% if user.id == 0 %>
Default Permission
<% else %>
<%= user.name %>
<% end %>
<%= f.hidden_field :user_id, value: user.id %><br />
<%= f.select :level, [["Read Only", 3], ["Read, Edit, and Delete", 1],
["Read and Edit", 2], ["Can't Read", 4]] %>
</div>
<% end %>
note_controller.rb
...
def new
#note = Note.new
#note.permissions.build
end
def create
#note = current_user.notes.build(note_params)
if #note.save
#perm_user = #note.permissions.create(user_id: current_user.id, level: 0)
flash[:success] = "Note Created"
redirect_to notes_path
else
render 'new'
end
end
...
private
def note_params
params.require(:note).permit(:content, permissions_attributes: [:user_id, :level])
end
In case anyone happens to be having the same problem, I figured it out.
<%= f.fields_for :permissions do |perm| %>
<%= render 'permission_new', :f => perm %>
<% end %>
f.fields_for only technically creates one field per call. This means that in my _permission_new.html.erb file, where I have a loop creating a dropdown for each user in the house, and a dropdown for the default, all of those dropdowns were linked to the same field, and overwriting each other. Which is why only the last permission was being POSTed when a new Note was submitted. To fix this, you must call the f.fields_for multiple times in your form. In my case, I moved my f.fields_for into my _permission_new partial, and ended up with code like this.
_form.html.erb
...
<%= render 'permission_new', f: f %>
...
_permission_new.html.erb
<% House.find(current_user.relationship.house_id).users.each do |user| %>
<%= f.fields_for :permissions do |perm| %>
<%= render 'permission', :f => perm, user: user %>
<% end %>
<% end %>
<% User.new(id: 0) do |user| %>
<%= f.fields_for :permissions do |perm| %>
<%= render 'permission', :f => perm, user: user %>
<% end %>
<% end %>

Comments form showing blank comments even when database is empty, rails

I'm building a comments section on my blog, and so far I have it working to the point where I can successfully submit comments and have them appear on my page.
However, there is always a blank comment on the page whether I have 10 comments or the database is empty.
*** views/artist/lyrics/show.html.erb ***
<%= form_for(#lyric.comments.build, url: artist_album_lyric_comments_path(#artist, #album, #lyric)) do |f| %>
<%= f.text_area :content %>
<%= f.submit "comment" %>
<% end %>
<% if #lyric.comments.any? %>
<% #lyric.comments.each do |comment| %>
<%= comment.username %>
<%= comment.content %>
<% end %>
<% else %>
No one has commented.
<% end %>
*** /controllers/users/comments_controller.rb ***
def create
#comment = Comment.new(comment_params)
#comment.user_id = current_user.id
#comment.username = current_user.username
#comment.lyric_id = Lyric.friendly.find(params[:lyric_id]).id
if #comment.save
redirect_to (:back)
else
redirect_to root_url
end
end
The Comment model is nested and I think that has something to do with it. It's Artist => Album => Lyric => Comment
When I remove the Comment form from the page the blank comment disappears and the <else> statement runs.
In your form_for tag, you are building a comment on #lyric. I believe this is showing up when you are calling #lyric.comments immediately after. Try:
<% #lyric.comments[0..-2].each do |comment| %>
That will grab all the comments from the first to the second to last (basically all of them except the new one you just created).
Edit:
Also change <% if #lyric.comments.any? %> to <% if #lyric.comments.any? && !#lyric.comments[0].new_record? %>
I used this on my code before. Try this:
<% #lyric.comments.each do |comment| %>
<% next if comment.new_record? %>
<%= comment.username %>
<%= comment.content %>
<% end %>
I changed this line:
<%= form_for(#lyric.comments.build, url: artist_album_lyric_comments_path(#artist, #album, #lyric)) do |f| %>
to:
<%= form_for(Comment.new, url: artist_album_lyric_comments_path(#artist, #album, #lyric)) do |f| %>
It runs the else statement and gets rid of the new record on the page.

How do I display validation errors with namespaces? Ruby on rails

I can't figure out how to do this.. I'm in the user-controller that's inside a namespace called admin, and this is how my form looks like:
<%= form_for [:admin, #user] do |f| %>
<% if #user.errors.any? %>
<div class="reg-error">
<h4>Could not send registration!</h4>
<ul>
<% for message in #user.errors.full_messages %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<%= f.label :email %><br>
<%= f.text_field :email %><br><br>
<%= f.label :rank %><br>
<%= f.select :rank, options_for_select([1, 2, 3, 4, 5]) %><br><br>
<%= f.submit "Send registration", :confirm => "Are you sure?" %>
<% end %>
As you can see I'm using [:admin, #user] for the form, but it doesn't work with just replacing #user.errors.any? with [:admin, #user].errors.any?
The form it self works just fine, but it just won't display the validation errors.
How do I do this?
UPDATE - SOLVED
I didn't show you my controller, and I found the error there..
if #user.save
UserMailer.invitation_mail(#user).deliver
redirect_to admin_manage_users_path, :notice => "Successfully added a new account! Mail has been sent"
else
#user = User.new
#registered_users = User.where(:reg_key => nil)
#pending_users = User.where("users.reg_key IS NOT NULL")
render "show"
end
Since I had a #user = User.new in the else statement, It resetted the error messages some how. Totally missed that one. I'll leave it here if someone else would do this simple mistake too.. Thanks for the replys tho.
Try making just the following changes:
form_for #user do |f|
if #user.errors.any?
...
#user.errors_full_messages.each do |message|
<li><%= message %></li>
If that doesn't work can you show me what your controller looks like. For instance, in your users_controller new method are you doing something like:
#user = Admin::User.new

Rails Geocoder - Still learning

I'm sure it's a simply issue due to me not fully understanding how bits fit together in Rails...
I've followed the rails cast but I'm having trouble implementing it into my app (I've had it working stand-alone).
The error I get is
undefined method `nearbys'
Here's what I've got:
user.rb
geocoded_by :full_address
after_validation :geocode
def full_address
[address1, address2, address3, city, country, postcode].compact.join(', ')
end
users_controller.rb
def index
#title = "All users"
if params[:search].present?
#users = User.near(params[:search], 50, :order => :distance)
else
#users = User.all
end
end
index.html.erb
<h3>Nearby locations</h3>
<ul>
<% for user in #users.nearbys(10) %>
<li><%= link_to user.address1, user %> (<%= user.distance.round(2) %> miles)</li>
<% end %>
</ul>
_sidebar.html.erb
<%= form_tag users_path, :method => :get do %>
<p>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag "Search Near", :name => nil %>
</p>
<% end %>
Thanks
If I comment out the .nearbys
<% for user in #users#.nearbys(10) %>
<li><%= link_to user.latitude, user %> (<%= user.distance.round(2) %> miles)</li>
<% end %>
The search works. Could this be a problem with the install of geocoder?
The function nearbys is a function on your model, not on a collection of models. The variable #users contains a collection of User models. You need to call the function on a single model instance, for example for each user in #users.
As an example, but not sure if you really want this:
<% #users.each do |user| %>
<% user.nearbys(10).each do |near_user| %>
<li><%= link_to near_user.latitude, near_user %> (<%= near_user.distance.round(2) %> miles)</li>
<% end %>
<% end %>
(Note that I also changed the for user in #users to use #users.each do |user|, which is more "Rubyish".)

Resources