flash[:notice] not working in Rails 4 after edit/create action - ruby-on-rails

I can get flash messaging to work after create and destroy when they are redirected to root_path but cannot get it to work when update redirects to show.html.erb for some reason. What do you think is the problem? My Quote model has 4 columns(id, category, author and quotetext)
My show view
<% if !flash[:notice].blank? %>
<div class="notice">
<%= flash[:notice] %>
</div>
<% end %>
<% #category.each do |quote| %>
<div>
<p><strong> <%= quote.category %></strong></p>
<p><em><%= quote.author %></em></p>
<p> <%= quote.text %> </p>
<hr>
</div>
<% end %>
<%= link_to 'Home', quotes_path %>
My controller:
class QuotesController < ApplicationController
before_action :set_quote, only: [:show, :edit, :update, :destroy]
# GET /quotes
# GET /quotes.json
def index
#quotes = Quote.sorted
end
# GET /quotes/1
# GET /quotes/1.json
def show
#quote = Quote.find(params[:id])
end
# GET /quotes/new
def new
#quote = Quote.new
#apparently this doesn't really do anything but good to specify
end
def create
#quote = Quote.new(quote_params)
if #quote.save
flash[:notice] = "Quote #{#quote.pkey} created!"
redirect_to root_path
else
render('new')
end
end
# GET /quotes/1/edit
def edit
#quote = Quote.find(params[:id])
end
# PATCH/PUT /quotes/1
# PATCH/PUT /quotes/1.json
def update
#quote = Quote.find(params[:id])
if #quote.update_attributes(quote_params)
flash[:notice] = "Quote #{#quote.pkey} updated!"
redirect_to(:action => 'show', :id => #quote.id)
else
render('edit')
end
end
# DELETE /quotes/1
# DELETE /quotes/1.json
def destroy
#quote = Quote.find(params[:id]).destroy
flash[:notice] = "Quote #{#quote.pkey} deleted!"
redirect_to root_path
end
private
def set_quote
#quote = Quote.find(params[:id])
end
def quote_params
params.require(:quote).permit(:category, :author, :quotetext)
end
end
my index view
<div class='jumbotron'>
<h1>Root Index Page</h1>
</div>
<%= render 'shared/nav' %>
<div class="quotes index">
<%= render 'flash' %>
<table class="listing">
<tr class="header">
<th>Pkey</th>
<th>Category</th>
<th>Author</th>
<th>Quote Text </th>
</tr>
<% #quotes.each do |quote| %>
<tr>
<td><%=quote.pkey %></td>
<td><%=quote.category %></td>
<td><%=quote.author %></td>
<td><%=quote.text %></td>
<td class="actions">
<%= link_to("Show", {:action => 'show', :id => quote.id}) %>
<%= link_to("Edit", {:action => 'edit', :id => quote.id}) %>
<%= link_to quote_path(quote.id), method: :delete, data: {confirm: "Really delete Quote ##{quote.id}?"} do %><span class=edit>Delete</span><% end %>
</td>
</tr>
<% end %>
</table>
</div>
my edit view
<h1>Edit Existing Quote <%=#quote.pkey%> </h1>
<%= form_for(#quote) do |f| %>
<p>
<%= f.label :category %><br>
<%= f.text_field :category %>
</p>
<p>
<%= f.label :author %><br>
<%= f.text_field :author %>
</p>
<p>
<%= f.label :text %><br>
<%= f.text_area :quotetext %>
</p>
<div class="actions">
<%= f.submit "Update quote" %>
</div>
<% end %>
<%= link_to 'Show', #quote %> |
<%= link_to 'Back', quotes_path %>
flash partial
<% if !flash[:notice].blank? %>
<div class="notice">
<%= flash[:notice] %>
</div>
<% end %>

flash.keep is a method applied to flash an the params should be passed as argument, not array:
flash.keep(:notice)
http://guides.rubyonrails.org/action_controller_overview.html#the-flash
And the source code:
http://api.rubyonrails.org/classes/ActionDispatch/Flash/FlashHash.html#method-i-keep

Related

Rendering 'form' is giving me an ArgumentError

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

How to combine a <div> with a Rails "link_to"?

I am creating a "to-do website". Users can log in and generate tasks as well as notes. The tasks work perfectly but I have some issues with notes for some reason. I don't use any partials for notes. If I use this on my index.html.erb as I did for the tasks:
<div class="notes">
<%= link_to 'New Note', new_note_path %>
<div class="note">
<div>
<%= link_to note_path(note) do %>
<%= note.content %>
<%= link_to 'X', note, :class => 'task-destroy', method: :delete, data: {confirm: 'Are you sure?'} %>
<% end %>
</div>
<div>
<%= link_to edit_note_path(note) do %>
<%= time_ago_in_words(note.updated_at) %> ago
<% end %>
</div>
</div>
</div>
I get:
"NameError in NotesController#index" - "undefined local variable or
method `note' for #..."
notes_controller.rb
class NotesController < ApplicationController
before_action :logged_in_user
before_action :set_note, only: [:show, :edit, :update, :destroy]
def index
#notes = current_user.notes
end
def show
end
def new
#note = Note.new
end
def edit
end
def create
#note = current_user.notes.new(note_params)
if #note.save
flash[:success] = "You successfully created a Note!"
redirect_to notes_path
else
render 'new_note_path'
end
end
def update
#note.update(note_params)
if #note.save
flash[:success] = "You successfully updated a Note!"
redirect_to notes_path
else
render 'edit_note_path'
end
end
def destroy
#note.destroy
flash[:success] = "You successfully deleted a Note!"
redirect_to notes_path
end
private
def set_note
#note = Note.find(params[:id])
end
def note_params
params.require(:note).permit(:content)
end
end
Question: What is wrong with my instance variable on my controller and how can I make it work?
add loop before <div class="note"> to loop through list of notes stored in #notes in your index action.
Html should look like this:
<% #notes.each do |note| %>
<div class="note">
<div>
<%= link_to note_path(note) do %>
<%= note.content %>
<%= link_to 'X', note, :class => 'task-destroy', method: :delete, data: {confirm: 'Are you sure?'} %>
<% end %>
</div>
<div>
<%= link_to edit_note_path(note) do %>
<%= time_ago_in_words(note.updated_at) %> ago
<% end %>
</div>
</div>
</div>
<% end %>
Your index.html.erb view doesn't have access to a note variable.
The instance variable from the following method is the only variable being passed to the view:
def index
#notes = current_user.notes
end
You would probably need to do something like,
<% #notes.each do |n| >
<%= link_to(n) >
<% end >

adding my comment system to the index page

i have a comment system associated to a shipment model in my app where a user can have many shipments and a shipment can have many comments.
Everything is working perfectly the only problem is that i want my whole comment system to be shown in the index page of my model currently it is in the show page.
when i try to put it on the index page i get an error:
undefined method `comments' for nil:NilClass
My Controllers
shipment_controller.rb
class ShipmentsController < ApplicationController
before_action :set_shipment, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!
# GET /shipments
# GET /shipments.json
def index
#shipments = Shipment.all
end
# GET /shipments/1
# GET /shipments/1.json
def show
#comments = Comment.where(shipment_id: #shipment)
end
# GET /shipments/new
def new
#shipment = Shipment.new
end
# GET /shipments/1/edit
def edit
end
# POST /shipments
# POST /shipments.json
def create
#shipment = current_user.shipments.new(shipment_params)
respond_to do |format|
if #shipment.save
format.html { redirect_to #shipment, notice: 'Shipment was successfully created.' }
format.json { render :show, status: :created, location: #shipment }
else
format.html { render :new }
format.json { render json: #shipment.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /shipments/1
# PATCH/PUT /shipments/1.json
def update
respond_to do |format|
if #shipment.update(shipment_params)
format.html { redirect_to #shipment, notice: 'Shipment was successfully updated.' }
format.json { render :show, status: :ok, location: #shipment }
else
format.html { render :edit }
format.json { render json: #shipment.errors, status: :unprocessable_entity }
end
end
end
# DELETE /shipments/1
# DELETE /shipments/1.json
def destroy
#shipment.destroy
respond_to do |format|
format.html { redirect_to shipments_url, notice: 'Shipment was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_shipment
#shipment = Shipment.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def shipment_params
params.require(:shipment).permit(:name, :description, :from, :to, :date, :pay)
end
end
comments_controller.rb
class CommentsController < ApplicationController
before_action :authenticate_user!
def create
#shipment = Shipment.find(params[:shipment_id])
#comment = Comment.create(params[:comment].permit(:content))
#comment.user_id = current_user.id
#comment.shipment_id = #shipment.id
if #comment.save
redirect_to shipment_path(#shipment)
else
render 'new'
end
end
end
My routes
Rails.application.routes.draw do
devise_for :users, :controllers => {:registrations => "registrations"}
resources :shipments do
resources :comments
end
root 'shipments#index'
end
Shipment View
show.html.erb
<p id="notice"><%= notice %></p>
<p>
<strong><%= current_user.full_name %></strong>
</p>
<p>
<strong>Description:</strong>
<%= #shipment.description %>
</p>
<p>
<strong>From:</strong>
<%= #shipment.from %>
</p>
<p>
<strong>To:</strong>
<%= #shipment.to %>
</p>
<p>
<strong>Date:</strong>
<%= #shipment.date %>
</p>
<p>
<strong>Pay:</strong>
<%= #shipment.pay %>
</p>
<div id="comments">
<h2 class="comment_count">
<%= pluralize(#shipment.comments.count, "comment") %>
</h2>
<% #comments.each do |comment| %>
<div class="comment">
<p class="full_name">
<%= comment.user.full_name %>
</p>
<p class="content">
<%= comment.content %>
</p>
</div>
<% end %>
<%= render "comments/form" %>
</div>
<%= link_to 'Edit', edit_shipment_path(#shipment) %> |
<%= link_to 'Back', shipments_path %>
Comments View render
_form.html.erb
<%= simple_form_for([#shipment, #shipment.comments.build]) do |f| %>
<%= f.input :content, label: "Reply to thread" %>
<%= f.button :submit, class: "button" %>
<% end %>
index.html.erb without comments
<h1>Listing Shipments</h1>
<%= link_to "Post a new Shipment", new_shipment_path, class: "btn btn-success" %>
<% #shipments.each do |shipment| %>
<div class="shipment">
<h3><strong><%= shipment.user.full_name%></strong></h3>
<h5><strong>DESCRIPTION: </strong><%= shipment.description %></h5>
<div class="meta">
<%= link_to time_ago_in_words(shipment.created_at) + " ago" %> |
<%= link_to "show", shipment %>
<span class="admin">
| <%= link_to "Edit", edit_shipment_path(shipment) %> |
<%= link_to "Delete", shipment, method: :delete, data: { confirm: "Hey! Are you sure! You wanna delete this shipment??"} %>
</span>
</div>
</div>
<% end %>
index.html.erb with comment system
<h1>Listing Shipments</h1>
<%= link_to "Post a new Shipment", new_shipment_path, class: "btn btn-success" %>
<% #shipments.each do |shipment| %>
<div class="shipment">
<h3><strong><%= shipment.user.full_name%></strong></h3>
<h5><strong>DESCRIPTION: </strong><%= shipment.description %></h5>
<div class="meta">
<%= link_to time_ago_in_words(shipment.created_at) + " ago" %> |
<%= link_to "show", shipment %>
<span class="admin">
| <%= link_to "Edit", edit_shipment_path(shipment) %> |
<%= link_to "Delete", shipment, method: :delete, data: { confirm: "Hey! Are you sure! You wanna delete this shipment??"} %>
</span>
</div>
</div>
<div id="comments">
<h2 class="comment_count">
<%= pluralize(#shipment.comments.count, "comment") %>
</h2>
<% #comments.each do |comment| %>
<div class="comment">
<p class="full_name">
<%= comment.user.full_name %>
</p>
<p class="content">
<%= comment.content %>
</p>
</div>
<% end %>
<%= render "comments/form" %>
<% end %>
After Pavan's Answer
Error
ActiveRecord::RecordNotFound (Couldn't find Shipment with 'id'=):
app/controllers/shipments_controller.rb:9:in `index'
Rendered C:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/actionpack-4.2.3
/lib/action_dispatch/middleware/templates/rescues/_source.erb (1.0ms)
Rendered C:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/actionpack-4.2.3
/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb (3.0ms)
Rendered C:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/actionpack-4.2.3
/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb
(1.0ms)
Rendered C:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/actionpack-4.2.3
/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb within re
scues/layout (36.0ms)
Rendered C:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/web-console-2.2.
1/lib/web_console/templates/_markup.html.erb (1.0ms)
You've got an ivar #comments that doesn't appear to be defined...Try #shipment.comments.each
I want my whole comment system to be shown in the index page of my
model currently it is in the show page
You need to loop through #shipments in the index view like below
<% #shipments.each do |shipment| %>
<% shipment.comments.each do |comment| %>
----rest of the code---
<% end %>
<% end %>
Update:
You are getting the error here in this line <%= pluralize(#shipment.comments.count, "comment") %>. You just need to change it to
<%= pluralize(shipment.comments.count, "comment") %>
And you need to modify the comments iteration part like I said above.

Incorrect path in form_for helper

I can't figure out how to correctly write a url path in form_for for creating a new object. I tried to do it different ways, but no luck. I suppose there is some particular form of url's that can include objects' id's.
views/tasks/new.html
<%= form_for :task, url: [#task.user, #task] do |f| %>
<p>
<%= f.label :title %><br>
<%= f.text_field :title %>
</p>
<p>
<%= f.label :description %><br>
<%= f.text_area :description %>
</p>
<p>
<%= f.hidden_field :user_id, value: params[:user_id] %>
<%= f.submit %>
</p>
<% end %>
rake routes
controllers/tasks_controller.rb
class TasksController < ApplicationController
before_filter :authorize, only: [:edit, :new, :destroy]
def index
#tasks = Task.where(user_id: params[:user_id])
end
def show
#task = Task.find(params[:id])
redirect_to users_path
end
def edit
#task = Task.find(params[:id])
end
def new
#task = Task.new
end
def create
#task = Task.new(task_params)
if #task.save
redirect_to #task
else
render 'new'
end
end
def update
#task = Task.find(params[:id])
if #task.update(task_params)
redirect_to #task
else
render 'edit'
end
end
def destroy
#task = Task.find(params[:id])
#task.destroy
respond_to {|format| format.js }
end
private
def task_params
params.require(:task).permit(:title, :description)
end
end
views/tasks/index.html
<p align="right"><%= link_to 'Users', users_path %> <%= link_to 'Tasks', user_tasks_path %></p>
<h3>Tasks database</h3>
<table>
<% #tasks.each do |task| %>
<tr id="task_<%= task.id %>">
<td>
<b>Title:</b>
<i> <%= task.title %></i>
</td>
<td>
<b>Description: </b>
<i><%= task.description %></i>
</td>
<td>
<%= link_to 'Edit', edit_user_task_path(task.user, id: task.id) %>
</td>
<td>
<%= link_to 'Delete', user_task_path(task.user, id: task.id),
data: { confirm: 'Are you sure?' }, :method => :delete, remote: true %>
</td>
</tr>
<% end %>
<tr>
<td><%= link_to 'Create task', new_user_task_path %></td>
<td><%= link_to 'Back to Users', users_path %></td>
</tr>
</table>
Can anybody help?
You have nested_routes for tasks and users, so changing your form_for like below should solve your problem
<%= form_for [current_user, #task] do |f| %>
Please can you try this:
<%= form_for([current_user, #task]) do |f| %>
<p>
<%= f.label :title %><br>
<%= f.text_field :title %>
</p>
<p>
<%= f.label :description %><br>
<%= f.text_area :description %>
</p>
<p>
<%= f.hidden_field :user_id, value: params[:user_id] %>
<%= f.submit %>
</p>
Seeing the routes it seems that you need to allow either the admin/user to create tasks for any user. So for this first add a before_action in your controller:
before_action :find_user
def find_user
#user = User.find(params[:user_id])
end
Then in you form do it like:
<%= form_for [#user, #task] do |f| %>
Then in the create action of your controller do it like:
def create
#task = #user.tasks.build(task_params)
if #task.save
redirect_to #task
else
render 'new'
end
end
The above can be used when you need to save tasks for many user and if you need that only the current_user tasks should be saved you can go with the above answers.

errors uploading a file "name cant be blank"

I am trying to add the option to upload and download files in my Rails application, but I keep getting this error when I try to upload my file:
name can't be blank
Here's my code:
newsletters_controller.rb:
class NewslettersController < ApplicationController
def index
#newsletters = Newsletter.all
end
def new
#newsletter = Newsletter.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #newsletter }
end
end
def create
#newsletter = Newsletter.new(newsletter_params)
if #newsletter.save
redirect_to newsletters_path, notice: "The newsletter #{#newsletter.name} has been uploaded."
else
render "new"
end
end
def destroy
#newsletter = Newsletter.find(params[:id])
#newsletter.destroy
redirect_to newsletters_path, notice: "The newsletter #{#newsletter.name} has been deleted."
end
private
def newsletter_params
params.require(:newsletter).permit(:newsletter, :attachment)
end
end
index.html.erb:
<% if !flash[:notice].blank? %>
<div class="alert alert-info">
<%= flash[:notice] %>
</div>
<% end %>
<br />
<%= link_to "New Newsletter", new_newsletter_path, class: "btn btn-primary" %>
<br />
<br />
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Name</th>
<th>Download Link</th>
<th> </th>
</tr>
</thead>
<tbody>
<% #newsletters.each do |newsletter| %>
<tr>
<td><%= newsletter.name %></td>
<td><%= link_to "Download Newsletter", newsletter.attachment_url %></td>
<td><%= button_to "Delete", newsletter, method: :delete, class: "btn btn-danger", confirm: "Are you sure that you wish to delete #{newsletter.name}?" %></td>
</tr>
<% end %>
</tbody>
</table>
new.html.erb:
<% if !#newsletter.errors.empty? %>
<div class="alert alert-error">
<ul>
<% #newsletter.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="well">
<%= form_for #newsletter, html: { multipart: true } do |f| %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.label :attachment %>
<%= f.file_field :attachment %>
<%= f.submit "Save", class: "btn btn-primary" %>
<% end %>
</div>
routes.rb:
resources :newsletters, only: [:index, :new, :create, :destroy]
root "newsletters#index"
get "newsletters/index"
get "newsletters/new"
get "newsletters/create"
get "newsletters/destroy"
change:
params.require(:newsletter).permit(:newsletter, :attachment)
to:
params.require(:newsletter).permit(:newsletter, :attachment, :name)
This way, the model will receive the name from the form and validation will succeed.

Resources