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.
Related
I've had an existing comment form on a resource show.html.erb that I want to be added to the show page without having to reload the entire page. I understand that with ajax via the 'form_with' form, this should be entirely possible.
My issue is that whilst the form does create a new comment, it only appears after I refresh the page.
I also get the following error.
ArgumentError (too few arguments):
app/controllers/comments_controller.rb:18:in 'format'
app/controllers/comments_controller.rb:18:in 'create'
comments_controller
class CommentsController < ApplicationController
before_action :load_commentable
before_action :authenticate_user!
before_action :comment_auth, only: [:edit, :update, :destroy]
...
def create
#comment = #commentable.comments.new(allowed_params)
#comment.user_id=current_user.id if current_user
if #comment.save
format.html { redirect_to #commentable, notice: "Comment added." }
format.js
else
render 'edit'
end
...
views/comments/create.js.coffee
comment = document.getElementById("comment")
comment.innerHTML = "<%= j render(#comment) %>"
views/comments/_form.html.erb
<%= form_with(model: [#commentable, #comment]) do |f| %>
<% if #comment.errors.any? %>
<div class="error_messages">
<h2>Please correct the following errors.</h2>
<ul>
<% #comment.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<p>
<strong><%= f.label :name, :class=>'form-label' %></strong><br>
<%= f.text_field :name, value: current_user.fname, readonly: true, :class=>'form-control' %>
</p>
<p>
<strong><%= f.label :title, :class=>'form-label' %></strong><br>
<%= f.text_field :title, :class=>'form-control' %>
</p>
<p>
<strong><%= f.label :review, :class=>'form-label' %></strong><br>
<%= f.text_area :body, :class=>'form-control', rows: 5 %>
</p>
<p>
<%= f.submit :class=>'btn btn-success' %>
</p>
<% end %>
For me, I needed
<%= form_with(model: #message, method: :post, local: true) do |f| %>
local: true was necessary. All other combos didn't work remote: true, remote: false, local: false
as you know, form_with it's a remote form, you should not use redirect_to there. Please remove your block
if #comment.save
format.html { redirect_to #commentable, notice: "Comment added." }
format.js
else
render 'edit'
end
replace it to
if #comment.save
#status = "success"
end
And you can add a notice message to your views/comments/create.js.erb (it's not .js.coffee) with condition of #status (failed/success).
Hope this helps.
Trying to figure out the edit path within _comment.html.erb file.
Keep getting this error:
ActiveRecord::RecordNotFound in CommentsController#edit
Couldn't find Article with 'id'=#<Comment::ActiveRecord_Associations_CollectionProxy:0x007fcac37359e8>
Don't know how to figure how to write the correct path.
Comments Controller
class CommentsController < ApplicationController
def create
#article = Article.find(params[:article_id])
#comment = #article.comments.create(comment_params)
redirect_to article_path(#article)
end
def show
#article = Article.find(params[:article_id])
#comment = #article.comments.find(params[:id])
end
def edit
#article = Article.find(params[:article_id])
#comment = #article.comments.find(params[:id])
end
def destroy
#article = Article.find(params[:article_id])
#comment = #article.comments.find(params[:id])
#comment.destroy
redirect_to article_path(#article)
end
private
def comment_params
params.require(:comment).permit(:commenter, :body)
end
end
_comment.html.erb
<p>
<strong>Commenter:</strong>
<%= comment.commenter %>
</p>
<p>
<strong>Comment:</strong>
<%= comment.body %>
</p>
<p>
<%= link_to 'Edit', edit_article_comment_path(#article.comments, comment) %>
</p>
<p>
<%= link_to 'Show', [comment.article, comment] %>
</p>
<p>
<%= link_to 'Destroy Comment', [comment.article, comment],
method: :delete,
data: { confirm: 'Are you sure?' } %>
</p>
routes
resources :articles do
resources :comments
end
How do I write the correct path?
Also, the earlier path I had was this:
<%= link_to 'Edit', edit_article_comment_path(#article, comment) %>
But it would turn up a blank edit form, ie, none of the text boxes had anything filled in ... hence why I tried the other path.
Any help would be appreciated.
Thank you.
Comment _form.html.erb
<%= form_for([#article, #article.comments.build]) do |f| %>
<p>
<%= f.label :commenter %><br>
<%= f.text_field :commenter %>
</p>
<p>
<%= f.label :body %><br>
<%= f.text_area :body %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
Article show.html.erb
<p>
<strong>Title:</strong>
<%= #article.title %>
</p>
<p>
<strong>Text:</strong>
<%= #article.text %>
</p>
<h2>Comments</h2>
<%= render #article.comments %>
<h2>Add a comment:</h2>
<%= render 'comments/form' %>
<%= link_to 'Edit', edit_article_path(#article) %> |
<%= link_to 'Back', articles_path %>
There's a problem in _comment.html.erb
<%= link_to 'Edit', edit_article_comment_path(#article.comments, comment) %>
It should be
<%= link_to 'Edit', edit_article_comment_path(#article, comment) %>
But it would turn up a blank edit form, ie, none of the text boxes had anything filled in
You should check if you are passing the proper values in form_for
<%= form_for [#article, #comment] do |f| %>
EDIT2
Well the problem is you are passing new instance of comment every time, Even with the edit action. That's why you are not getting any values in the form
<%= form_for([#article, #article.comments.build]) do |f| %>
Change it to
<%= form_for([#article, #comment]) do |f| %>
And make sure you are assigning #article and #comment in both new and edit action of CommentsController or from wherever you are rendering the comments/_form
class CommentsController < ApplicationController
def new
#article = Article.find(params[:article_id])
#comment = #article.comments.new
end
def edit
#article = Article.find(params[:article_id])
#comment = #article.comments.find(params[:id])
end
#...
end
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 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
Sorry about the repetition, I could not find the answers to my questions after a lot of searches. The will_paginate does not work after the Ajax call.
After delete action, It does not display the pages numbers at all (it simply returns all results).
After search action, the page number does not update, it shows more pages than what should actually be there.
Here is the controller code.
class CitiesController < ApplicationController
def index
#cities = City.get_cities(params[:city_name],params[:city_population]).paginate(:page => params[:page])
respond_to do |format|
format.html
format.js
end
end
def create
#city = City.new(params[:city])
if #city.save
flash[:success] = "City information saved successfully"
redirect_to cities_path
else
render 'index'
end
end
def new
#city = City.new
end
def destroy
#city = City.find(params[:id]).destroy
#city.destroy
#cities = City.all
respond_to do |format|
format.html {redirect_to cities_path}
format.js
end
end
end
Here is the index view:
<div class="row">
<h1>Search Cities or <%= link_to "Create New City", new_city_path %></h1>
<h3>99 random city information are generated in the database </h2>
<h3>Simply type any letter or city population between 0 and 10 to filter out</h3>
<%= form_tag "/cities/index", method: :get, remote: true do %>
<%= label_tag(:q, "City Name:") %>
<%= text_field_tag 'city_name' %>
<%= label_tag(:q, "City Population greater than, in units of 1 million:") %>
<%= text_field_tag 'city_population' %>
<label></label>
<%= button_tag("Search", :class => "btn") %>
<% end %>
<% flash.each do |key, value| %>
<div class="alert alert-<%= key %>"><%= value %></div>
<% end %>
<div id='table' class="table table-striped">
<%= render 'table' %>
</div>
<%=will_paginate #cities %>
</div>
Here is the partial view of the table:
<div class="row">
<h1>Enter City descriptions or <%= link_to "Search Cities", cities_path %></h1>
<%= form_for #city, html: {multipart: true} do |f| %>
<%= f.label :city_name %>
<%= f.text_field :city_name %>
<%= f.label :city_description %>
<%= f.text_field :city_description %>
<%= f.label :city_population_in_units_of_millions %>
<%= f.text_field :city_population %>
<label></label>
<%= f.file_field :image%>
<label></label>
<%= f.submit "Create new City", :class => "btn"%>
<% end %>
</div>
Finally two js.erb codes associated with index and delete actions:
index.js.erb:
$('#table').html('<%= escape_javascript(render('table')) %>');
destroy.js.erb:
$('#table').html('<%= escape_javascript(render('table')) %>');
Found the solution by myself.
add <%= will_paginate #cities %> into partial file
and change #cities = City.all to
#cities = City.all.paginate(page: params[:page])
because will_paginate does not expect an array of objects.
write in your controller
def index
#cities = City.get_cities(params[:city_name],params[:city_population]).paginate(:page => params[:page])
respond_to do |format|
format.html
format.js
end
end
in your view folder create index.js.erb and write
$('id or class').html('<%=escape_javascript render :partial => which part you update %>')