undefined method `lastname' for nil:NilClass rails - Avatar issues - ruby-on-rails

OK, not sure what I did.. but it was working before and now it stopped.
I'm currently trying to add initials as the avatar to users' navbar, following this step by step guide
It all makes sense and I did what was required, but for some reason I'm now getting the error of undefined method..
I'm not sure what am I doing wrong to be honest...Obviosly, users have attribute of firstname and lastname.. Any help would be greatly appreciated. Thank you!
UsersHelper
module UsersHelper
def show_avatar(user)
render partial: 'users/avatar'
end
end
Avatar partial under users/_avatar
<div class=“avatar-circle-sm”>
<span class="initials">
<%= #user.lastname[0..1].upcase %>
</span>
</div>
Page navbar shared/_navbar
<div>
<%= show_avatar(#user) %>
</div>

As discussed in chat, since you're using Devise, you can use current_user instead of setting a new #user variable.

Related

rails 5.1.4 ( ActionCable + Jobs + Devise + ConversationsController.render )

Actually I need a big help, I'm using rails 5.1.4, I get stuck when rendering a partial with ActionCable and background Jobs. In my partial, I have a condition on current_user to check if current_user is the message owner and get his username with green color to make somes differents, so far display an update and delete button for each message he's the owner in the room conversations. But, if I refresh the page or remove current_user in the partial before rendering it works. However, I want that condition happens. Or, looking for a best way if there is one. THANKS IN ADVANCE.
Here is the error displayed in my terminal:
ERROR: ActionView::Template::Error: Devise could not find the warden::Proxy instance on your request environment.
Those are my files content.
The partial: _conversation.html.erb
<div id="message">
<% if conversation.user == current_user %>
<span style="text-align: center; color: green"><%= conversation.user.username %>
</span>
<% else %>
<span style="text-align: center; color: magenta"><%=
conversation.user.username %></span>
<% end %>
<p style="color: black"><%= conversation.body %></p>
</div>
Message_controller.rb
def create
conversation = #room.conversations.new(conversation_params)
conversation.user = current_user
conversation.save
MessageRelayJob.perform_later(conversation)
End
Room/show.html
<div id="conversations" data-room-id="<%= #room.id %>">
<%= render #room.conversations %>
</div>
MY JOB CLASS
class MessageRelayJob < ApplicationJob
queue_as :default
def perform(conversation)
ActionCable.server.broadcast "room_tchats_#{conversation.room.id}_channel",
conversation: render_conversation(conversation)
end
private
def render_conversation(conversation)
ConversationsController.render partial: 'conversations/conversation', locals: {conversation: conversation}
end
end
It can be happening when you try to get Devise current_user in some part of code being managed by action cable. like a background job to render comment or something else. you can resolve it by using something like following in your controller, since you cant access warden at a model or job level(according to my limited knowledge): (I call a job right after creation of my comment in CommentsController create action, which calls a private method to render a comment partial containing edit and delete button, for which current_user was required)
def create
#product = Product.find(comment_params[:product_id])
#comment = #product.comments.build(comment_params)
#comment.save!
gon.comment_id = #comment.id
gon.comment_user_id = #comment.user_id
ActionCable.server.broadcast "chat", comment: render_comment
render :create, layout: false
end
def render_comment
CommentsController.renderer.instance_variable_set(:#env, {"HTTP_HOST"=>"localhost:3000",
"HTTPS"=>"off",
"REQUEST_METHOD"=>"GET",
"SCRIPT_NAME"=>"",
"warden" => warden})
CommentsController.render(
partial: 'comments/comment_detail',
locals: {
product: #product,
comment: #comment
}
)
end
this will help you resolve warden issue, if you have used devise's current_user in that partial, it will give you the commentor user (as it should since that user initiated the rendering of partial). Now to solve this, if you have a front end framework you might need to fetch the current user from cookies in order to restrict some actions like edit/delete. but if you are working in pure rails the solution I came across is that you have to make a hidden field in the dom having current users id, and you will fetch that id for comparison in a script. you might need to access rails variables in javascript, for that you can use GON gem. I know this answer might contain much more than asked but I've searched alot and no where I found a satisfactory solution to this problem, feel free to discuss.

Render a rails model custom getter using react.js

I've started playing a bit with the react-rails gem and am struggling to understand why I am unable to render a custom model attribute in react.js.
All database persisted attributes work fine, it's just custom getters that are returning nothing.
For the sake of simplicity, here's my User model with email, first_name and last_name as persisted attributes.
class User < ActiveRecord::Base
def full_name_and_email
"#{first_name} #{last_name} (#{email})"
end
end
When rendering my view, I initialize a react component:
<%= react_component 'Header', { data: current_user } %>
And within the Header component, if I try the following inside the render function:
var user = this.props.data;
...
return(
<p>Welcome {user.email}</p>
)
My rendered HTML is:
<p data-reactid=".0.0.2">
<span data-reactid=".0.0.2.0">Welcome </span>
<span data-reactid=".0.0.2.1">super_admin#email.com</span>
</p>
However if I try
render(
<p>Welcome {user.full_name_and_email}</p>
)
My rendered HTML results in
<p data-reactid=".0.0.2">
<span data-reactid=".0.0.2.0">Welcome </span>
</p>
I'm probably missing something pretty basic here so if anyone could please help me understand what's going on it would be great!
Thanks!
Answering my own question after re-reading the documentation for the gem:
props is either an object that responds to #to_json or an
already-stringified JSON object (eg, made with Jbuilder, see note
below).
And to add methods to to_json
current_user.to_json(methods: :full_name_and_email)

RoR undefined method 'to_datetime' depending on order of helper methods

I am experiencing a very odd problem; I get this error
undefined method `to_datetime' for nil:NilClass"
when render 'modal' is before render 'post' in show.html.erb, but not if it is after:
<div class="page-header">
<h2>Indlæg af <%= #user.first_name %></h2>
</div>
<% if current_user == #user %>
<%= render 'modal' %>
<% end %>
<%= render 'post' %>
I have attached the views in the gist underneath:
Gist: https://gist.github.com/czepluch/8166841
It makes no sense to me that this error occurs depending on the order the renders are placed in. So I would really like to know why the order of the rendering of the helpers matter?
Please add code to the question so it is saved with the answers here. I suspect it has to do with the fact that your form has this:
simple_form_for([#user, #user.posts.build]
That means a new post is built that has no attributes, which could cause a nil error later on. reverse the order, and this isn't built until after the other code has run. The only thing I can see at first glance that is related to datetime would be:
time_ago_in_words(p.created_at)
If created_at is nil, because of an empty post, that could generate an error.
Play with the form declaration, you may be able to do
simple_form_for([#user, :post])
or something like that to get a form for a new post without actually attaching an empty object to the #user object.

Custom Button Action in Rails View - Ruby on Rails

Rails newbie here. I have an array of hashes that contain Facebook Friends that I'd like to optionally turn into 'Contacts'. I have an index view that lists all of the users's 'friends'. I'd like to have a custom button that enables the user to turn each friend into a contact. How do I do this in Rails?
Index view - I am currently listing each user with their avatar & name. I'd like to add the button in each list item.
Note: I do not have a Friend model, as I am simply pulling this data in from the Facebook Graph API as an array of hashes.
<% #friends.each do |friend|%>
<li> <%= image_tag(fb_avatar(friend["id"], "type=square"))%> <%=friend["name"]%> #put button here </li>
<% end %>
Custom make_friend_contact method in Application Helper (to be called on a friend):
def make_friend_contact
Contact.new(name: self["name"], uid: self["id"], avatar_url: fb_avatar(self["id"], "type=square"), user_id: params[:user])
end
Any help is much appreciated. I've done quite a bit of reading, and I can't seem to crack this one. Thanks!
One solution might be to use button_to. You can check it out in the Rails API. Here is one of their examples:
<%= button_to [:make_happy, #user] do %>
Make happy <strong><%= #user.name %></strong>
<% end %>
# => "<form method="post" action="/users/1/make_happy" class="button_to">
# <div>
# <button type="submit">
# Make happy <strong><%= #user.name %></strong>
# </button>
# </div>
# </form>"
where the button calls the make_happy action in the Users controller on #user.
You could do something similar by making an action in your Users controller that creates a new Contact, using a friend parameter.
def make_friend_contact
friend = params[:friend]
Contact.new(name: friend["name"]...
end
Then you just have to send the friend parameter with the button's POST request.

List all records on main page

I'm trying to list all records from the database in the main page.
Model and controllers were both created properly (I suspect) since using the following code and pointing to proper address (http://localhost:3000/subdomainw1s) lists all the records:
in /app/views/subdomainw1s/index.html.erb:
<h1>subdomain word 1</h1>
<ol class="subdomainw1">
<% #subdomainw1s.each do |sdw1| %>
<li>
<%= sdw1.blognamew1 %>
</li>
<% end %>
</ol>
However, attempting to past the same code in /app/views/home/index.html.erb results in an error message ("undefined method `each' for nil:NilClass") complaining about:
<% #subdomainw1s.each do |sdw1| %>
Clearly, rails doesn't know what to do with this model under the home page.. no?
Any advice would be great.
there is at least two more "codeless" options
convert it to (empty) array
..#subdomainw1s.to_a.each do |sdw1|..
or use method try
..#subdomainw1s.try(:each) do |sdw1|..
copy the code to collect the subdomains from 'index' in subdomains controller to 'index' in home controller.

Resources