Display form's message by remote method using ujs on Rails - ruby-on-rails

I followed the episode http://railscasts.com/episodes/136-jquery-ajax-revised
and create my cusotm example.
I put the create form in the index, and create a book by remote method
But I have no idea how to put error message in the page.
please give me some example , thanks~
index
<%= render 'form' %>
<p>
<table id='books_tbl' class="table">
<th>id</th>
<th>title</th>
<th>ISBN</th>
<th>sn</th>
<th>price</th>
<th>Functions</th>
<div class="books" id="books">
<%= render #existed_books %>
</div>
</table>
the controller
# POST /books
# POST /books.json
def create
#book = Book.new(params[:book])
respond_to do |format|
if #book.save
format.html { redirect_to #book, notice: 'Book was successfully created.' }
format.json { render json: #book, status: :created, location: #book }
format.js
else
format.html { render action: "new" }
format.json { render json: #book.errors, status: :unprocessable_entity }
format.js
end
create.je.erb
<% unless #book.save %>
<% else %>
$('#books_tbl tr:last').after('<%= j render(#book) %>');
<% end %>

First, change your books_controller so that it will always render create.js.erb whether the book is persisted or not.
def create
#book = Book.new(params[:book])
respond_to do |format|
if #book.save
format.html { redirect_to #book, notice: 'Book was successfully created.' }
format.json { render json: #book, status: :created, location: #book }
else
format.html { render action: "new" }
format.json { render json: #book.errors, status: :unprocessable_entity }
end
format.js
end
end
Then, in you create.js.erb, you will want to check whether your book is persited? or not:
<% if #book.persisted? %>
# ...
<% else %>
# display the error message
<% end %>
Let's say we are going to display the error message in a <p> with the .errors class:
$('<p>').text('<%= #book.errors.full_messages.to_sentence.capitalize %>')
.prepend('form');
The thing is that you will have to remove the errors paragraph every time you render create.js.erb so that former errors won't stick around:
$('p.errors').remove();
All in all, it gives:
$('p.errors').remove();
<% if #book.persisted? %>
# ...
<% else %>
$('<p>').text('<%= #book.errors.full_messages.to_sentence.capitalize %>')
.prepend('form')
<% end %>

Related

Rails form with remote: true reloads the page

In my Rails 5.1 app i have 2 controllers: home_controller and posts_controller which i created with the scaffold tool, so what i'm doing is rendering the partial _form.html.haml in the index view of my home_controller.rb like this: (by the way i'm using haml)
.top-space
.row.center-xs
.col-xs-8.col-md-10
.row
.col-sm-3.col-lg-2.col-xs-10.top-space
%ul.no-bullets.text-left
%li=link_to "Explore", "#"
%li=link_to "Suggestions", "#"
.col-sm.col-xs-10
=render "posts/form"
#posts
i added remote: true to the form like this:
= form_for #post, remote: true do |f|
- if #post.errors.any?
#error_explanation
%h2= "#{pluralize(#post.errors.count, "error")} prohibited this post from being saved:"
%ul
- #post.errors.full_messages.each do |message|
%li= message
.mdl-textfield.mdl-js-textfield.full-width
= f.text_area :body, class:"mdl-textfield__input", row:3
= f.label :body, "Write something",class:"mdl-textfield__label"
.actions.text-right
= f.submit 'Save',class:"mdl-button mdl-js-button mdl-button--raised mdl-button--colored"
as you can see it has remote: true but when i submit the form it takes me to the show view in my posts_controller,
this is my posts_controller:
def create
#post = current_user.posts.new(post_params)
respond_to do |format|
if #post.save
format.html { redirect_to #post}
format.json { render :show, status: :created, location: #post }
else
format.html { render :new }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
i created a show.js.coffee to show the post created in a <div id="posts"> below the form
$('#posts').append('<%= j render #post %>')
Basically what i want is to show the post created below the form without reloading the page or taking me to show view in my posts_controller.
What am i doing wrong and how can i achieve this?
Try to set your create action like this maybe:
def create
#post = current_user.posts.new(post_params)
respond_to do |format|
if #post.save
format.js
format.html { redirect_to #post}
format.json { render :show, status: :created, location: #post }
else
format.js
format.html { render :new }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
i have just added format.js

Issue with has_and_belongs_to_many association in rails

Can you help a noob, please?
I have 2 models - Player and Poker Tables, which have has_and_belongs_to_many association. When i try create player i catch error
undefined method `poker_table'
respond_to do |format|
**if #player.save**
format.html { redirect_to #player, notice: 'Player was successfully created.' }
format.json { render :show, status: :created, location: #player }
else
I use checkboxes for mark needed poker tables, here form code:
<% #poker_tables = PokerTable.all %>
<% #poker_tables.each do |poker_table| %>
<div>
<%= check_box_tag "player[poker_table_ids][]", poker_table.id %>
<%= poker_table.name %>
<%= poker_table.actual_time %>
</div>
<% end %>
create method and params
def create
#player = Player.new(player_params)
respond_to do |format|
if #player.save
format.html { redirect_to #player, notice: 'Player was successfully created.' }
format.json { render :show, status: :created, location: #player }
else
format.html { render :new }
format.json { render json: #player.errors, status: :unprocessable_entity }
end
end
end
def player_params
params.require(:player).permit(:email, :poker_table_ids => [])
end
I can create poker table, but couldn't create a player with associated poker tables.
I don't really understand what I'm doing wrong. I studied a lot of resources about this theme, but i can't find answer.

When a Post comment is made, no more can be created, only shown

I am trying to get a post and comment system working, for this however i want only one comment to be made per post. Only as i am trying to create a system as where content will be displayed followed by a comment 7 times in one post... Example...
program model 1 body content 1
Commentmodel1
program model 1 body content 2
Commentmodel2
program model 1 body content 3
Commentmodel3
.etc.etc.
For Me this is the simplest way of being able todo this by creating 7 different comment models, i know there is probably an easier way but as im new this seems the simplest. However i am struggling getting the one comment model to only allow just one comment to be made.
In this application coach is the user.
Here are the files involved, For the Models, program is the basic Post model, and comments is comments.
programs/Show.html.erb
<p id="notice"><%= notice %></p>
<p>
<b>Title:</b><br />
<%= #program.title %>
</p>
<p>
<b>Body:</b><br />
<%= #program.cweekcomments %>
</p>
<%= link_to 'Edit', edit_program_path(#program) %> |
<%= link_to 'Back', programs_path %>
<br /><br /><br />
<i>Comments</i>
<% #program.comments.each do |comment| %>
<p>
<b>Comment:</b>
<% if comment %>
<%= comment.body %>
<br />
<%= link_to 'Edit', edit_program_comment_path(#program, comment) %> | <%= link_to 'Destroy', [#program, comment] , method: :delete, data: { confirm: 'Are you sure?' } %>
<% else %>
<%= form_for([#program, #program.comments.build]) do |f| %>
<div class="field">
<%= f.label :body %><br />
<%= f.text_area :body %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
<% end %>
</p>
<% end %>
Programs_controller.rb
class ProgramsController < ApplicationController
before_filter :authenticate_coach!, :except => [:show]
# GET /programs
# GET /programs.json
def index
#programs = Program.find_all_by_coach_id(current_coach[:id])
respond_to do |format|
format.html # index.html.erb
format.json { render json: #programs }
end
end
# GET /programs/1
# GET /programs/1.json
def show
#program = Program.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #program }
end
end
# GET /programs/new
# GET /programs/new.json
def new
#program = Program.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #program }
end
end
# GET /programs/1/edit
def edit
#program = Program.find(params[:id])
end
# POST /programs
# POST /programs.json
def create
#program = Program.new(params[:program])
respond_to do |format|
if #program.save
format.html { redirect_to #program, notice: 'Program was successfully created.' }
format.json { render json: #program, status: :created, location: #program }
else
format.html { render action: "new" }
format.json { render json: #program.errors, status: :unprocessable_entity }
end
end
end
# PUT /programs/1
# PUT /programs/1.json
def update
#program = Program.find(params[:id])
respond_to do |format|
if #program.update_attributes(params[:program])
format.html { redirect_to #program, notice: 'Program was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #program.errors, status: :unprocessable_entity }
end
end
end
# DELETE /programs/1
# DELETE /programs/1.json
def destroy
#program = Program.find(params[:id])
#program.destroy
respond_to do |format|
format.html { redirect_to programs_url }
format.json { head :no_content }
end
end
end
Comments_controller.rb
class CommentsController < ApplicationController
def new
#comment = #program.comments.build
end
def create
#program = Program.find(params[:program_id])
#comment = #program.comments.create(params[:comment])
redirect_to program_path(#program)
end
def destroy
#program = Program.find(params[:program_id])
#comment = #program.comments.find(params[:id])
#comment.destroy
redirect_to program_path(#program)
end
def edit
#program = Program.find(params[:program_id])
#comment = #program.comments.find(params[:id])
end
def update
#program = Program.find(params[:program_id])
#comment = #program.comments.find(params[:id])
respond_to do |format|
#if #program.comments.update_attributes(params[:comment])
if #comment.update_attributes(params[:comment])
format.html { redirect_to program_path(#program), 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
end
In advance, thanks for your help, much appreciated!
Change your program comment relation to has_one.(has_one :comment in your program.rb)
def create
#program = Program.find(params[:program_id])
if #program.comment
flash[:error] = "Cannot comment more than once"
else
#comment = #program.comments.create(params[:comment])
flash[:notice] = "Comment created"
end
redirect_to program_path(#program)
end

redirect using a form

this form (views/workers/_form.html.erb) redirects me to the index of tasksadmins, after I push the 'create tasksadmin' button.
I want it to redirect me to "workers/index" and change the button to 'update the task'.
how can I do that please?
<%= form_for(#tasksadmin) do |f| %>
<% if #tasksadmin.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#tasksadmin.errors.count, "error") %> prohibited this tasksadmin from being saved:</h2>
<ul>
<% #tasksadmin.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<%= f.hidden_field :admin_mail, :value => #tasksadmin.admin_mail %>
<%= f.hidden_field :worker_mail, :value => #worker_mail %>
<%= f.hidden_field :task, :value => #tasksadmin.task %>
<div class="field">
<%= f.label :done %><br />
<%= f.check_box :done %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
and this is my workers_controller:
class WorkersController < ApplicationController
# GET /workers
# GET /workers.json
def index
#tasks_worker = Tasksadmin.where(:worker_mail => "alon.shmiel#gmail.com")
respond_to do |format|
format.html # index.html.erb
format.json { render json: #workers }
end
end
# GET /workers/1
# GET /workers/1.json
def show
#task_worker = Tasksadmin.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #worker }
end
end
# GET /workers/new
# GET /workers/new.json
def new
#worker = Worker.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #worker }
end
end
# GET /workers/1/edit
def edit
#tasksadmin = Tasksadmin.find(params[:id])
#worker_mail = "alon.shmiel#gmail.com"
end
# POST /workers
# POST /workers.json
def create
#worker = Worker.new(params[:worker])
respond_to do |format|
if #worker.save
format.html { redirect_to "#worker", notice: 'Worker was successfully created.' }
format.json { render json: #worker, status: :created, location: #worker }
else
format.html { render action: "new" }
format.json { render json: #worker.errors, status: :unprocessable_entity }
end
end
end
# PUT /workers/1
# PUT /workers/1.json
def update
#worker = Tasksadmin.find(params[:id])
respond_to do |format|
if #worker.update_attributes(params[:worker])
format.html { render action: "index", notice: 'Worker was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #worker.errors, status: :unprocessable_entity }
end
end
end
# DELETE /workers/1
# DELETE /workers/1.json
def destroy
#worker = Tasksadmin.find(params[:id])
#worker.destroy
respond_to do |format|
format.html { render action: "index" }
format.json { render json: #worker }
end
end
end
In your controller, you have to redirect to the appropriate path like so:
def update
redirect_to "workers/index"
end
I would suggest using path helpers so if you have your routes set up as resources, you can do this:
redirect_to workers_path
As for changing the the button text, just change it to:
f.submit("update the task")
You create a form for an object #tasksadmin, which in your WorkersController#edit is set as follows:
#tasksadmin = Tasksadmin.find(params[:id]
This means that that parameter contains an object of class Tasksadmin, if you let rails build the path for the a Tasksadmin, it will send you to the TasksadminsController#update, and that is why your code does not work. You never get to the WorkersController#update. Check your logs to verify that.
Let me be very clear about this: you should not edit Tasksadmin objects in the WorkersController.
I do not understand why you would do that.

Ruby - error rendering a view referencing a loop that I never wrote

I have this controller:
class AlexesController < ApplicationController
# GET /alexes
# GET /alexes.json
def index
##alexes = Alex.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #alexes }
end
end
# GET /alexes/1
# GET /alexes/1.json
def show
# #alex = Alex.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #alex }
end
end
# GET /alexes/new
# GET /alexes/new.json
def new
#alex = Alex.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #alex }
end
end
# GET /alexes/1/edit
def edit
#alex = Alex.find(params[:id])
end
# POST /alexes
# POST /alexes.json
def create
#alex = Alex.new(params[:alex])
respond_to do |format|
if #alex.save
format.html { redirect_to #alex, notice: 'Alex was successfully created.' }
format.json { render json: #alex, status: :created, location: #alex }
else
format.html { render action: "new" }
format.json { render json: #alex.errors, status: :unprocessable_entity }
end
end
end
# PUT /alexes/1
# PUT /alexes/1.json
def update
#alex = Alex.find(params[:id])
respond_to do |format|
if #alex.update_attributes(params[:alex])
format.html { redirect_to #alex, notice: 'Alex was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #alex.errors, status: :unprocessable_entity }
end
end
end
# DELETE /alexes/1
# DELETE /alexes/1.json
def destroy
#alex = Alex.find(params[:id])
#alex.destroy
respond_to do |format|
format.html { redirect_to alexes_url }
format.json { head :no_content }
end
end
end
It gets called when this link gets pressed:
<%= link_to "Alex Link", alexes_path(#alex) %>
so I am assuming that the get-all part of the controller would get invoked, and I commented out lines in the controller that I thought would get invoked, but I still get this error:
undefined method `each' for nil:NilClass
from line 10:
7: <th></th>
8: </tr>
9:
10: <% #alexes.each do |alex| %>
11: <tr>
12: <td><%= link_to 'Show', alex %></td>
13: <td><%= link_to 'Edit', edit_alex_path(alex) %></td>
Any idea where the problem is happening?
Thanks!
<%= link_to "Alex Link", alexes_path(#alex) %>
=>
<%= link_to "Alex Link", alex_path(#alex) %>
or
<%= link_to "Alex Link", #alex %>

Resources