NoMethodError in Statuses#index - ruby-on-rails

I get the following error when I try running my ruby on rails application:
NoMethodError in Statuses#index
undefined method `full_name' for #<Status:0x3fe0e38>
I don't understand why I am getting this error, I would appreciate if someone could point out where I've gone wrong!
Index.html.erb
<div class="page-header">
<h1>All Statuses</h1>
</div>
<%= link_to "Post A New Status", new_status_path, class: "btn btn-success" %>
<% #statuses.each do |status| %>
<div class="status">
<strong><%= status.full_name %></strong>
<p><%= status.content %></p></div>
<div class="meta">
<%= link_to time_ago_in_words(status.created_at) + " ago", status %>
<span class="admin">
| <%= link_to "Edit", edit_status_path(status) %> |
<%= link_to "Delete", status, method: :delete, data: { confirm: "Are you sure your want to delete this status?"} %>
</span>
</div>
</div>
<% end %>
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
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation, :remember_me,
:first_name, :last_name, :profile_name
# attr_accessible :title, :body
has_many :statuses
def full_name
first_name + " " + last_name
end
end
statuses_controller.rb
class StatusesController < ApplicationController
# GET /statuses
# GET /statuses.json
def index
#statuses = Status.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #statuses }
end
end
# GET /statuses/1
# GET /statuses/1.json
def show
#status = Status.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #status }
end
end
# GET /statuses/new
# GET /statuses/new.json
def new
#status = Status.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #status }
end
end
# GET /statuses/1/edit
def edit
#status = Status.find(params[:id])
end
# POST /statuses
# POST /statuses.json
def create
#status = Status.new(params[:status])
respond_to do |format|
if #status.save
format.html { redirect_to #status, notice: 'Status was successfully created.' }
format.json { render json: #status, status: :created, location: #status }
else
format.html { render action: "new" }
format.json { render json: #status.errors, status: :unprocessable_entity }
end
end
end
# PUT /statuses/1
# PUT /statuses/1.json
def update
#status = Status.find(params[:id])
respond_to do |format|
if #status.update_attributes(params[:status])
format.html { redirect_to #status, notice: 'Status was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #status.errors, status: :unprocessable_entity }
end
end
end
# DELETE /statuses/1
# DELETE /statuses/1.json
def destroy
#status = Status.find(params[:id])
#status.destroy
respond_to do |format|
format.html { redirect_to statuses_url }
format.json { head :no_content }
end
end
end

You are calling full_name on a status object, yet the method is defined in the user model. If you want the user's full name iterating through statuses you would do something like:
<%= status.user.full_name %>
assuming the association in Status exists for user

Because a Status does not have a full_name.
Your User model does, but you do not appear to be attempting to display a user, rather the statuses. It appears each user has unique statuses, so you could just print the status's user's full name.
That said, unless you really need arbitrary statuses per user, normally you might have a status table, and related users to statuses with a join table, which would make this technique unsuitable.

Really, you should be calling full_name on the User Object not the Status object.
<strong><%= status.user.full_name %></strong>
Assuming they both are associated (with a belongs_to :user), this should work.

Related

Item in Active Record not rendering correctly - Rails 4.2

Not quite sure if 'Active Record' is the right term. The DB? Postgres?
I'm following through Rails Tutorial and having a very frustrating issue. I've found quite a few posts on SO with people struggling, but majority of them went way off base for the answers, so I'm trying to find out what's wrong with my example.
My User Controller
class UsersController < ApplicationController
before_action :set_user, only: [:show, :edit, :update, :destroy]
# GET /users
# GET /users.json
def index
#users = User.all
end
# GET /users/1
# GET /users/1.json
def show
end
# GET /users/new
def new
#user = User.new
end
# GET /users/1/edit
def edit
end
# POST /users
# POST /users.json
def create
#user = User.new(user_params)
respond_to do |format|
if #user.save
format.html { redirect_to #user, notice: 'User was successfully created.' }
format.json { render :show, status: :created, location: #user }
else
format.html { render :new }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /users/1
# PATCH/PUT /users/1.json
def update
respond_to do |format|
if #user.update(user_params)
format.html { redirect_to #user, notice: 'User was successfully updated.' }
format.json { render :show, status: :ok, location: #user }
else
format.html { render :edit }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
# DELETE /users/1
# DELETE /users/1.json
def destroy
#user.destroy
respond_to do |format|
format.html { redirect_to users_url, notice: 'User was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_user
#user = User.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def user_params
params.require(:user).permit(:name, :email)
end
end
My User Model
class User < ApplicationRecord
has_many :micropost
validates :name, presence: true
validates :email, presence: true
end
My Microposts Model
class Micropost < ApplicationRecord
belongs_to :user
validates :content, length: { maximum: 140 },
presence: true
end
My Microposts Controller
class MicropostsController < ApplicationController
before_action :set_micropost, only: [:show, :edit, :update, :destroy]
# GET /microposts
# GET /microposts.json
def index
#microposts = Micropost.all
end
# GET /microposts/1
# GET /microposts/1.json
def show
end
# GET /microposts/new
def new
#micropost = Micropost.new
end
# GET /microposts/1/edit
def edit
end
# POST /microposts
# POST /microposts.json
def create
#micropost = Micropost.new(micropost_params)
respond_to do |format|
if #micropost.save
format.html { redirect_to #micropost, notice: 'Micropost was successfully created.' }
format.json { render :show, status: :created, location: #micropost }
else
format.html { render :new }
format.json { render json: #micropost.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /microposts/1
# PATCH/PUT /microposts/1.json
def update
respond_to do |format|
if #micropost.update(micropost_params)
format.html { redirect_to #micropost, notice: 'Micropost was successfully updated.' }
format.json { render :show, status: :ok, location: #micropost }
else
format.html { render :edit }
format.json { render json: #micropost.errors, status: :unprocessable_entity }
end
end
end
# DELETE /microposts/1
# DELETE /microposts/1.json
def destroy
#micropost.destroy
respond_to do |format|
format.html { redirect_to microposts_url, notice: 'Micropost was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_micropost
#micropost = Micropost.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def micropost_params
params.require(:micropost).permit(:content, :user_id)
end
end
My show.html.erb
<p id="notice"><%= notice %></p>
<p>
<strong>Name:</strong>
<%= #user.name %>
</p>
<p>
<strong>Email:</strong>
<%= #user.email %>
<% if #user.micropost.any? %>
<%= #user.micropost.first %>
<% end %>
</p>
<%= link_to 'Edit', edit_user_path(#user) %> |
<%= link_to 'Back', users_path %>
When I load a Users page (6 or 7 in my case) I am seeing 'something' being outputted in this format, but it's showing
Which I feel like is an Active Record (?) index? I'm not sure how to get it to show the first (or any) Micropost of a User.
In some solutions I saw people used render #user.micropost but I get an issue about partials (Which I'm familiar with) but the tutorial says you should be able to use the syntax used previously (aka #user.email ) to solve it. So I feel I'm over complicating it?
My issue was I needed to use
<p id="notice"><%= notice %></p>
<p>
<strong>Name:</strong>
<%= #user.name %>
</p>
<p>
<strong>Email:</strong>
<%= #user.email %>
<% if #user.micropost.any? %>
<%= #user.micropost.first.content %>
<% end %>
</p>
<%= link_to 'Edit', edit_user_path(#user)
%> |
<%= link_to 'Back', users_path %>
I should have realized when it was reporting a hash value.
you can't be rendering the show page because if you did you would get a no method or for nil class.
Your show action has no instance variable called #user.
For your show to display data you need a user object. In your case you have none.
So in your show method, add this:
#user.find_by(params[:id])
That will find the user 6 or 7 and allow you to call #
Can you paste the url from the browser so I can see where you actually are?

How to associate user to orders

Only the admin can create orders. The orders are assigned to a user by user_id. On a users profile page, is the only place where a user can see only their records. I have a feeling the problem is with my controller.
class OrdersController < ApplicationController
before_action :set_order, only: [:show, :edit, :update, :destroy]
# GET /orders
# GET /orders.json
def index
#orders = Order.all
end
# GET /orders/1
# GET /orders/1.json
def show
end
# GET /orders/new
def new
#order = User.find_by(params[:id]).orders.build
end
# GET /orders/1/edit
def edit
end
# POST /orders
# POST /orders.json
def create
#order = current_user.orders.build(order_params)
respond_to do |format|
if #order.save
format.html { redirect_to #order, notice: 'Order was successfully created.' }
format.json { render :show, status: :created, location: #order }
else
format.html { render :new }
format.json { render json: #order.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /orders/1
# PATCH/PUT /orders/1.json
def update
respond_to do |format|
if #order.update(order_params)
format.html { redirect_to #order, notice: 'Order was successfully updated.' }
format.json { render :show, status: :ok, location: #order }
else
format.html { render :edit }
format.json { render json: #order.errors, status: :unprocessable_entity }
end
end
end
# DELETE /orders/1
# DELETE /orders/1.json
def destroy
#order.destroy
respond_to do |format|
format.html { redirect_to orders_url, notice: 'Order was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_order
#order = Order.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def order_params
params.require(:order).permit(:service, :charge, :user_id)
end
end
This is my users's controller
class UsersController < ApplicationController
def index
#users = User.all
end
def new
#user = User.new
end
def create
customer = Stripe::Customer.create(
:email => 'example#stripe.com',
:card => params[:stripeToken]
)
rescue Stripe::CardError => e
flash[:error] = e.message
redirect_to charges_path
end
def admin_dashboard
#users = User.all
end
def show
end
def edit
end
def update
if params[:user][:password].blank?
params[:user].delete(:password)
params[:user].delete(:password_confirmation)
end
token = params[:stripeToken]
customer = Stripe::Customer.create(
card: token,
email: current_user.email
)
current_user.stripeid = customer.id
current_user.save
redirect_to dashboard_path
end
def payment
end
def destroy
end
private
def user_params
params.require(:user).permit( :stripe_card_token, :avatar, :first_name, :last_name, :country_code, :phone_number,:home_adress,:work_address, :email, :password, :current_password)
end
end
Model User
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 :orders
end
Order Model
class Order < ActiveRecord::Base
belongs_to :user
end
Profile Page
<div class = 'container'>
<table class="table table-hover" style = 'width: 70%'>
<thead>
<tr>
<th> ID </th>
<th> Date </th>
<th>Service</th>
<th>Charge</th>
<th>Feedback</th>
</tr>
</thead>
<tbody>
<% Order.all.each do |orders| %>
<tr>
<td><%= orders.user.id %></td>
<td><%= orders.created_at %></td>
<td><%= orders.service %></td>
<td><%= orders.charge %></td>
</tr>
<%end%>
If I'm missing anything please let me know. I'm not sure how I would associate the admin class to all of this.

Create and Update record from same field with RoR

I'm building a rails app that will be used by people to log how many steps they took on a given week.
The functionality of the application includes an activity logger that a person can enter steps into, click a week shown on a calendar, and click submit. The application will then create a record of the person's id, when the steps were taken, and how many steps. The same step logger should update the step count if the same user logs a different number of steps on a day.
I'm having trouble getting the logic into the controller to check if a step record exists that has the same user_id and step_date as the step being added.
I've looked into "find_or_initialize_by"/"find_or_create_by" but haven't had much luck.
Can anyone point me in the right direction? Code below.
Logging form (_activityLog.html.erb):
<%= simple_form_for Step.new do |f| %>
<%= f.hidden_field :user_id, :value => #user.id %>
<%= f.hidden_field :challenge_id, :value => "1" %>
<div class="input-group">
<span class="input-group-addon" id="basic-addon2">Steps I've Taken:</span>
<%= f.input :step_count, label: false, id: "step_count", class: "form-control", required: true %>
</div>
<div id="weekpicker"></div>
<%= f.input :step_date, as: :hidden, input_html: { class: 'week' } %>
<%= f.button :submit, "Log Activity", class: "submit btn-block", id: "submitWeekly" %>
<% end %>
Steps Controller (steps_controller.rb)
class StepsController < ApplicationController
before_action :set_step, only: [:show, :edit, :update, :destroy]
# GET /steps
# GET /steps.json
def index
#steps = Step.all
end
# GET /steps/1
# GET /steps/1.json
def show
redirect_to(:back)
end
# GET /steps/new
def new
#step = Step.new
end
# GET /steps/1/edit
def edit
end
# POST /steps
# POST /steps.json
def create
#step = Step.new(step_params)
respond_to do |format|
if #step.save
format.html { redirect_to #step, notice: 'Step was successfully created.' }
format.json { render :show, status: :created, location: #step }
else
format.html { render :new }
format.json { render json: #step.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /steps/1
# PATCH/PUT /steps/1.json
def update
respond_to do |format|
if #step.update(step_params)
format.html { redirect_to #step, notice: 'Step was successfully updated.' }
format.json { render :show, status: :ok, location: #step }
else
format.html { render :edit }
format.json { render json: #step.errors, status: :unprocessable_entity }
end
end
end
# DELETE /steps/1
# DELETE /steps/1.json
def destroy
#step.destroy
respond_to do |format|
format.html { redirect_to steps_url, notice: 'Step was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_step
#step = Step.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def step_params
params.require(:step).permit(:user_id, :challenge_id, :step_date, :step_count)
end
end
Step Model (step.rb)
class Step < ActiveRecord::Base
belongs_to :user
belongs_to :challenge
end
Maybe something like this?
def create
# ... leaving some stuff out :)
#step = Step.where(user_id: params[:user_id], step_date: params[:step_date]).first_or_initialize(step_params) # or first_or_create
# ... other code here (leaving more stuff out)
end

How to allow users to comment

So, I'd like users to be able to comment. At the present moment anyone can comment just by typing in a arbitrary name in the name field.
But I'd like to associate a comment with a user. So there will no longer be a need for a name field in the comments form as it will be the users name.
How can this be done?
I've followed Ryan Bates railscast but he never associates comments with users.
comments_controller.rb
class CommentsController < ApplicationController
before_action :set_comment, only: [:show, :edit, :update, :destroy]
def index
#comments = Comment.where("song_id IS NOT ?", nil)
end
def show
end
# GET /comments/new
def new
end
# GET /comments/1/edit
def edit
end
# POST /comments
# POST /comments.json
def create
#comment = Comment.new(comment_params)
respond_to do |format|
if #comment.save
format.html { redirect_to song_url(#comment.song_id), notice: 'Comment was successfully created.' }
format.json { render action: 'show', status: :created, location: #comment}
else
format.html { render action: 'new' }
format.json { render json: #comment.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /comments/1
# PATCH/PUT /comments/1.json
def update
respond_to do |format|
if #comment.update(comment_params)
format.html { redirect_to song_url(#comment.song_id), notice: 'Comment was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #comment.errors, status: :unprocessable_entity }
end
end
end
# DELETE /comments/1
# DELETE /comments/1.json
def destroy
#comment.destroy
redirect_to song_url(#comment.song_id)
end
private
# Use callbacks to share common setup or constraints between actions.
def set_comment
#comment = Comment.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def comment_params
params.require(:comment).permit(:song_id, :author_name, :site_url, :content, :user_id)
end
end
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 :songs
has_many :comments
acts_as_voter
end
comment.rb
class Comment < ActiveRecord::Base
belongs_to :user
belongs_to :song
end
comments#form.html.erb
<%= form_for #comment do |f| %>
<% if #comment.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#comment.errors.count, "error") %> prohibited this comment from being saved:</h2>
<ul>
<% #comment.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div id="comment_form">
<div class="field">
<%= f.hidden_field :song_id %>
<p>
<%= f.text_field :author_name, placeholder: "Name" %>
</p>
<p>
<%= f.text_area :content, :rows => '12', :cols => 35, placeholder: "Leave a comment..." %>
</p>
<p><%= f.submit "Submit" %></p>
<% end %>
<br /><br />
</div></div>
Your Comment table should have a column named user_id if it does not already. Then you can assign the user_id two different ways. These assume you have a current_user method. If you do not, then you will have to fill in the user_id from whatever session store or method you are using.
You could create a hidden_field in your form to assign it.
<%= f.hidden_field :user_id, value: current_user.id %>
but as noted by #rmagnum2002 this could be a security concern due to a user could edit this.
You could assign it during the create action:
def create
#comment = Comment.new(comment_params)
#comment.user_id = current_user.id
respond_to do |format|
if #comment.save
format.html { redirect_to song_url(#comment.song_id), notice: 'Comment was successfully created.' }
format.json { render action: 'show', status: :created, location: #comment}
else
format.html { render action: 'new' }
format.json { render json: #comment.errors, status: :unprocessable_entity }
end
end
end
Assigning this in the controller create action is probably best.

Devise - Trying to display the user who made a post

I'm creating this rails app,
In the app I have the functionality to make an account, then post a status.
I have made it so I can display the status on the screen, but how do i display the name of the person who made the post? I am using devise and have setup :username
My View
<% if user_signed_in? %>
<h1 id="welcome" class="nuvo">Welcome <%= current_user.username %>!</h1>
<% else %>
<h1 id="welcome" class="nuvo">Log-In to make some posts!</h1>
<% end%>
<div class="follow-row">
<div class="titan-users nuvo"><h2>TITAN Users</h2></div>
</div>
<div class="statuses">
<% if user_signed_in? %><div class="status-form"><%= render 'form' %></div><% end %>
<% #posts.each do |post| %>
<div class="post">
<div class="tstamp"><strong>Posted <%= time_ago_in_words(post.created_at) %> ago by <%= current_user.username %></strong></div>
<div class="status"><%= post.status %></div>
</div>
<% end %>
</div>
My Post Controller
class PostsController < ApplicationController
# GET /posts
# GET /posts.json
def index
#posts = Post.all(:order => "created_at DESC")
#post = Post.new
respond_to do |format|
format.html # index.html.erb
format.json { render json: #posts }
end
end
# GET /posts/1
# GET /posts/1.json
def show
redirect_to posts_path
end
# GET /posts/new
# GET /posts/new.json
def new
#post = Post.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #post }
end
end
# GET /posts/1/edit
def edit
#post = Post.find(params[:id])
end
# POST /posts
# POST /posts.json
def create
#post = Post.new(params[:post])
respond_to do |format|
if #post.save
format.html { redirect_to #post, notice: 'Post was successfully created.' }
format.json { render json: #post, status: :created, location: #post }
else
format.html { render action: "new" }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
# PUT /posts/1
# PUT /posts/1.json
def update
#post = Post.find(params[:id])
respond_to do |format|
if #post.update_attributes(params[:post])
format.html { redirect_to #post, notice: 'Post was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
# DELETE /posts/1
# DELETE /posts/1.json
def destroy
#post = Post.find(params[:id])
#post.destroy
respond_to do |format|
format.html { redirect_to posts_url }
format.json { head :no_content }
end
end
end
My user model
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
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation, :remember_me, :username
has_many :post
# attr_accessible :title, :body
end
My Post model
class Post < ActiveRecord::Base
attr_accessible :status, :author
belongs_to :user
validates :status, :presence => true
end
So, does anyone have any ideas how in the view instead displaying, 'current_user.username' can I display the name of the person who posted it?
So, for CodeIt this is the error I get
undefined method `username' for nil:NilClass
Extracted source (around line #17):
14: <% if user_signed_in? %><div class="status-form"><%= render 'form' %></div><% end %>
15: <% #posts.each do |post| %>
16: <div class="post">
17: <div class="tstamp"><strong>Posted <%= time_ago_in_words(post.created_at) %> ago by <%= post.user.username %></strong></div>
18: <div class="status"><%= post.status %></div>
19: </div>
20: <% end %>
20: <% end %>`
You have post belongs_to user. So you can use:
post.user.username #In your #posts loop
In your create method in the controller, i dont see you pass the user_id to it,so probably the user dint set into the post model.
Maybe you can put a hidden_field_tag in your form, and pass your user_id as a param.
Then, in your controller,do something like
#post.user_id = params[:user_id]
Then,in your view,you can access the user_id and find the username from the user_id

Resources