This is view
<%= '<br /><br />' if flash %>
<% flash.each do |name, msg| %>
<div class="alert alert-<%= name == :notice ? "success" : name.to_s %>">
<a class="close" data-dismiss="alert">×</a>
<%= content_tag :div, msg.html_safe, :id => "flash_#{name}" if msg.is_a?(String) %>
</div>
<% end %>
<%= yield %>
This code below shows only one flash message("Deleted") on the top of the screen when after I deleted a record. Then that's how I want.
def update
if params[:destroy]
if current_user.id == #code.user_id
#code.destroy
flash[:notice] = "Deleted"
else
flash[:notice] = "You don't have permission to edit"
end
respond_to do |format|
format.html { redirect_to community_codes_url }
format.json { head :no_content }
end
else
respond_to do |format|
if #code.update_attributes(params[:code])
format.html { redirect_to community_code_path(#community.community_name, #code), notice: 'Updated' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #code.errors, status: :unprocessable_entity }
end
end
end
end
But this code below is messing up this rule, and I'm totally confused:(
If I create new record, it should show just one flash message like previous one. Then it has tweet button in it.
This flash doesn't not contain only string but also contains html and javascript within flash message.
I don't think it matters whether if there will be 2 flash messages or not:(
How can I show only one flash message?
def create
#code = #community.codes.build (params[:code])
#code.user_id = current_user.id
respond_to do |format|
if #code.save
tag_strings = #community.tags.join(", ") + "," if #community.tags
flash[:notice] = 'Tweet<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>You can tweet if you click this button'
format.html { redirect_to community_code_path(#community.community_name, #code) }
format.json { render json: [#community, #code], status: :created, location: #code }
else
format.html { render action: "new" }
format.json { render json: #code.errors, status: :unprocessable_entity }
end
end
end
In the one that only shows one message, you're writing to the notice key of the flash hash, then writing to that same key again, thereby overwriting it. In the one that shows two messages, you're writing to the notice key once, and the error key once, resulting in two keys. Then, the flash mechanism displays both. Based on the flash display mechanisms you're using, they might appear in different colors, since they're two different 'levels' of problem.
If you want to only display one, you could keep writing to the same key of the flash hash.
Related
Issue: I am looking for a way to have separate notices for different values in a tables column.
I have order_status that has 3 separate values, created, cancelled, and charged.
I would like 3 separate notices for each when the columns are changed from a view.
a view will be something like:
<%= form_for #order, remote: true do |f| %>
<%= f.hidden_field :order_status, value: "cancelled" %>
<%= f.button type:'submit', class: "btn btn-danger" %>
<% end %>
This will change the column to "cancelled".
I then want to create a method like:
def cancel_update
respond_to do |format|
if #order.update(params[:order_update])
if user_signed_in?
if #order.order_status = "cancelled"
format.html { redirect_to #order, notice: 'Order was successfully cancelled.' }
format.json { render :show, status: :ok, location: #order }
else
format.html { render :edit }
format.json { render json: #order.errors, status: :unprocessable_entity }
end
end
end
end
end
But this method didn't work how i planned. When i use this method, nothing happens when i click the button, no page reload, redirect, etc. I get the error: "The action 'update' could not be found for OrdersController"
(This was tested by taking out the original update method - which is below).
Now when i use this update method, it works but doesn't pin point the value update on the order_status only.
def update
respond_to do |format|
if #order.update(order_params)
if user_signed_in?
format.html { redirect_to #order, notice: 'Order was successfully uploaded.' }
format.json { render :show, status: :ok, location: #order }
else
format.html { render :edit }
format.json { render json: #order.errors, status: :unprocessable_entity }
end
if buyer_signed_in?
format.html { redirect_to #order, notice: 'Order was successfully updated.' }
format.json { render :show, status: :ok, location: #order }
else
format.html { render :edit }
format.json { render json: #order.errors, status: :unprocessable_entity }
end
end
end
end
Here is another attempt that somehow didn't function:
def order_cancel
respond_to do |format|
if #order.update(order_status)
format.html { redirect_to #order, notice: 'Order was successfully cancelled.' }
format.json { head :no_content }
end
end
end
private
def order_status
params.permit(:order_status)
end
How can I pin point the order_status values from the controller to allow me to have separate actions and notices when the values are changed by a end user?
Given that you use the Rails form builder to generate the form's HTML
<%= form_for #order, remote: true do |f| %>
<%= f.hidden_field :order_status, value: "cancelled" %>
I would expect that the generated name of the input field is nested under order. That said you will need to follow these nesting when permitting the params:
def order_status
params.require(:order).permit(:order_status)
end
When you are unsure how the parameters really look like you might want to have a look at the generated HTML structure of the form or you can look at the Rails logs for the update request to the application.
So, those three lines are wrong:
if #order.update(params[:order_update])
if user_signed_in?
if #order.order_status = "cancelled"
Should be:
if user_signed_in?
if #order.update(status: params[:order_status])
if #order.order_status == "cancelled"
But actually should be #order.update!(status: :cancelled) in a cancel action, or at least have a state machine to validate that the user is not messing up the states of the orders.
Or like is expected by your form, those should be in a update method (not cancel_update)
The update method you posted doesn't make sense, it has a minimum of 2 renders, I think you meant to not have the buyer_signed_in section.
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 %>
I've got a list of articles with checkboxes on a form. When a box is checked, the body of the selected article is copied into one of x text areas.
Should a user want to make a change to the body of an article in the text area I need to send that change through my controller into a new Rails model (called an Edit).
I already have the record being created, I just need the application to record the changes into a new Edit record. Here's my relevant controller code:
new
def new
#template = Template.find(params[:template])
#article_count = #template.pages-1
#doc = Doc.new
#doc.template_id = #template.id
#doc.user_id = current_user.id
#articles = current_user.brand.articles
respond_to do |format|
format.html
format.json { render json: #doc }
end
end
create
def create
#doc = Doc.new(params[:doc])
respond_to do |format|
if #doc.save
#make editable version
if current_user.brand.try(:editable?)
#doc.articles.each do |article|
#edit = Edit.new
#edit.name = article.name
#edit.video = article.video
#something here to get the bodies of the text areas
#edit.article_id = article.id
#edit.doc_id = #doc.id
#edit.user_id = current_user.id
#edit.save
end
end
#doc.create_activity :create, owner: current_user
format.html { redirect_to share_url(#doc.user.ftp, #doc) }
format.json { render json: #doc, status: :created, location: #doc }
else
format.html { render action: "new" }
format.json { render json: #doc.errors, status: :unprocessable_entity }
end
end
end
And here's the code that makes the text areas in the view.
<% #article_count.times do |article| %>
<div id="edit<%= article %>" class="tab-pane <%= "active" if article == 0 %>">
<%= text_area_tag("edit[#{article}][body]") %>
</div>
<% end %>
Records are created for each article, but I can't seem to be able to save the edits from the text areas. It's kind of a nested-form arrangement. Any help at all would be definitely appreciated. Cheers!
I've solved this by breaking the form up into two pages: one handles the selection, the second the editing. Given that a Doc has many edits, this is the method I made for part two of the form:
def edit_content
#doc = Doc.find(params[:id])
if !#doc.edits.exists?
#doc.articles.reverse.each do |article|
#doc.edits.build(:body => article.body)
end
end
end
Hope that helps someone.
I scaffolded an Authorization(user_id, code, otherparam1, ...) and I want to add a custom_create method to the authorizations_controller which only require a code, the method generating the other parameters. I need this method to work with json or be called in others methods like User.newcustom(code)
def newcustom
case request.method
when :post #post
code = params[:code]
if(code and code != '')
...
respond_to do |format|
if #authorization.save
format.html { redirect_to #authorizations, notice: 'Authorization was successfully created.' }
format.json { render json: #authorizations, status: :created, location: #authorization }
else
format.html { render action: "new" }
format.json { render json: #authorization.errors, status: :unprocessable_entity }
end
end
else #get
respond_to do |format|
format.html
end
end
Here's my newcustom.html.erb
<%= form_tag( newcustom_authorizations_path, :method => :post ) do %>
<div class="field">
<%= text_field_tag :code %>
</div>
<div class="actions">
<%= submit_tag('Get tokens') %>
</div>
<% end %>
But it doesn't work through json, the form. And calling the method newcustom(:code => code) throws me a too many arguments (1 for 0). Any idea ?
for this add the given code to config/routes.rb
resources :authorizations do
collection do
post :newcustom
end
end
Thanks for the help everyone.
I ended up solving my problem filtering the parameters of the create function, then calling my customcreate one.
AND YES I CHEAT :)
I have a form with a drop down generated from a collection_select. The collection_select starts off blank and then when the user selects a date from the date field, the collection_select is updated with values for the date that is chosen.
I'm trying to show a nice error message if the form is submitted without a value chosen in my dropdown. Currently i'm getting this error: undefined methodmap' for nil:NilClass`
How can i make it so that if the user doesn't select a value in the dropdown, I can show them a nice error message?
View
<%= form_for(#arrangement) do |f| %>
<div class="control-group">
<%= f.label :date, :class => 'control-label' %>
<div class="controls">
<%= f.text_field :date, :class => 'input-large datepicker' %>
</div>
</div>
<div class="control-group">
<%= f.label :timeslot, :class => 'control-label' %>
<div class="controls">
<%= collection_select(:arrangement, :timeslot_id, #available_timeslots, :id, :timeslot_spelled) %>
</div>
</div>
<% end %>
Controller
# GET /arrangements/new
# GET /arrangements/new.json
def new
date = Time.now.to_date.to_s(:db)
#arrangement = Arrangement.new
#available_timeslots = Timeslot.where("location_id = ? AND date(timeslot) = ? AND arrangement_id is null", current_user.user_details.location_id, date).order('timeslot ASC')
respond_to do |format|
format.html # new.html.erb
format.json { render json: #arrangement }
end
end
# POST /arrangements
# POST /arrangements.json
def create
#arrangement = Arrangement.new(params[:arrangement])
respond_to do |format|
if #arrangement.save
# update the timslot record with the arrangement id
if #timeslot = Timeslot.update(#arrangement.timeslot_id, :arrangement_id => #arrangement.id)
format.html { redirect_to #arrangement, notice: 'Arrangement was successfully created.' }
format.json { render json: #arrangement, status: :created, location: #arrangement }
else
format.html { render action: "new" }
format.json { render json: #arrangement.errors, status: :unprocessable_entity }
end
else
format.html { render action: "new" }
format.json { render json: #arrangement.errors, status: :unprocessable_entity }
end
end
end
The error given is referring to #available_timeslots being empty when trying to save the form
I would try something like this.
def new
#available_timeslots = ...
if #available_timeslots.count > 0
flash.now[:error] = "nil errrraaarrr"
end
...
end
In view
<div class="controls">
<%- if #available_timeslots.count > 0 %>
<%= collection_select(:arrangement, :timeslot_id, #available_timeslots, :id, :timeslot_spelled) %>
<% else %>
<%= flash.now[:error] %>
<% end %>
</div>
#available_timeslots is nil. Make sure it's set with an array of available timeslots to avoid this error message.
The trick was to add #available_timeslots = [] in the else clause
def create
#arrangement = Arrangement.new(params[:arrangement])
respond_to do |format|
if #arrangement.save
# update the timslot record with the arrangement id
if #timeslot = Timeslot.update(#arrangement.timeslot_id, :arrangement_id => #arrangement.id)
format.html { redirect_to #arrangement, notice: 'Arrangement was successfully created.' }
format.json { render json: #arrangement, status: :created, location: #arrangement }
else
format.html { render action: "new" }
format.json { render json: #arrangement.errors, status: :unprocessable_entity }
end
else
format.html { render action: "new" }
format.json { render json: #arrangement.errors, status: :unprocessable_entity }
end
end
end