Rendering 'form' is giving me an ArgumentError - ruby-on-rails

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

Related

NoMethodError in Admin::Posts#index

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 .

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.

Show a form if no search results found Sunspot Solr Rails 3

I am using Sunspot and Solr to full text search my rails app. I am trying to figure out how to show a form (or a link) when no search results are returned. It currently will just show my blank index page when nothing is found. Would I do this with an if/else statement?
Here is my model (dairy.rb)
class Dairy < ActiveRecord::Base
attr_accessible :title
searchable do
text :title
end
end
and controller (dairies_controller.rb)
class DairiesController < ApplicationController
before_filter :set_dairy, only: [:show, :edit, :update, :destroy]
respond_to :html
def index
#search = Sunspot.search [Dairy, Drink] do
fulltext params[:search]
end
#results = #search.results
end
def show
respond_with(#dairy)
end
def new
#dairy = Dairy.new
respond_with(#dairy)
end
def edit
end
def create
#dairy = Dairy.new(params[:dairy])
#dairy.save
respond_with(#dairy)
end
def update
#dairy.update_attributes(params[:dairy])
respond_with(#dairy)
end
def destroy
#dairy.destroy
respond_with(#dairy)
end
private
def set_dairy
#dairy = Dairy.find(params[:id])
end
end
and index (index.html.erb)
<body class="DI">
<%= form_tag dairies_path, :method => :get do %>
<p>
<%= text_field_tag :search, params[:search], style:"width:550px; height:30px;", :autofocus => true %><br>
<%= submit_tag "Search!", :name => nil, class: "btn btn-primary btn-lg", style: "margin-top:10px" %>
</p>
<% end %>
<%= link_to 'Add New Item', new_dairy_path, class: "btn btn-default" %>
<p id="notice"><%= notice %></p>
<table>
<thead>
<tr>
<th>Title</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% #results.each do |dairy| %>
<tr>
<td><%= dairy.title %></td>
<td><%= link_to 'Show', dairy %></td>
<td><%= link_to 'Edit', edit_dairy_path(dairy) %></td>
<td><%= link_to 'Destroy', dairy, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
</table>
</body>
Let me know if you need any other pages. Probably a very simply way to do what I want, but I am still learning. My real goal is to have a contact form when no search results are found. Thank you!!
def index
#search = Sunspot.search [Dairy, Drink] do
fulltext params[:search]
end
if #search.results.any?
#results = #search.results
else
return redirect_to some_path
end
end
or in the view
if #results.any?
render partial: 'list_results'
else
render partial: 'empty_results'
end

flash[:notice] not working in Rails 4 after edit/create action

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

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