I just finished Rails' Getting Started guide and everything works perfectly except for this mysterious entry that's being printed in the Index view as shown below. I've been trying to find the cause to no avail, neither have I found no suitable terms to Google this issue.
Index.html.erb
<h1>Index</h1>
<%= link_to 'New Client', new_client_path %>
<table>
<tr>
<th>Name</th>
<th>Issued On</th>
<th>Notes</th>
<th>Finished?</th>
<th>Payments</th>
</tr>
<%= #clients.each do |client| %>
<tr>
<td><%= client.name %></td>
<td><%= client.date %></td>
<td><%= client.note %></td>
<td><%= client.finished %></td>
<td><%= client.payment %></td>
<td><%= link_to 'Show', client_path(client) %></td>
<td><%= link_to 'Edit', edit_client_path(client) %></td>
<td><%= link_to 'Destroy', client_path(client),
method: :delete,
data: { confirm: 'This client will be permanentally deleted, do you want to continue?' } %></td>
</tr>
<% end %>
</table>
Clients Controller
class ClientsController < ApplicationController
def index
#clients = Client.all
end
def show
#client = Client.find(params[:id])
end
def new
#client = Client.new
end
def edit
#client = Client.find(params[:id])
end
def create
#client = Client.new(client_params)
if #client.save
redirect_to #client
else
render 'new'
end
end
def update
#client = Client.find(params[:id])
if #client.update(client_params)
redirect_to #client
else
render 'edit'
end
end
def destroy
#client = Client.find(params[id])
#client.destroy
redirect_to clients_path
end
private
def client_params
params.require(:client).permit(:name, :date, :note, :finished, :payment)
end
end
Remove = from <%= #clients.each do |client| %>. It is outputting result of each which you don't need to print.
In ERB,
<%= %>
executes ruby code as well as outputs the result
For example: <%= client.name %>
<% %>
executes ruby code but doesn't output the result
For example: <% #clients.each do |client| %>....<% end %>
Related
My users are set up through Devise. I also can use CanCanCan.
I set up an articles model and any user can create articles. They can only delete and edit their own article creations. On the index, they can view all articles that have been created by all users. There is currently an option to View, Edit, and Delete. I only want that option visible on the articles that are owned by the user. I want all other article lines to be blank. (Except for admin of course.)
Users can view posts on views/articles/index.html.erb
<table>
<tr>
<th>Title</th>
<th>Description</th>
</tr>
<% #articles.each do |article| %>
<tr>
<td><%= article.title %></td>
<td><%= article.description %></td>
<td><%= link_to 'View', article_path(article) %></td>
<td><%= link_to 'Edit', edit_article_path(article) %></td>
<td><%= link_to 'Delete', article_path(article),
method: :delete,
data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</table>
How can I allow users to only see the Edit and Delete button on the post that they own?
I tried this but it does not work:
<table>
<tr>
<th>Title</th>
<th>Description</th>
</tr>
<% #articles.each do |article| %>
<tr>
<td><%= article.title %></td>
<td><%= article.description %></td>
<td><%= link_to 'View', article_path(article) %></td>
<% if user_signed_in? && current_user.articles.exists?(#article.id) %>
<td><%= link_to 'Edit', edit_article_path(article) %></td>
<td><%= link_to 'Delete', article_path(article),
method: :delete,
data: { confirm: 'Are you sure?' } %></td>
<% end %>
</tr>
<% end %>
</table>
I've also tried:
<% if current_user && current_user.articles.exists?(#article.id) %>
Here is what my articles controller looks like: (I know I need to make it look better.)
def create
#article = current_user.articles.build(article_params)
if #article.save
redirect_to #article
else
render 'new'
end
end
def update
#article = Article.find(params[:id])
if user_signed_in? && current_user.articles.exists?(#article.id)
if #article.update(article_params)
redirect_to #article
else
render 'edit'
end
elsif current_user && current_user.admin_role?
if #article.update(article_params)
redirect_to #article
else
render 'edit'
end
else
redirect_to #article
end
end
def destroy
#article = Article.find(params[:id])
if user_signed_in? && current_user.articles.exists?(#article.id)
#article.destroy
redirect_to articles_path
elsif current_user && current_user.admin_role?
#article.destroy
redirect_to articles_path
else
redirect_to articles_path
end
end
As you have access to the current_user helper provided by Devise, then you can compare it with the article's owner. This can be in the view, to render the proper links to perform the actions:
<% #articles.each do |article| %>
<tr>
<td><%= article.title %></td>
<td><%= article.description %></td>
<td><%= link_to 'View', article_path(article) %></td>
<% if current_user == article.user %>
<td><%= link_to 'Edit', edit_article_path(article) %></td>
<td><%= link_to 'Delete', article_path(article),
method: :delete,
data: { confirm: 'Are you sure?' } %></td>
<% end %>
</tr>
<% end %>
You can move this verification to a helper, in the ApplicationHelper to be available in most of your views, like:
module ApplicationHelper
def owner?(object)
current_user == object.user
end
end
You pass the object, and this returns true or false depending if the current user is equal to the object user. The view only changes to:
<% if owner?(article) %>
If you want to move this verification to the controller, or also if you want to use it in both cases, then you can do the same verification in the controller. As the owner? helper method isn't available in the controller, you can just redirect back in case the current_user isn't the article's owner, like:
def edit
unless current_user == #article.user
redirect_back fallback_location: root_path, notice: 'User is not owner'
end
end
If you want to move this part to a before callback, to be able to use it in the edit and destroy method, then you can add it as a private method, and having access to the #article you can do such comparison, it'd be:
private
def owner?
unless current_user == #article.user
redirect_back fallback_location: root_path, notice: 'User is not owner'
end
end
This way you just need to add it as a before_action callback:
before_action :owner?, only: %i[edit destroy]
Most probably before the one that defines the #article variable.
Note the use of redirect_back in Rails 5, previous versions might use redirect_to :back.
I am trying to create an activity feed, and trust me, it will take a while to create as I am new to ruby on rails. Sorry for a basic question.
However, I am trying to render '_form.html.erb' as I want the user to be able to create a 'story' and for it to be listed on the same page, like any activity feed. Could someone explain to me what the problem is?
My index.html.erb:
<p id="notice"><%= notice %></p>
<h1>This is a list of posts</h1>
<table>
<thead>
<tr>
<th>Name</th>
<th>Description</th>
<th>User</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% #stories.each do |story| %>
<tr>
<td><%= story.name %></td>
<td><%= story.description %></td>
<td><%= story.user.email %></td>
<td><%= link_to 'Show', story %></td>
<% if user_signed_in? %>
<td><%= link_to 'Edit', edit_story_path(story) %></td>
<td><%= link_to 'Destroy', story, method: :delete, data: { confirm: 'Are you sure?'} %></td>
<% end %>
</tr>
<% end %>
</tbody>
</table>
<%= link_to 'New Story', new_story_path %>
<%= render 'form' %>
_form.html.erb:
<%= form_for #story do |f| %>
<%= render 'shared/errors', object: #story %>
<div class="form-group">
<%= f.label :name %>
<%= f.text_field :name, class: 'form-control', required: true %>
</div>
<div class="form-group">
<%= f.label :description %>
<%= f.text_area :description, class: 'form-control', required: true, cols: 3 %>
</div>
<%= f.submit 'Create Story', class: 'btn btn-primary' %>
<% end %>
Story Controller:
class StoriesController < ApplicationController
before_action only: [:destroy, :show, :edit, :update]
def index
#stories = Story.order('created_at DESC')
end
def new
#story = current_user.stories.build
end
def create
#story = current_user.stories.build(story_params)
if #story.save
flash[:success] = "Your beautiful story has been added!"
redirect_to root_path
else
render 'new'
end
end
def edit
#story = Story.find(params[:id])
end
def update
#story = Story.find(params[:id])
if #story.update_attributes(params.require(:story).permit(:name, :description))
flash[:success] = "More knowledge, more wisdom"
redirect_to root_path
else
render 'edit'
end
end
def destroy
#story = Story.find(params[:id])
if #story.destroy
flash[:success] = "I think you should have more confidence in your storytelling"
redirect_to root_path
else
flash[:error] = "Can't delete this story, sorry"
end
end
def show
#stories = Story.find(params[:id])
end
private
def story_params
params.require(:story).permit(:name, :description)
end
end
My error in terminal:
ActionView::Template::Error (First argument in form cannot contain nil or be empty):
1: <%= form_for #story do |f| %>
2: <%= render 'shared/errors', object: #story %>
3:
4: <div class="form-group">
You should add #store variable to index action.
def index
#stories = Story.order('created_at DESC')
#story = current_user.stories.build
end
I am having problem with my post code please see this.
The error is saying
NoMethodError in Admin::Posts#index Showing
/home/muba/rblog/app/views/admin/posts/index.html.erb where line #2
raised:
undefined method `exists?' for nil:NilClass
post> index.html.erb is here:
<h2 class="page-header">Posts <%= link_to "Create New", new_admin_post_path, class:'btn btn-success pull-right' %></h2>
<% if #posts.exists? %>
<table class="table table-striped">
<tr>
<th>Post Title </th>
<th>Date Created</th>
<th>Post Category </th>
<th> Actions </th>
</tr>
<% #posts.each do |post| %>
<tr>
<td><%= post.title %></td>
<td><%= post.created_at.to_time.strftime('%B %e at %l:%M %p') %></td>
<td><%= post.category.name %></td>
<td><%= link_to "Edit", edit_admin_post_path(post), class:'btn btn-primary' %> <%= link_to "Delete", admin_posts_path(post), class:'btn btn-danger', method: :delete, data: {confirm: 'Are you sure'} %></td>
</tr>
<% end %>
</table>
<%= will_paginate #posts %>
<% else %>
<p> There are no posts </p>
<% end %>
And The Posts Controller is:
class PostsController < ApplicationController
def new
#page_title = 'Add Post'
#post = Post.new
end
def create
#post = post.new(post_params)
if #post.save
flash[:notice] = 'Post Created'
redirect_to admin_posts_path
else
render 'new'
end
end
def edit
#post = Post.find(params[:id])
end
def update
#post = Post.find(params[:id])
if #post.update(post_params)
flash[:notice] = 'Post Updated'
redirect_to admin_posts_path
else
render 'new'
end
end
def destroy
#post = Post.find(params[:id])
#post.destroy
flash[:notice] = 'Post Removed'
end
def index
#posts = Post.all
end
private
def category_params
params.require(:post).permit(:title, :category_id, :user_id, :tags, :image, :body)
end
Please give me a solution :(
Check #post like this:-
<% if #posts.present? %>
<% end %>
May be this works:
<% unless #posts.nil? %>
As per the documentation, exists? generally used for comparison, takes argument to check whether exist or not.
You can also try this :
<% if !#posts.nil? %>
<%= your code... %>
<% end %>
This will also help your cause .
I'm pretty new at Ruby on Rails and I'm struggling with best_in_place
I'm using best_in_place to enable editing of data within a HTML table. I'm able to successfully enter data and hit enter for it to save. The new data briefly shows in the table, but it soon reverts back to the previous value. If I reload the page the table will show the new, updated data. Does anyone have any suggestion how to make the updated data show straight away?
This is the code for my controller:
class GamesController < ApplicationController
def index
#games = Game.all
end
def show
#game = Game.find(params[:id])
#render 'index'
end
def new
#game = Game.new
end
def edit
#game = Game.find(params[:id])
end
def create
#game = Game.new(game_params)
if #game.save
redirect_to #game
else
render 'new'
end
end
def update
#game = Game.find(params[:id])
if #game.update(game_params)
redirect_to #game
else
render 'edit'
end
end
def destroy
#game = Game.find(params[:id])
#game.destroy
redirect_to games_path
end
private
def game_params
params.require(:game).permit(:number, :title, :weight, :owner, :borrower, :borrowed)
end
end
And this is the code for the view:
<h1>Listing games</h1>
<%= link_to 'New game', new_game_path, :class => "pure-button pure-button-primary" %>
<p>
<table class="pure-table sortable">
<thead>
<tr>
<th width="110px">Number</th>
<th width="300px" >Title</th>
<th width="110px">Weight</th>
<th width="110px">Owner</th>
<th width="120px">Borrowed</th>
<th width="140px">Borrowed by</th>
<th class="sorttable_nosort">Action</th>
</tr>
</thead>
<tbody>
<% #games.each do |game| %>
<tr>
<td><%= best_in_place game, :number, :inner_class => "input_number" %></td>
<td><%= best_in_place game, :title , :inner_class => "input_title" %></td>
<td><%= best_in_place game, :weight, :inner_class => "input_weight" %></td>
<td><%= best_in_place game, :owner, :inner_class => "input_owner" %></td>
<td><%= best_in_place game, :borrowed, as: :checkbox, collection: {false: "No", true: "Yes"} %></td>
<td><%= best_in_place game, :borrower, :inner_class => "input_borrower" %></td>
<td><%= link_to 'Show', game_path(game) %> |
<%= link_to 'Edit', edit_game_path(game) %> |
<%= link_to 'Destroy', game_path(game),
method: :delete,
data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
</table>
</p>
</div>
<%= render 'grid_bottom' =%>
Any help or suggestion is greatly appreciated!
Sooo... I'm a noob and I haven't found an answer that gets me through this yet. I've been struggling through this and I know it's a simple question, but I'm just not experienced enough to know how to solve this one.
I'm receiving the error:
No route matches [POST] "/users/1/edit"
Here are the routes for the issue: (simple, I know)
Rails.application.routes.draw do
resources :users
Here is the Controller:
class UsersController < ApplicationController
def new
#user=User.new
end
def create
#user = User.new(user_params)
if #user.save
redirect_to users_path
else
render 'new'
end
end
def edit
#user = User.find(params[:id])
end
def update
#user = User.find(params[:id])
if #user.update_attributes(user_params)
redirect_to #user
else
render 'edit'
end
end
def delete
#user = User.find(params[:id])
end
def destroy
#user = User.find(params[:id])
#user.destroy
redirect_to(:action => 'index')
end
def show
#user = User.find(params[:id])
end
def index
#users=User.all.order("created_at ASC")
end
private
def user_params
params.require(:user).permit(:first_name, :last_name, :username, :admin, :email, :birthday)
end
end
And, here is the view:
<DOCTYPE!! HTML>
<html>
<h1>Edit User</h1>
<%= #user.username %>
<%= link_to "Back to User Index", users_path %>
<%= form_for(:user, :url => {:action => 'edit'}) do |f| %>
<table summary="Edit user form fields">
<tr>
<th>First Name</th>
<td><%= f.text_field(:first_name) %></td>
</tr>
<tr>
<th>Last Name</th>
<td><%= f.text_field(:last_name) %></td>
</tr>
<tr>
<th>Username</th>
<td><%= f.text_field(:username) %></td>
</tr>
<tr>
<th>Password</th>
<td><%= f.text_field(:password) %></td>
</tr>
<tr>
<th>Birthday</th>
<td><%= f.date_field(:birthday) %></td>
</tr>
<tr>
<th>Is Admin?</th>
<td><%= f.text_field(:admin) %></td>
</tr>
</table>
<%= submit_tag("Update User") %>
<% end %>
</html>
I know this is probably not worth serious time for you to answer, but I haven't been able to figure it out. Please help, and let me know if you need more info. Thanks again in advance!
Change
<%= form_for(:user, :url => {:action => 'edit'}) do |f| %>
to
<%= form_for(#user) do |f| %>
In this instance, you don't need to specify the action to use. The default conventions in Rails will take care of this for you.
As you already got an answer, so as a suggestion you can also add method parameter as given here
<%= form_for #user, url: edit_user_path(#user), method: :get do |f| %>
...
<% end %>