I am using devise as my user authentication and carrierwave gem for image uploading. Now everything works well and the avatar gets saved in the users table and is shown inside the index view; but not inside the show view.
To make my question a bit more clear:
Inside the index view, the avatar get's successfully shown.
Inside the show view, the avatar falls to the default image because #user.avatar is blank/nil
Show code:
<div class="well">
<div class="media">
<a class="pull-left">
<% if #user.avatar.blank? %>
<img src="http://www.adtechnology.co.uk/images/UGM-default-user.png" style="width: 75px;">
<% elsif #user.avatar %>
<%= image_tag #user.avatar, :style => "width:75px;" %>
<% end %>
</a>
<div class="media-body">
<p>About <%= link_to #question.user.username, #question.user, :class => " bg" %></p>
</div>
<p class="text-muted small">Apparently this user doesn't like to share his information.</p>
</div>
</div>
Question controller:
class QuestionsController < ApplicationController
before_action :set_question, only: [:show, :edit, :update, :destroy]
respond_to :html
def index
#questions = Question.all
respond_with(#questions)
end
def show
#user = User.find(params[:id])
respond_with(#question)
end
def new
if user_signed_in?
#question = current_user.questions.build
respond_with(#question)
else
redirect_to new_user_session_path
end
end
def edit
end
def create
#question = current_user.questions.build(question_params)
#question.save
respond_with(#question)
end
def update
#question.update(question_params)
respond_with(#question)
end
def destroy
#question.destroy
respond_with(#question)
end
private
def set_question
#question = Question.find(params[:id])
end
def question_params
params.require(:question).permit(:title, :description)
end
end
User model:
class User < ActiveRecord::Base
mount_uploader :avatar, AvatarUploader
has_many :questions, :dependent => :destroy
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
end
Question model:
class Question < ActiveRecord::Base
belongs_to :user
end
I fixed it by changing these lines inside the show.html.erb :
<% if #question.user.avatar.blank? %>
<img src="http://www.adtechnology.co.uk/images/UGM-default-user.png" style="width: 75px;">
<% elsif #question.user.avatar %>
<%= image_tag #question.user.avatar, :style => "width:75px;" %>
<% end %>
def show
#user = User.find(params[:id])
respond_with(#question)
end
Since the show action's called in QuestionsController, params[:id] will be #question's id. You should use #question.user to refer to the author of #question:
def show
#user = #question.user
respond_with(#question)
end
Related
I need help with this my code,that displays list of posts of users along with their username.What i want is, when i click on a username of a particular post, it should send me to that user's profile. instead, it send's to my own profile or the current user's profile whiles i want it to link me to the username i have clicked profile. (e.g like when you click on a username on Instagram, it links you to the user's profile so you can follow or unfollow and see their post)
Please i need help. what i'm i not doing right in my code.
i'm on rails 5.2.3 & ruby 2.3.3
Home
<div class="posts">
<% #posts.each do |post| %>
<section class="post">
<div class="user">
<div class="avatar">
<img src="assets/avater.jpg">
</div>
<%= link_to post.user.username, user_path(post.user), class: 'username' %>
</div>
<%= image_tag post.image, class: 'main-image' %>
<div class="description">
<% post.description.to_s.split(' ').each do |word| %>
<% if word.start_with?('#') %>
<%= link_to word, search_index_path(query: word) %>
<% else %>
<%= word %>
<% end %>
<% end %>
</div>
</section>
<% end %>
<%= paginate #posts %>
</div>
routes
Rails.application.routes.draw do
get 'search/index'
devise_for :users
get 'home/index'
resources :posts
root 'home#index'
resources :users, only: [:show, :edit, :update]
resources :posts, only: [:new, :create, :show, :destroy]
end
users controller
class UsersController < ApplicationController
before_action :find_user
def show
#user = User.find(params[:id])
#posts = current_user.posts.order(created_at: :desc)
end
def edit
end
def update
current_user.update(user_params)
redirect_to current_user
end
private
def find_user
#user = User.find(params[:id])
end
def user_params
params.require(:user).permit(:username, :name, :website,:bio, :email, :phone, :gender, :avatar)
end
end
post controller
class PostsController < ApplicationController
def new
#post = current_user.posts.build
end
def create
#post = Post.create(post_params)
redirect_to root_path
end
def show
#post = Post.find(params[:id])
end
def destroy
#post = current_user.posts.find(params[:id])
#post.destroy
redirect_to user_path(current_user)
end
private
def post_params
params.require(:post).permit(:description, :image, :user_id)
end
end
home controller
class HomeController < ApplicationController
before_action :authenticate_user!
def index
#posts = Post.order(created_at: :desc).page(params[:page]).per(5)
end
end
I guess the problem is that on the show method from users_controller, you are getting the posts from current_user instead of the user, it should be #posts = #user.posts.order(created_at: :desc)
I'm working on a to-do list in rails and I'm getting the following: undefined method items for nil:NilClass in my users_controller.rb.
The program was working to the point where I could delete and create the list and have it take me to the new_list_path. However, after I came back a day later, I got the undefined method.
Currently, the user is logged in and there is no list. I tried to add a list via rails console but that didn't work.
users_controller.rb
class UsersController < ApplicationController
def show
return redirect_to new_list_path unless current_user
#list = current_user.list
#items = #list.items
end
end
I am directing everything to go the View/Users/Show page with some partials:
users/show.html.erb
<h1><%= #list.title %></h1>
<%= link_to "Delete List", #list, method: :delete %>
<h2 class="media-heading"><%= current_user.name %></h2>
<%= render partial: 'items/form'%>
<%= render partial: 'items/item', collection: #items %>
Partials are here
items/_form.html.erb
<%= form_for [#list, #list.items.new] do |f| %>
<div class="form-group">
<h4>Add an Item:</h4><br/>
</div>
<div class="field">
<%= f.label :name %>
<%= f.text_field :name, class: 'form-control', placeholder: "Add an Item:" %>
</div>
<div class= "form-group">
<%= f.submit "Create Item", class: 'btn btn-success' %>
</div>
<% end %>
items/_item.html.erb
<small class="media-heading">
<p><%= item.name %></p>
<%# time_ago_in_words(item.created_at) %>
</small>
Here are my other two controllers:
lists_controller.rb
class ListsController < ApplicationController
before_action :authenticate_user!
def new
#list = List.new
end
def create
#list = List.new(list_params)
#list.user = current_user
if #list.save
flash[:notice] = "List was saved."
redirect_to current_user
else
flash[:error] = "There was a problem saving your list."
redirect_to user_path(current_user)
end
end
def destroy
#list = List.find(params[:id])
if #list.destroy
redirect_to new_list_path
else
redirect_to current_user
end
end
def edit
end
private
def list_params
params.require(:list).permit(:title)
end
end
items_controller.rb
class ItemsController < ApplicationController
def show
#items = Item.all
end
def create
#list = List.find(params[:list_id])
#item = Item.new(item_params)
#item.list = #list # after initializiation, before saving
if #item.save
flash[:notice] = "Item was saved."
redirect_to current_user
else
flash[:error] = "There was a problem saving your item."
redirect_to current_user
end
end
private
def item_params
params.require(:item).permit(:name)
end
end
I'm wondering how it's broken when it worked previously.
Models are as follows:
list.rb
class List < ActiveRecord::Base
belongs_to :user
has_many :items
end
user.rb
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable, :confirmable
has_one :list
end
item.rb
class Item < ActiveRecord::Base
belongs_to :list
end
In the users_controller.rb, maybe you should define:
def show
#user = User.find(params[:id])
#list = #user.lists
#items = #list.items
end
You need to find the specific user first so it know what lists to show. I realize you are trying to do that with devise helpers, but it isn't really necessary.
name
metric
date_value
result_value
None of the above attributes are showing when I load the index page.
I know its because of this line: <% if averaged.user == current_user %>
More specifically it's because of the nested attributes of date_value and result_value (because if I take out those nested attributes the name & metric will show)
What do I need to add to the controller to allow the nested attributes to show on the index page, and in effect all the attributes?
I am using the cocoon gem and the devise gem.
Thanks in advance for your service!
<div id="values" class="panel panel-default">
<div class="panel-heading"><h4><b>AVERAGE</b></h4></div>
<!-- Table -->
<table>
<% #averaged_quantifieds.each do |averaged| %>
<% if averaged.user == current_user %>
<th class="value">
<%= link_to edit_quantified_path(averaged) do %>
<%= averaged.name %>
<% end %>
(<%= averaged.metric %>)
</th>
<tbody class="value">
<td><%= averaged.date_value.strftime("%m-%Y") %></td>
<td><%= averaged.result_value %></td>
</tbody>
<% end %>
<% end %>
</table>
</div>
controller
class QuantifiedsController < ApplicationController
before_action :set_quantified, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!, except: [:index, :show]
def index
#averaged_quantifieds = current_user.quantifieds.averaged
#instance_quantifieds = current_user.quantifieds.instance
#averaged_quantifieds = Result.all.order("date_value")
#instance_quantifieds = Result.all.order("date_value")
end
def show
end
def new
#quantified = current_user.quantifieds.build
#quantified = Quantified.new
end
def edit
end
def create
#quantified = current_user.quantifieds.build(quantified_params)
if #quantified.save
redirect_to quantifieds_url, notice: 'Quantified was successfully created'
else
render action: 'new'
end
end
def update
if #quantified.update(quantified_params)
redirect_to quantifieds_url, notice: 'Goal was successfully updated'
else
render action: 'edit'
end
end
def destroy
#quantified.destroy
redirect_to quantifieds_url
end
private
def set_quantified
#quantified = Quantified.find(params[:id])
end
def correct_user
#quantified = current_user.quantifieds.find_by(id: params[:id])
redirect_to quantifieds_path, notice: "Not authorized to edit this goal" if #quantified.nil?
end
def quantified_params
params.require(:quantified).permit(:categories, :name, :metric, :result, :date, results_attributes: [:id, :result_value, :date_value, :_destroy])
end
end
quantified.rb
class Quantified < ActiveRecord::Base
belongs_to :user
scope :averaged, -> { where(categories: 'averaged') }
scope :instance, -> { where(categories: 'instance') }
has_many :results
accepts_nested_attributes_for :results, :reject_if => :all_blank, :allow_destroy => true
CATEGORIES = ['averaged', 'instance']
end
result.rb
class Result < ActiveRecord::Base
belongs_to :quantified
belongs_to :user
end
user.rb
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :goals
has_many :values
has_many :quantifieds
has_many :results
end
Please let me know if you need any more code or comments to help bring this question to a resolution.
I made a website in which people can share photo's (they are called pins in my code). I wanted to add a system in which, when someone clicks on the picture, they can comment on it. I decided to use the commontator gem and I installed it. My problem is that the commenting system does not show up below posts like it's supposed to and I get an undefined local variable or method error for my pins controller.
routes.rb
Photo::Application.routes.draw do
resources :pins
devise_for :users
root "pins#index"
get "about" => "pages#about"
mount Commontator::Engine => '/commontator'
show.html.erb
<%= link_to 'Back', pins_path %>
<div class="row">
<div class="col-md-offset-2 col-md-8">
<div class="panel panel-default">
<div class="panel-heading center">
<%= image_tag #pin.image.url(:medium) %>
</div>
<div class="panel-body">
<p><%= #pin.description %></p>
<p><strong><%= #pin.user.name if #pin.user %></strong></p>
<%= commontator_thread(commontable) %>
<% if #pin.user == current_user %>
<%= link_to edit_pin_path(#pin) do %>
<span class="glyphicon glyphicon-edit"></span>
<% end %>
<% end %>
</div>
</div>
</div>
pin.rb
class Pin < ActiveRecord::Base
belongs_to :user
acts_as_commentable
has_attached_file :image, :styles => { :medium => "300x300>", :thumb => "100x100>" }
validates :image, presence: true
acts_as_commontator
acts_as_commontable
end
pins_controller.rb
class PinsController < ApplicationController
before_action :set_pin, only: [:show, :edit, :update, :destroy]
before_action :correct_user, only: [:edit, :update, :destroy]
before_action :authenticate_user!, except: [:index, :show]
def index
#pins = Pin.all.order("created_at DESC").paginate(:page => params[:page], :per_page => 8)
end
def show
end
def new
#pin = current_user.pins.build
end
def edit
end
def create
#pin = current_user.pins.build(pin_params)
if #pin.save
redirect_to #pin, notice: 'Pin was successfully created.'
else
render action: 'new'
end
end
def update
if #pin.update(pin_params)
redirect_to #pin, notice: 'Pin was successfully updated.'
else
render action: 'edit'
end
end
def destroy
#pin.destroy
redirect_to pins_url
end
private
# Use callbacks to share common setup or constraints between actions.
def set_pin
#pin = Pin.find(params[:id])
end
def correct_user
#pin = current_user.pins.find_by(id: params[:id])
redirect_to pins_path, notice: "Not authorized to edit this pin" if #pin.nil?
end
def pin_params
params.require(:pin).permit(:description, :image)
end
end
User model user.rb
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
# :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :pins, dependent: :destroy
validates :name, presence: true
acts_as_commontator
end
error I am getting on show.html.erb
NameError in Pins#show
undefined local variable or method `commontable' for #<#<Class:0x007f9d8ccec328>:0x007f9d8df68768>
Extracted source (around line #12):
<div class="panel-body">
<p><%= #pin.description %></p>
<p><strong><%= #pin.user.name if #pin.user %></strong></p>
**<%= commontator_thread(commontable) %>**
<% if #pin.user == current_user %>
<%= link_to edit_pin_path(#pin) do %>
As there is no stacktrace added, a couple of observations.
acts_as_commontator and acts_as_commontable are added in same model.
As per documentation at https://github.com/lml/commontator
acts_as_commontator // to be added in user model(s) (or any models that should be able to post comments)
acts_as_commontable // to be added in models you want to be able to comment on
So can you try moving acts_as_commontator to user model?
In pin.rb line no. 3,.remove the line acts_as_commentable which is not used by your gem commontator
Assuming that you have added acts_as_commontable to the Pin model,
In the pins/show.html.erb,
Replace
<%= commontator_thread(commontable) %>
With
<%= commontator_thread(#pin) %>
As per the Commontator Usage Documentation,
In <%= commontator_thread(commontable) %>
commontable is an instance of a model that acts_as_commontable.
which in your case is #pin.
I'm trying to add a flashcards(cardsets) feature in Rails and I'm having some problems implementing this as I'm getting an undefined methodcardsets' for nil:NilClass` error
I can get the page to render if I change: <% if #user.cardsets.any? %> to <% unless #cardsets.any? %> but the corresponding cardsets are being shown when I do this.
Here is the html.erb code that is producing this error:
<% provide(:title, "Flashcards") %>
<h1>Flashcards</h1>
<div class="row">
<aside class="span3">
<%= render "shared/cardset_form" %>
</aside>
<div class="span6">
**<% if #user.cardsets.any? %>**
<h3>Flashcard Sets (<%= #user.cardsets.count %>)</h3>
<ol class="cardsets">
<% #user.cardsets.each do |cardset| %>
<li>
<span class="topic"><%= link_to cardset.topic, show_cardset_path(cardset) %></span>
<%= link_to "edit", edit_cardset_path(cardset) %>
<%= render partial: "shared/delete_link", locals: {item: cardset} %>
</li>
<% end %>
</ol>
<% end %>
</div>
</div>
I've starred the line that is producing the undefined methodcardsets' for nil:NilClass` error.
This is what's in my cardsets_controller.rb:
class CardsetsController < ApplicationController
before_action :signed_in_user, only: [:new, :index, :create, :edit, :destroy, :update]
before_action :correct_user, only: [:edit, :update, :destroy]
def index
#cardsets = Cardset.all
end
def show
#cardset = Cardset.find(params[:id])
end
def create
#cardset = current_user.cardsets.build(cardset_params)
if #cardset.save
flash[:success] = "A new set of flashcards have been created!"
redirect_to #cardset
else
render "new"
end
end
def new
#cardset = Cardset.new
end
def edit
end
def update
#cardset = Cardset.find(params[:id])
if #cardset.update_attributes(cardset_params)
flash[:success] = "You've updated your flashcards!"
redirect_to #cardset
else
render "edit"
end
end
def destroy
#cardset = Cardset.find(params[:id])
#cardset.delete
redirect_to cardsets_path
end
private
def cardset_params
params.require(:cardset).permit(:topic, :description)
end
def correct_user
#cardset = current_user.cardsets.find_by_id(params[:id])
redirect_to root_url if #cardset.nil?
end
end
Here is the code in my cardset.rb file:
class Cardset < ActiveRecord::Base
belongs_to :user
validates :user_id, presence: true
validates :topic, presence: true
end
Here is the code in my user.rb file:
class User < ActiveRecord::Base
has_many :cardsets
(...a bunch of other code...)
end
If anyone could provide some help or suggestions on where I may be going wrong I'd greatly appreciate it!
Thanks!
As far as I can tell, you aren't setting #user in your Controller, so #user is nil.
You probably want to either define #user or maybe you meant to use #cardsets.