Was trying to set up a ranking score for my users depending on their like counts.
I was able to get this to work for current_user.like.count but for some reason when I want it to be for user.like.count [so that its not the same one for everyone] my app crashes and gives me this error message: "Undefined method `likes' for nil:NilClass" I have put all my relevant code below as well as my github for this. Any help would be amazing.
Github Url: https://github.com/OmarZV/TY2
_rankings.html.erb
<% if current_user.likes.count >3 %>
A Ranking
<% elsif %>
<% current_user.likes.count == 2%>
B Ranking
<% else %>
C Ranking
<% end %>
users_controller.rb
class UsersController < ApplicationController
before_action :authenticate_user!
def index
#users = User.all
end
def show
#users = User.find(params[:id])
end
end
routes.rb
Rails.application.routes.draw do
devise_for :users, :controllers => { :omniauth_callbacks => "users/omniauth_callbacks" }
resources :users, :controllers => "users_controller.rb"
resources :users do
resource :ranking, module: :users
end
resources :posts do
resource :like, module: :posts
end
root to: "posts#index"
end
Index.html.erb
<h1 class="page-header">Platform Users</h1>
<% #users.each do |user| %>
<strong><%= user.username %></strong>
<div class="round-image-50"><%= image_tag(user.avatar.url(:thumb)) %></div>
div id="user_<%= #user_id%>_rankings">
<%= render partial: "rankings", locals: {user: #user} %>
</div>
<% end %>
Moving comment to answer.
Id just loop through and not use a partial probably. But im pretty sure you can just pass locals: {user: user} to use the variable from the loop and not the instance variable from your controller. checkout the docs on it for a bit more details http://guides.rubyonrails.org/layouts_and_rendering.html#using-partials
Related
I am working on a rails app, where one of the tabs (the user show view) has a partial that is an inner navbar of sorts. There are three links (match, activity, message), each of which correspond to a different partial that is rendered to the right of the inner navbar.
Each of the partials has a corresponding route in my routes.rb file, but they are all rendered within one controller action (user#show). As a result, my inner navbar links alone are bringing the page to the proper route, but aren't successfully rendering the partials. To resolve this, I am checking within the view for what the end of the route is, and rendering the appropriate partial accordingly.
I imagine that there is a more ideal way to accomplish what I am looking to do, but I've had trouble figuring out what that might be.
I know that I could use separate view files instead of partials to resolve this, but for the sake of modularity, I would rather not move in that direction. Is there a better way for me to link routes to the appropriate partials?
routes.rb
Rails.application.routes.draw do
mount RailsAdmin::Engine => '/admin', as: 'rails_admin'
resources :messages
resources :replies
resources :posts
resources :organizations
resources :users
resources :sessions
resources :matches
root "welcome#index"
get "/users/:id/match", to: "users#show", as: "user_match"
get "/users/:id/activity", to: "users#show", as: "user_activity"
get "/users/:id/message", to: "users#show", as: "user_message"
end
users_controller
class UsersController < ApplicationController
skip_before_action :verify_authenticity_token, only: [:create]
def show
#user = User.find(params[:id])
end
def new
#user = User.new
end
def create
#user = User.new(user_params)
if #user.save
log_in #user
flash[:notice] = "Your account was created!"
redirect_to #user
else
flash[:alert] = #user.errors.full_messages.join(", ")
render 'new'
end
end
private
def user_params
params.require(:user).permit(:first_name, :last_name, :email, :password, :password_confirmation)
end
end
/users/show.html.erb
<div class="row">
<% if #user.id == current_user.id %>
<div class="col-md-2 justify-content-start">
<div>
<ul>
<li>
<%= link_to(user_message_path(current_user.id)) do %>
<%= fa_icon "envelope", text: "Messages" %>
<% end %>
</li>
<li>
<%= link_to(user_activity_path(current_user.id)) do %>
<%= fa_icon "comments", text: "Activity" %>
<% end %>
</li>
<li>
<%= link_to(user_match_path(current_user.id)) do %>
<%= fa_icon "handshake-o", text: "Matches" %>
<% end %>
</li>
</ul>
</div>
</div>
<% end %>
<div class="col-md-10 justify-content-center">
<% last = request.path.split('/').last%>
<% if #user.id == current_user.id %>
<% if last == "match" %>
<%= render partial: "match" %>
<% elsif last == "activity" %>
<%= render partial: "activity" %>
<% elsif last == "message" %>
<%= render partial: "message" %>
<% else %>
<%= render partial: "home"%>
<% end %>
<% else %>
<%= render partial: "home" %>
<% end %>
</div>
</div>
You have a few alternative approaches you could take, like setting each sub-page up as a new controller (UserMatchesController, etc.) and routing to them directly, or using AJAX to load the sub-sections dynamically, but your approach isn't bad. What I would do to improve on it is to make the sub-page a named segment in the route with a constraint to lock it down:
get "/users/:id/:section", to: "users#show", constraints: { section: /^(message|home|match|activity)$/ }
You can link to each section by passing that parameter as an argument:
link_to user_path(current_user.id, section: "message")
And then in your template, something like:
render partial: params[:section]
I'm trying to make a dropdown search by category feature on my webapp. I am currently trying to get the dropdown menu to work, but I am constantly getting the error saying:
First argument in form cannot contain nil or be empty
Here is the view:
<%= form_for #search, html: {class: "pure-form"} do |s| %>
<div class="field">
<%= s.label :category %>
<%= s.select(:category, options_for_select([['Other', 'Other'], ["Breakfast", "Breakfast"], ["Lunch/Dinner", "Lunch/Dinner"], ["Dessert", "Dessert"]])) %>
<%end%>
<div class="card-columns">
<% #images.each do |image| %>
<div class="card">
<div class="card-body p-1">
<%= image_tag image.image, class: 'd-block w-100' %>
<%= link_to image.title, image_path(image.id), class: "btn btn-primary stretched-link" %>
</div>
</div>
<% end %>
</div>
And here is the controller:
class SearchesController < ApplicationController
def new
#search = Search.new
#categories = Image.uniq.pluck(:category)
end
def create
#search = Search.create(search_params)
redirect_to #search
end
def show
#search = Search.find(params[:id])
end
private
def search_params
params.require(:search).permit(:category)
end
end
And here are the routes:
Rails.application.routes.draw do
devise_for :users
# For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
root 'pages#home'
get '/images', controller: 'images', action: 'recent'
get '/upload', controller: 'images', action: 'new'
get '/#:username', to: 'users#show', as: :profile
delete 'images/:id(.:format)', :to => 'images#destroy'
resources :images, only: [:index, :show, :create]
get 'searches/search'
resources :searches
end
I tried to configure different things to see if I could get it working, but I could not. I am very unclear as to what is the problem. Any help would be appreciated! Thanks in advance!
I'm using the mailboxer gem to build a messaging system between users for my rails application. For some reason, I'm getting this error:
(undefined method `receipts_for' for nil:NilClass)
Maybe it's because I should define 'receipts_for' somewhere in my controller or in the mailboxer.rb? I tried a few things.. but unfortunately none of them were successful.
This is my routes.rb:
Rails.application.routes.draw do
root 'static_pages#home'
get '/help', to: 'static_pages#help'
get '/about', to: 'static_pages#about'
get '/contact', to: 'static_pages#contact'
get '/signup', to: 'users#new'
get '/login', to: 'sessions#new'
get 'search/index'
post '/login', to: 'sessions#create'
delete '/logout', to: 'sessions#destroy'
resources :users do
member do
get :following, :followers
end
end
resources :conversations do
resources :messages
end
resources :account_activations, only: [:edit]
resources :password_resets, only: [:new, :create, :edit, :update]
resources :microposts, only: [:create, :destroy]
resources :relationships, only: [:create, :destroy]
resources :searches
end
This is my conversations controller:
class ConversationsController < ApplicationController
def show
#conversation = current_user.mailbox.conversation.find(params[:id])
end
def new
#recipients = User.find(params[:user_id])
end
def create
recipient = User.find(params[:user_id])
receipt = current_user.send_message(recipient, params[:body])
redirect_to conversation_path(receipt.conversation)
end
end
This is my messages_controller:
class MessagesController < ApplicationController
before_action :set_conversation
def create
receipt = current_user.send_message(#conversation, body)
redirect_to receipt.conversation
end
private
def set_conversation
#conversation = current_user.mailbox.conversations.find(params[:conversation_id])
end
end
The messaging system I'm building precisely, is a messaging system where the 'current_user' can go to the profile page of any user on the application and message him/her via the profile page. So this means that I'm rendering show.html.erb of the conversation model inside the show.html.erb of my users model. Here is the code of both views:
show.html.erb - Users Model:
<% provide(:title, #user.name) %>
<div class="row">
<aside class="col-md-4">
<section>
<h1>
<%= gravatar_for #user %>
<%= #user.name %>
</h1>
</section>
<section class="stats">
<%= render 'shared/stats' %>
</section>
<h6>
<%= #user.gender %>
</h6>
<%= render "conversations/conversation" %>
</aside>
<div class="col-md-8">
<%= render 'follow_form' if logged_in? %>
<% if #user.microposts.any? %>
<h3>Microposts (<%= #user.microposts.count %>)</h3>
<ol class="microposts">
<%= render #microposts %>
</ol>
<%= will_paginate #microposts %>
<% end %>
</div>
</div>
_conversation.html.erb - show view of the conversations model.
<% #conversation.receipts_for(current_user).each do |receipt| %>
<div>
<%= receipt.message.body %>
</div>
<% end %>
<%= form_tag conversation_messages_path(#conversation), method: post do %>
<div>
<%= text_area_tag :body %>
</div>
<%= submit_tag %>
<% end %>
So how exactly can I define the 'receipts_for' method for my mailboxer? Or is something else wrong with my code?
Any help would be much appreciated!
Thanks!
I’ll piggy-back on what #mu is too short said. It’s important to pay attention to the whole error message. “undefined method receipts_for for nil:NilClass” is telling you that the receiver of the receipts_for method is nil. #conversation.receipts_for(current_user) looks to be the only place where receipts_for is used, so I would start debugging by making sure #conversation is assigned the value of an existing ActiveRecord-backed conversation object.
There seems to be too a lot going on, so I don't know how to offer you a quick fix. The value assignment in your ConversationsController#show method, #conversation= current_user.mailbox.conversation.find(params[:id]) looks cumbersome. That suggests to me that you're looking for a conversation based on a mailbox belonging to the current_user, which might be what you want (in which case, you need to have the appropriate associations defined in your models).
However, since the chain ends with conversation.find(params[:id]), I'm guessing that current_user.mailbox is not needed. Alternatively, if your params don't actually have a conversation id, then maybe that's what you need to focus on.
The good news is you can probably figure out how to define #conversation if you stick byebug (or binding.pry, depending on what you have installed) at the top of your show method and in your view partial:
# In the controller:
def show
binding.pry
#conversation = current_user.mailbox.conversation.find(params[:id])
end
# in the view
<% binding.pry %>
I have a users model and controller. I am trying to make a put and delete request to my controller where the put request is tied to users#allow and the delete request is suppose to be directed to users#destroy. I However keep on getting this error when I make the request:
No route matches [GET] "/users/1/allow"
I am also using devise for users and admin classes so that might have something to do with this error. Im not really sure. Here is my routes.rb:
Rails.application.routes.draw do
get 'users/index'
put 'users/:id/allow', :to => 'users#allow', :as=>:users_allow
delete 'users/:id/destroy', :to => 'users#destroy',:as => :users_destroy
devise_for :users
devise_for :admins
root 'website#show'
resources :tweets do
put '/pass', :to => 'tweets#pass',:as => :pass
put '/fail', :to => 'tweets#fail',:as => :fail
end
get '/to_json', :to=>'tweets#to_json'
end
Here is my users controller:
class UsersController < ApplicationController
before_action :find_user, only:[:allow,:destroy]
before_filter :authenticate_admin!
def index
#users = User.all
end
def allow
find_user.update(:edit_permission=>true)
redirect_to(:back)
end
def destroy
find_user.destroy
redirect_to(:back)
end
private
def find_user
#user = User.find(params[:user_id])
end
end
And here is my users view where I am calling from, users/index.html.erb:
<h1>Users#index</h1>
<p>Find me in app/views/users/index.html.erb</p>
<ul>
<% #users.each do |user|%>
<% if user.edit_permission == nil%>
<li style="color:red"> <%=link_to 'approve', users_allow_path(user), method: :put %> <%=link_to 'delete', users_destroy_path(user), method: :delete %><%= "#{user.name} #{user.email}"%> </li>
<% else%>
<li style="color:green"><%=link_to 'delete', users_destroy_path(user), method: :delete %><%= "#{user.name} #{user.email}"%> </li>
<% end%>
<%end%>
</ul>
I also want to add that when I go into the view and I do an inspect element in my browser for the link for the put request I do see this:
<a rel="nofollow" data-method="put" href="/users/1/allow">approve</a>
I would run rake routes to see your actual routes, because in your routes.rb you actually don't have a route that matches a get with users/:id/allow
#config/routes.rb
resources :users, only: [:index, :destroy] do
put :allow, action: :allow #-> url.com/users/:user_id/allow
end
#app/controllers/users_controller.rb
class UsersController < ApplicationController
def index
#users = User.all
end
def allow
user.update edit_permission: true
redirect_to :back
end
private
def user
User.find params[:user_id] #-> why return an instance var if you aren't going to use it
end
end
#app/views/users/index.html.erb
<ul>
<% #users.each do |user| %>
<% options = {} %>
<% options.allow = ["allow", "red", "put"] %>
<% options.destroy = ["destroy", "green", "delete"] %>
<% option = user.edit_permission ? options.allow : [options.allow, options.destroy] %>
<% option.each do |action,colour,method| %>
<%= link_to action, eval("users_#{action}_path(user)"), method: method, class: colour %><%= "#{user.name} #{user.email}") %>
<% end %>
<% end %>
</ul>
--
To fix your actual problem, you need to make sure you have your Rails UJS driver loaded:
#app/assets/javascripts/application.js
//= require jquery
//= require jquery_ujs
//= require_tree .
I'm currently trying to set up an admin page. I'm creating a form in the page where I can update user's profile using checkboxes, but when I tried to submit, I get sent to a routing error page with uninitialized constant AdminController
my routes.rb
namespace :admin do
get '', to: 'dashboard#index', as: '/'
end
resources :admin do
collection do
post :edit_multiple
put :update_multiple
end
end
controllers/admin/dashboard_controller.rb
class Admin::DashboardController < ApplicationController
def index
#users = User.all
#admin = User.new
end
def edit_multiple
end
def update_multiple
end
end
views/admin/dashboard/index.html.erb
<%= form_tag edit_multiple_admin_index_path do |f| %>
<table>
<% #users.each do |user| %>
<% if !user.public %>
<tr>
<td><%= check_box_tag "user_ids[]", user.id %></td>
</tr>
<% end %>
<% end %>
</table>
<%= submit_tag "Edit Checked" %>
<% end %>
Anyone know when I'm getting this error?
Thanks!
Change your routes.rb file to:
namespace :admin do
get '', to: 'dashboard#index', as: '/'
resource :dashboard do
post :edit_multiple
put :update_multiple
end
end