J. Haselden J. Haselden - 6 months ago 15
Ruby Question

Ruby on Rails - Thredded Gem - Displaying #<User:0x007fd8d5424108> instead of Username

I'm creating an app that runs on Ruby on Rails and is using the thredded Gem for it's community component: https://github.com/thredded/thredded

Currently, in the thredded part of the app, it's displaying

#<User:0x007fd8d5424108>


where it should be displaying the user name.

I have a :name column on the User that defines their username. I am also using Devise for registration.

The link when displaying the username looks like this: <%= link_to thredded_current_user, user_path(thredded_current_user) %>

Now I know I can just change thredded_current_user to thredded_current_user.name, however this would require finding everywhere it's used in the thredded gem, copying it to my app, and then changing the view. I'm thinking there has to be a more simple answer, I just don't know what.

Is there another way to display the user name other than changing all instances of thredded_current_user to thredded_current_user.name ?

Here's the code for the thredded initializer:

# frozen_string_literal: true
# Thredded configuration

# ==> User Configuration
# The name of the class your app uses for your users.
# By default the engine will use 'User' but if you have another name
# for your user class - change it here.
Thredded.user_class = 'User'

# User name column, used in @mention syntax and should be unique.
# This is the column used to search for users' names if/when someone is @ mentioned.
Thredded.user_name_column = :name

# The path (or URL) you will use to link to your users' profiles.
# When linking to a user, Thredded will use this lambda to spit out
# the path or url to your user. This lambda is evaluated in the view context.
Thredded.user_path = lambda do |user|
user_path = :"#{Thredded.user_class.name.underscore}_path"
main_app.respond_to?(user_path) ? main_app.send(user_path, user) : "#{user.to_param}"
end

# This method is used by Thredded controllers and views to fetch the currently signed-in user
Thredded.current_user_method = :"current_#{Thredded.user_class.name.underscore}"

# User avatar URL. rb-gravatar gem is used by default:
Thredded.avatar_url = ->(user) { user.profile_picture.url }

# ==> Permissions Configuration
# By default, thredded uses a simple permission model, where all the users can post to all message boards,
# and admins and moderators are determined by a flag on the users table.

# The name of the moderator flag column on the users table.
Thredded.moderator_column = :admin
# The name of the admin flag column on the users table.
Thredded.admin_column = :admin

# This model can be customized further by overriding a handful of methods on the User model.
# For more information, see app/models/thredded/user_extender.rb.

# ==> Email Configuration
# Email "From:" field will use the following
# Thredded.email_from = 'no-reply@example.com'

# Incoming email will be directed to this host
# Thredded.email_incoming_host = 'example.com'

# Emails going out will prefix the "Subject:" with the following string
# Thredded.email_outgoing_prefix = '[My Forum] '

# Reply to field for email notifications
# Thredded.email_reply_to = -> postable { "#{postable.hash_id}@#{Thredded.email_incoming_host}" }

# ==> View Configuration
# Set the layout for rendering the thredded views.
Thredded.layout = 'thredded/application'

# ==> Error Handling
# By defau

lt Thredded just renders a flash alert on errors such as Topic not found, or Login required.
# Below is an example of overriding the default behavior on LoginRequired:
#
# Rails.application.config.to_prepare do
# Thredded::ApplicationController.module_eval do
# rescue_from Thredded::Errors::LoginRequired do |exception|
# @message = exception.message
# render template: 'sessions/new', status: :forbidden
# end
# end
# end


Here is my routes code:

Rails.application.routes.draw do
get 'page/home'
get 'page/feed'
get 'page/about'
get 'page/contact'

mount Thredded::Engine => '/community'

devise_for :users, :path => '', :path_names => { :sign_in => "login", :sign_out => "logout", :sign_up => "register" }, :controllers => {
:registrations => 'users/registrations', :omniauth_callbacks => "users/omniauth_callbacks" }

resources :users, path: "", only: [:show] do
resources :tracks
end

resources :tracks, only: [:create, :destroy]

resources :feeds, only: [:create, :destroy, :show]
# The priority is based upon order of creation: first created -> highest priority.
# See how all your routes lay out with "rake routes".

# You can have the root of your site routed with "root"
root 'page#home'



# Example of regular route:
# get 'products/:id' => 'catalog#view'

# Example of named route that can be invoked with purchase_url(id: product.id)
# get 'products/:id/purchase' => 'catalog#purchase', as: :purchase

# Example resource route (maps HTTP verbs to controller actions automatically):
# resources :products

# Example resource route with options:
# resources :products do
# member do
# get 'short'
# post 'toggle'
# end
#
# collection do
# get 'sold'
# end
# end

# Example resource route with sub-resources:
# resources :products do
# resources :comments, :sales
# resource :seller
# end

# Example resource route with more complex sub-resources:
# resources :products do
# resources :comments
# resources :sales do
# get 'recent', on: :collection
# end
# end

# Example resource route with concerns:
# concern :toggleable do
# post 'toggle'
# end
# resources :posts, concerns: :toggleable
# resources :photos, concerns: :toggleable

# Example resource route within a namespace:
# namespace :admin do
# # Directs /admin/products/* to Admin::ProductsController
# # (app/controllers/admin/products_controller.rb)
# resources :products
# end

end

Answer

This doesn't actually have to do with the threaded gem; the view is calling to_s on the user object. If you put <?= thredded_current_user => in your view, ERB will automatically call to_s on the thredded_current_user object. Same thing happens in the link_to helper method.

You can override the to_s method in the User model like so:

class User < ActiveRecord::Base
  def to_s
    name
  end
  ...
end

Alternatively, you can alias the name method to to_s like this:

alias_method :to_s, :name
Comments