0

I've been trying to do this for a few hours now. I'm pretty new to Ruby and Rails.

In a devise.html.erb file I have

<div class="container">
<%= render :partial => 'layouts/header' if user_signed_in? %>
</div>

The above works fine. If the user has signed in, then they get to see the header at the top of my page, if they're not signed in, they don't see it.

But I need to have (because the user has to put in an address on the next page):

 <div class="container">
<%= render :partial => 'layouts/header' if current_user.registration_complete?  %>

And when I restart my app I get the error message:

NoMethodError in Devise/registrations#new

I have registration_complete defined elsewhere in my project, in user.rb (which other parts of my project have no trouble recognising) as:

#Determines whether user completed his profile on registration or not
 def registration_complete?
self.address.present?
 end

Is there somewhere else I should put this code, so it will be recognised in my devise.html.erb?

Dave Newton
  • 158,873
  • 26
  • 254
  • 302
CHarris
  • 2,693
  • 8
  • 45
  • 71
  • 1
    Give us the complete error for the NoMethodError. Like it is, we can't see where it came from (although I assume it came from the call to `registration_complete?` – Jesper Mar 06 '13 at 15:03
  • `NoMethodError`... what? What method is not available? (I'm guessing it's complaining about `current_user`) – Chowlett Mar 06 '13 at 15:03

4 Answers4

2

NoMethodError in Devise/registrations#new is because -

Consider this:

<div class="container">
<%= render :partial => 'layouts/header' if current_user.registration_complete?  %>

The current_user in the above code is nil because for registration page the user is not logged in.

So registration_complete is no method for nil.

You can also check for the current_user presence anywhere in your code by;

if current_user
 #User is logged in
    <div class="container">
    <%= render :partial => 'layouts/header' if current_user.registration_complete?  %>
else
 #User is not logged in
 #Don't try current_user.registration_complete? check here..it will give error.
end

So you can put the code containing current_user.registration_complete? check anywhere in your application provided that you are logged in.

sjain
  • 23,126
  • 28
  • 107
  • 185
0

What about:

<%= render :partial => 'layouts/header' if current_user && current_user.registration_complete?  %>
adbeel
  • 384
  • 1
  • 9
0

As Saurabh Jain already pointed out, your current_user will sometimes be nil, so you have to handle that in some way.

His if-statement for current_user is good way of handling it.

Another way of structuring this is to put all the logic the determines whether a user sees the header into a helper method, or even better into a presenter (see for example draper).

In the controller, I would also make sure that here is always a user-object present. If no user is logged in, I will create a new User object as a dummy. That way there'll be less nasty nil-problems.

For example:

# In your controller
@user = current_user || User.new

# In a helper
def can_see_header? (user)
  user_signed_in? and user.registration_complete?
end

# In view
<div class="container">
  <% if can_see_header? @user %>
    <%= render "layouts/header" %>
  <% end %>
</div>

The :partial key in the render call is only needed when you want to pass additional options, at least in later versions off Rails.

Jesper
  • 4,535
  • 2
  • 22
  • 34
0

thanks for your help every one. I'd be lost without sites like Stackoverflow!

In the end I used a combination of Adbeel and Jesper's solution, which seems to do the job.

I used:

<div class="container">
<%= render :partial => 'layouts/header' if user_signed_in? && current_user.registration_complete?%>
</div>

As I said, it works nicely, but if you think there's some disaster lurking ahead I don't know about, I'd be grateful if you'd let me know!Thanks again.

Christophe.

CHarris
  • 2,693
  • 8
  • 45
  • 71