Understanding Rails rendering an error from controller - ruby-on-rails

I am still new to Rails and am having trouble understanding how to render certain sections of a page conditionally. I have a button in index.html.erb as well as another partial rendered:
<%= #facade.processing_button %>
<%= render 'snap', app: #facade.app %>
Which is defined as follows:
link_to processing_path(#app.id),
method: :post, action: :processing,
class: 'btn btn-danger' do
concat([
image_tag('blah', class: 'check_icon'),
content_tag(:span, 'Processing')
].join(' ').html_safe)
end
This button calls a controller method:
def processing
if service.upload
# render success bar?
else
# render error bar?
end
end
I would like to render something like the following pictures. In the snap partial, a section looks like this normally:
Once the button is clicked, if the action is successful I want to render the following green success bar:
It is unclear to me how to accomplish this. Should I be leveraging some form of JS/CoffeeScript? Should I add the bars to the partial as hidden by default and simply show them with JS when the action is completed?

link_to processing_path(#app.id), method: :post, action: :processing Using both _path and :action parameters doesn't make sense. Use only one of them
You need to decide whether your button is doing a "traditional" request or an AJAX request
In case of a traditional request, you can use a controller variable #success = ..., and then check this variable inside the view: <% if #success %>
In case of an AJAX request, things would get a little more complicated. However, there's Rails support for "success" and "failed" AJAX responses. Take a look at https://guides.rubyonrails.org/working_with_javascript_in_rails.html#rails-ujs-event-handlers. Typically, you would show/hide certain elements on the page, depending on the server response

You would need something like this on your layouts
<% flash.each do |name, msg| %>
<%= content_tag :div, msg, class: "alert alert-info" %>
<% end %>
Then on your controller
def processing
if service.upload
flash[:notice] = "Success"
else
flash[:notice] = "Error"
end
end
Take a look at this: rails 4 -- flash notice

see Doc: https://coderwall.com/p/jzofog/ruby-on-rails-flash-messages-with-bootstrap
Step 1: Add flash code in layouts/application.html.erb file
<% flash.each do |key, value| %>
<div class="<%= flash_class(key) %>">
<%= value %>
</div>
<% end %>
Step 2: Just need to quickly extend application_helper.rb with the following
def flash_class(level)
case level
when :notice then "alert alert-info"
when :success then "alert alert-success"
when :error then "alert alert-error"
when :alert then "alert alert-error"
end
end
# sometimes it will not work then wrap it with single quotes. for example:
when 'notice' then "alert alert-success"
Step 3: Add below in controller.erb
def processing
if service.upload
flash[:success] = "Processing complete!"
else
flash[:error] = "Something went wrong!"
end
end
Hope it will work :)

Related

Rails: render not updating page, but it's being returning in response

When calling render The view is not being updated, however, I do notice in the network tab, after the POST request is made to me POST route, it's returning HTML as the response, and the response has my rendered error message. It's just not updating the page. I don't know what to make of that.
In my POST action, I'm forcing this to be called
flash.now[:notice] = responseMessage
render :deactivate_show
Which renders the action:
def deactivate_show
#user = User.find(params[:id])
authorize! :deactivate_user, #user
if current_user.role == "admin"
if #user.broker?
#companyUsers = User.where(parent_id: #user.id)
#properties = Property.where(user_id: #user.id)
.or(Property.where(user_id: #companyUsers.ids))
elsif #user.broker_manager?
# get all agents in company
# exclude current user
# get broker
#companyUsers = User.where(parent_id: #user.parent_id)
.where.not(id: #user.id)
.or(User.where(id: #user.parent_id))
#properties = Property.where(user_id: #companyUsers.ids)
.or(Property.where(user_id: #user.parent_id))
else #user.agent?
#properties = #user.properties
if #user.parent_id?
#companyUsers = User.where(parent_id: #user.parent_id)
.where.not(id: #user.id)
.or(User.where(id: #user.parent_id) )
else
# dealing with owner.
#companyUsers = User.where('role IN (2,4,1)')
.where.not(id: #user.id)
end
end
else
end
end
which renders a view I have that displays the form.
I added to my show view:
<div class="messages">
<% flash.each do |key, value| %>
<div class="hello"><%= value %></div>
<% end %>
</div>
Note the class of "hello".
When I make a POST request, the response in the network tab has the notice:
Rendered from POST request response:
<div class="messages">
<div class="hello">testing errors</div>
</div>
Edit: here's the form:
<div class="form-wrap">
<%= form_with do %>
<%= button_tag( id: 'button--submit', class: 'button button--secondary') do %>
<i class="icon-arrow-right"></i>
<span>Deactivate</span>
<% end %>
<% end %>
</div>
Well the actual answer was something no one could have provided since I didn't share my form. I was using form_with, which apparently does AJAX by default, thus not rendering the view.
Thanks for the help from this question: Rails render not showing in browser, despite positive server reply
I've changed
<%= form_with do %>
to
<%= form_with local: true do %>
and now it works.
The Flash is only rendered upon a new request, which you don't make with render. Instead, you should use flash.now[:notice] to have it display on render.

Flash message don't show up when I do return redirect_to

I've a weird problem(I'm still learning rails) with rails and flash messages.
I have a link_to with method post in my rails view:
<%= link_to "<i class='fa fa-times'></i>".html_safe, email_post_path(#post.id), method: 'post' %>
and in my controller I do this:
def email_post
# do nothing
return redirect_to posts_path, alert: 'test flash'
end
The problem
is that works fine(so it redirect me correctly), but don't show the flash message(and the problem is not about the showing flash message, but that the flash[:alert] doesn't exists)
This is the way I show the flash messages:
<%= binding.pry %> #used for see if the flash is empty or not - and in this case is it!
<% flash.each do |type, message| %>
<div class="flash-<%= type %>">
<%= message %>
</div>
<% end %>
Why don't show the flash message in this case ?
Ok the problem seems to be
error: 'lol'
With:
alert: 'lol'
Works fine...why ?

Flash Message (Rails v.4.1.1) Curly Brackets

I'm creating a blog on rails. Everytime a post is created on the new page I want to be back at the index page and see a flash message saying "You post was saved". On the layout I have the following:
<body>
<%= flash.each do |key, value| %>
<p><%= value %></p>
<% end %>
<%= yield %>
</body>
The problem is that I have now on every page (index, new, etc.) curly brackets on the top and I don't know why. Also, instead of just having a message "Your post was saved.". It also appears the following: "{"notice"=>"Your post was saved."}". This is the code for the message hold on the controller (posts_controller.rb):
def create
#post = Post.new(post_params)
if #post.save
redirect_to posts_path
flash[:notice] = "Your post was saved."
else
render "new"
end
end
I'm beginning with Rails, thanks for the help.
See update below for explanation
remove the = in <%= flash.each.... %> Should just be <% flash.each.....%>
<% flash.each do |key, value| %>
<p><%= value %></p>
<% end %>
To keep it simple, when you want your ruby code to render something onto the page, use <%= %>, ex: to show the current time you would use <%= Time.now %>. For other things like settings variables in your view without text rendering on the page, use <% %>.
For example, say I want to assign a variable equal to the current time so I can use it below in the view, I would use <% time = Time.now %> then I can show that time on the page with <%= time %>.
<% time = Time.now %>
<p>The current time is <%= time %>.</p>

flash message when user logout

In devise.en.yml,i kept signed_out message empty as
sessions:
signed_out: ""
i am having a condition where if failed attempt > 3 then we have to make user signed out.
For this i wrote in the controller as:
if params[:failed_attempt].to_i > 3
current_user.update_attribute(:status, false)
redirect_to destroy_user_session_path(#user), :notice =>
"locked"
end
I am able to update attribute and able to logout but couldnot able to display notice or flash message. Please try to help me out.
I am getting all the messages except this. I also tried :
redirect_to destroy_user_session_path(#user)
flash[:notice] = "locked"
But no use.
Most likely you are setting the flash variable but not actually rendering out the content... try this:
In your application.html.erb before the <%= yield %> paste in code like this:
<% flash.each do |name, msg| %>
<div data-alert id="flashes" class="alert-box <%= name %>">
<%= content_tag :div, msg, id: "flash_#{name}" %>
×
</div>
<% end %>
You can style it afterwards whatever way you want
This done the trick. I just changed my signout as:
sign_out(current_user), :notice =>"locked"
instead of
redirect_to destroy_user_session_path(#user), :notice => "locked"

Update Ruby on Rails partial with Ajax

I've built a fav icon that works like a Facebook like/unlike button, and I'm trying to update it via Ajax but can't seem to get it working. I think I'm missing something simple.
events_controller.rb
def fav
#event = Event.find(params[:id])
current_user.toggle_flag(#event, :fav) #events_helper.rb
respond_to do |format|
format.js
end
end
events_helper.rb
def toggle_fav(event, user)
if user_signed_in? #change icon from heart to empty heart and vice-versa
link_to user.flagged?(event, :fav) ? #if the event is flagged
content_tag(:span, " ", :class => "glyphicon glyphicon-heart") : #show full heart
content_tag(:span, " ", :class => "glyphicon glyphicon-heart-empty"), #else show empty heart
fav_event_path(event), #path that changes the state of the heart
:remote => true
else
link_to content_tag(:span, " ", :class => "glyphicon glyphicon-heart-empty"), fav_event_path(event) #prompt user to sign in
end
end
Events/index.html.erb
<% #events.each do |event| %>
<%= render 'each_event', :event => event %>
<% end %>
_each_event.html.erb (relevant info only)
<div class="row">
<div class="event-div">
<div class="event-details">
<ul><li class="fav-li"><%= render 'fav_li', :event => event %></li></ul>
</div>
</div>
</div>
_fav_li.html.erb
<%= toggle_fav(event, current_user) %>
fav.js.erb
$('.fav-li').html('<%=j render 'events/fav_li', :event => event, :layout => false %>');
I followed this tutorial to make the like button: http://www.youtube.com/watch?v=GG-kCSx0taU
And am using the make_flaggable gem.
Right now when I update the button it directs me to http://localhost:3000/events/23/fav but that template doesn't exist (and shouldn't). The events are displayed on the event index page after going through the index filters. There are multiple events on a single page.
I'd appreciate any help! Thanks.
Your controller is doing format.js in the respond_to block. It's expecting a js template to exist so it can run it as the response. Something like app/views/events/fav.js.erb. This file will contain some js code that will update your view with the results of your controller action e.g. update the icon from glyphicon-heart-empty to glyphicon-heart.
Here's another question/answer discussing js.erb templates: How does js.erb work
Hope that helps.

Resources