Notice is Firing Twice when Saving User Model - ruby-on-rails

When I save a new user the notice fires twice. Any suggestions on how to get it to fire once? I am also using Sorcery
def create
#user = User.new(user_params)
if #user.save
redirect_to #user, notice: 'Profile successfully created.'
auto_login(#user)
else
render :new
end
end

As per the code snippet given above, I don't think notice will appear twice. There is nothing wrong in your code. There is one possible chance that in your application layout displaying notice is defined once and in your current view template it's defined again. That's why it's showing twice.

Flash:
The flash provides a way to pass temporary objects between actions. Anything you place in the flash will be exposed to the very next action and then cleared out.
A notice can't fire twice according to your code. In your app you somewhere have this code twice (my guess would be in your layout file and then your view)
<% flash.each do |name, msg| %>
<%= content_tag :div, msg, :id => "flash_#{name}" %>
<% end %>

Related

How do I get flash[:notice] to display in my view?

I'm having difficulty getting my notices to display in my Rails 5 view. I have this before_filter method set up in a controller:
def check_email_confirmed!
redirect_to controller: "users", action: "edit", notice: 'Please confirm your email.' unless current_user.email_confirmed
end
and in my view I have this
<% if flash[:notice] %>
<p class="flash-notice"><%= flash[:notice] %></p>
<% end %>
but despite the fact that I know the notice is getting set (I see it in my URL) the above is not getting invoked in my view (I see no HTML with the class="flash-notice").
Is there some other way I should be setting flash notices in a redirect? Or should I be using a redirect at all (someone told me there might be some security risks in embedding messages in the URL query string)?
You're currently setting a parameter with the key notice, not setting the flash in your session.
To accomplish this the way you're doing it you would have to do:
<p class="flash-notice"><%= params[:notice] %></p>
Most Rails apps that I've worked on set the session[:flash] in the controller method, in which case you would do:
unless current_user.email_confirmed
redirect_to edit_user_path(current_user)
flash[:notice] = 'Please confirm your email.'
end
Unless you have a good reason to pass the notice text as a URL param, I'd recommend doing it this way.
Try
flash[:notice] = 'bla'
redirect_to controller: "users", action: "edit"
I'm pretty sure that
redirect_to edit_user_path(user), notice: 'bla'
Will also work. For some reason your syntax apparently doesn't pick up the notice modifier. But you'll have to assign user to your current user for that to work obviously.

Rails 5.0 - How to implement in-place editing without using best_in_place gem

I'm building an Events site using RoR which I've just upgraded to v5.0.1 (not moving to 5.1 just yet). My events show page has a comments section at the foot of the page which, so far, only has a create and delete functionality.
I want to add an Edit/Update function to comments so only the user who created the comment can edit the comment if they see fit. I want them to be able to edit their comment whilst on the same page.
I'm trying to implement these changes using remote: true & Ajax, rather than rely on a gem as it doesn't appear too complex, but I've never done this before and there doesn't appear to be a clear guide via the internet/SO. Here's my views & controller code -
comments_controller.rb
def create
#event = Event.find(params[:event_id])
#comment = #event.comments.create!(params[:comment].permit(:name, :body))
#comment.user_id = current_user.id
redirect_to #event
end
def update
#comment.user = current_user
respond_to do |format|
if #comment.update
format.html { redirect_to #comment, notice: 'Comment was successfully updated.' }
format.js { }
format.json { render :show, status: :created, location: #comment }
else
format.html { render :new }
format.json { render json: #comment.errors, status: :unprocessable_entity }
end
end
end
def destroy
#event = Event.find(params[:event_id])
#comment = #event.comments.find(params[:id])
#comment.destroy
redirect_to event_path(#event)
end
_comments.html.erb
<% if user_signed_in? %>
<p><%= link_to "Edit", remote: true %></p>
<p><%= link_to 'Delete', [comment.event, comment],
method: :delete,
class: "button",
data: { confirm: 'Are you sure?' } %></p>
<% end %>
My understanding is that I need to include a .js.erb file in my views/comments folder to deal with this ( edit.js.erb ?) but what I'm not clear on is exactly what javascript code I need to include in order for this to work. Also, I don't think my controller code above seems right - should this go in the Edit action? Do I also need an Event#show action in my events controller as this is where it sits in the views?
Any assistance would be greatly appreciated.
I realize this doesn't answer your question, but hopefully it'll solve headaches down the road for you as far as reinventing the wheel goes. It's also why (I believe) you're seeing downvotes.
I don't want to use best_in_place gem as it appears to not have been updated for a while and I'm not sure if its the best fit for Rails 5.0.
Gems don't need to have activity to still be useful. By "for a while", you must mean mean "less than 24 hours ago" because I'm seeing plenty of activity over the last month. Once a Gem solves its usually good to go.
https://github.com/bernat/best_in_place/commits/master
Rails 5 still handles POST requests right? Then it should work. best_in_place is more javascript-heavy than anything. https://github.com/bernat/best_in_place/tree/master/lib/best_in_place
The most "daunting" code in there is the helper.rb file, which renders the HTML that hooks into the JS library.
Update:
The comments/edit.js.erb file would be responsible for inserting the form to edit the comment, such as $('div#new_comment').append('<%= j render 'form' %>');
This assumes you're using Rails' conventions in regards to element/ID naming.
If you have a link_to("Edit", edit_comment_path(comment), :remote => true) everything should fire automatically.
Here's an example repo using Rails 4; should be the same for Rails 5, with the exception of (maybe) respond_to blocks? I'm not sure, haven't used Rails 5 yet. Just do a bundle, rake db:setup, and then a rails s; navigate to http://localhost:3000/events and enjoy.
You're on the right track with edit.js.erb. The file should contain JS code to set up the screen for editing, which might be hiding a DIV and displaying an INPUT or TEXTAREA instead, for example.
Of course, the file can also contain Ruby code as well, inside <% %> tags.

How do I display the name of a deleted element in Ruby on Rails?

I have a simple Rails application where I create objects (such as posts). So far I can edit and delete them, one by one, but now I want to have a <%= notice %> echoing the name of the deleted object after confirming its deletion. Is this possible? If so, how?
This is an extremely common task in Rails, and the idiomatic solution is to forward some data about the deleted record to the subsequent GET request via the the flash array.
Your controller's destroy action should look something like this:
def destroy
#post = Post.find(params[:id])
#post.destroy
redirect_to posts_path, notice: "#{#post.name} was deleted"
end
In your index action, you'll be able to access flash[:notice] to get the string generated in the previous action.
You need to store the details you want to echo (e.g. the name) somewhere, because the object itself will be gone after a redirect. I would use the flash for that:
# in the controller
def destroy
thing = Thing.find(params[:id])
thing.destroy
redirect_to things_path, :notice => "Thing #{thing.name} was deleted"
end
# in the index view
<% if flash[:notice] %>
<div class="notice"><%= flash[:notice] %></div>
<% end %>

Flash isn't updated upon redirect_to

Here are the actions for my messages controller:
def new
#message = Message.new
end
def create
#message = Message.new(message_params)
if #message.valid?
Contactform.contact(#message.name, #message.town, #message.email, #message.content).deliver
redirect_to 'messages#new', flash: { success: "Sent Message" }
else
redirect_to 'messages#new', flash: { alert: "Message Error" }
end
end
This is what I want to happen:
I go to the 'new' route, a #message instance is created, and in the 'new' view there is a form where we can update this 'Message' instance' attributes.
Now, I'm following a tutorial, but it seems a little work-aroundy. When we 'submit' the form, we are automatically taken to the 'create' action, and a second message instance is created and populated with the old instances attributes.
If the attributes pass the Message model's validations, the attributes are passed into the 'Contactform' mailer's 'contact' action, which delivers the message. We are then redirected to the 'new' view, and the flash is populated with a "Sent Message" string, that we can see when we arrive at the 'new' view.
If the attributes fail the Message model's validations, we are then redirected to the 'new' view, and the flash is populated with a "Message Error" string, that we can see when we arrive at the 'new' view.
What actually happens
Everything works perfectly, apart from the flash. Once it's populated with either the 'success' or 'alert' message, it doesn't change until I browse to another page. Then it gets the updated message, on a new page, so I think because I'm coming back to the same location, the flash isn't updated for some reason.
How can I get the flash to behave normally, despite us coming back to the same page?
Update
Just to say again, it works perfectly if I get redirected to another page. Just because it's the same page, the flash doesn't get updated.
Also, I now have this in the view: Still doesn't do anything.
<% if !flash.empty? %>
<% flash.each do |index, value| %>
<div class = "alert alert-<%= index %>"> <%= value %></div>
<% end %>
<% flash[:error] = flash[:message] = flash[:notice] = nil %>
<% end %>
If you want the flash to show up within the same request (i.e. without a redirect taking place), you'll need to use flash.now. Here's the explanation in the rails docs:
By default, adding values to the flash will make them available to the next request, but sometimes you may want to access those values in the same request. For example, if the create action fails to save a resource and you render the new template directly, that's not going to result in a new request, but you may still want to display a message using the flash
See section 5.2.1 http://guides.rubyonrails.org/action_controller_overview.html

Why the `flash[:warning]` message is not displayed?

I am using Rails 3.1.0 and I would like to understand why the following code in a controller action doesn't properly display the flash[:warning] message even if I state a <%= content_tag( :div, flash[:warning]) %> in the application.html.erb file.
flash[:warning] = "Warning message!"
respond_to do |format|
format.html { redirect_to :root }
end
Why the flash[:warning] message is not displayed? How can I display that after redirection?
P.S. I: I tryed to use flash.keep[:warning] but that didn't work.
SOLUTION
The problem is that I am redirecting two times in my controller actions.
P.S. II: Who voted down can at least give some reasons...
flash.now[:key] will save flash message again key for one request try it
flash.now[:warning] ='message'
and then after redirection show warning message with
<%= flash.now[:warning] %>
Have you written this line in your layout/view? If not then write this code in your layout file
<%= flash[:warning] || flash[:notice] || flash[:alert] %>

Resources