I have a simple messaging app. Users can set up a public profile with their description and people can send them inquiries. Those inquiries are then collected in a table in the user dashboard.
When a user is clicking on a row, a turbo frame opens up and shows the inquiry.
I would like to implement, that the inquiry is automatically set to #inquriy.seen = true whenever a row is clicked / the inquiry show action is called. Within the table is a blue dot in my ui that indicates, that the message/inquiry is not yet read.
currently i have this code within the show action:
respond_to do |format|
if #inquiry.update!(seen: true)
format.html
format.turbo_stream { flash.now[:notice] = "Anfrage angesehen." }
end
end
The problem is, that it does not work. The inquiry is successfully updated, but the table does not change. Instead I am getting a Completed 406 Not Acceptable response and an ActionController::UnknownFormat error.
I already tried to accept turbo_streams in the mime_type.rb but there are other features in my app that are using turbo streams that work just fine (btw also in the update action of the inquiries (you can manually set them to read)).
How can I trigger the turbo_stream when clicking calling the show action to update the table in the index action?
Thanks!
Related
So I'm working on a web application and I have a blog page, with two controllers, a posts controller for the blog and then a subscribers controller that simply allows the user to add a new subscriber. So currently I render the content using a view defined in posts, and then within that I have a partial, _subscriber, to handle the subscription model.
The problem comes when the user tries to subscribe. I want to be able to render the new action to show validations, like this:
def create
#subscriber = Subscriber.new(subscriber_params)
if #subscriber.save
flash[:success] = "Thank you for subscribing!"
redirect_to subscribers_url
else
render :new, status: :unprocessable_entity
end
end
Besides the fact that this results in a duplicate view (new.html.erb is identical to the partial), because it is not a partial view, it reloads the entire page and now replaces all of the post with just the subscription form. Currently, my workaround is to do a redirect when the user clicks the button, but then validation errors don't show and it isn't really an ideal solution.
I tried just rendering the partial, instead of the :new action, like this:
render partial: 'subscriber', status: :unprocessable_entity
But has the same effect as just calling redirect; my validation errors won't show.
Perhaps the ideal solution is to use something like AJAX. I tried to understand Turbo Frames and Turbo Streams, but I'm a little confused how I would implement that in this situation. Essentially, I could wrap the subscribe section of my posts page in a turbo frame but then how would I update the turbo frame? I don't want to have a different post page because that wouldn't make sense. I only want to change the content of the view inside.
What would the correct/best practices way of implementing this functionality be? Any suggestions would be appreciated!
If you don't want to actually reload the page, then yes, you'll need to do something with either AJAX / UJS or Turbo frames.
My favorite AJAX / UJS tutorial
A good Turbo tutorial
(Or go to the dark side with React or Node or some other JS solution)
Very general question I was hoping someone could clarify for me. I'm looking at the basic generated scaffold code for a model called products. I noticed the new and show actions in the controller don't have much written in them. In fact, show is entirely empty and new only has the line "#product = Product.new". I know these 2 actions are supposed to go to a separate view. A view to show the resource, and a new form view to input info and create a resource, respectively.
So, I'm curious how that actually happens. Other actions have redirect_to :some_path which makes sense, but how exactly does "render action 'show', location: #product " bring up the items show page when the action is empty? Also how is that different from redirect_to #product ?
thanks
Will
Render produces a string that will displayed as the response to the request to the application.
redirect_to produces a response header resulting in a new request to the application.
The render action 'show', location: #product uses the the file app/views/products/show.html.erb with #product as a parameter to produce the html which will be returned.
The reason some of the controller functions are empty is that rails are using defaults. So if you don't tell rails what to render then rails will look for a file in the appropriate location.
Methods ending with redirect_to are usually post/patch requests saving something in your database and after the requested action has been performed they redirect the user to a method meant for displaying information.
Here is my create action. It creates a new instance of Message, which is checked with model validations.
Then there is a simple if else loop that sends the message if the model validations were fulfilled and renders the 'new' view if they want to send another. If the model validations weren't fulfilled, it simply renders the 'new' view again.
The flash hash is also populated with relevant information, a success message and an alert message if the message was successful or not.
def create
#message = Message.new(message_params)
if #message.valid?
Contactform.contact(#message.name, #message.town, #message.email, #message.content).deliver
flash[:success] = "Sent message"
render 'new'
else
flash[:alert] = "Alert"
render 'new'
end
end
However, I don't think I'm doing it right, because the messages stay in the flash. They aren't cleared after they've been viewed once.
How should I ensure that the flash is cleared, as it should be?
Update
This is how the error comes about. I send a message successfully, and I'm routed back to the 'new' view and I receive a 'success' flash. I attempt to send an erroneous message, and I'm routed back to the 'new' view and I receive both the 'success' flash from before, and a 'alert' flash. Very confusing for the user!
The second I browse to another page, both flashes disappear, but that's the problem I think. Something to do with coming back to the same page so Rails doesn't know to clear the flash. Can I force clear the flash?
I think reading the section about flash.now in the rails doc will help clear this up for you: http://guides.rubyonrails.org/action_controller_overview.html#flash-now.
Flash sticks around for the next request. In this case, you aren't issuing a new request after your create action - you are just re-rendering the new view. I think flash.now is what you want to be using here.
I would also say that in your create success case, the create action should be doing a redirect rather than just re-rendering the view. Are redirect_to and render exchangeable? explains the difference between redirecting and rendering
I'm having a slight issue with a controller action. The behavior i'm after is the option to edit a note. I want the user to be able to edit the note, just like they created the note, in a modal(twitter bootstrap). Creating a note this way works fine. The problem is coming to edit the note. The main issue is that I need to always know the exact note id when a user clicks on a "edit" button. To complicate things a bit more, there is a "dashboard" controller/model which acts as a container for "notes" and other things.
Here is the code/link I have in the view on the dashboard which displays all the users current notes.
= link_to "Edit Note", "update_note/#{n.id}",{:note_id => "#{n.id}"}
So Here I am sending some params contain the note id. Then in the controller action, in the dashboard (the container)
def update_note
#user = current_user
#edit_note_id = params[:params1]
redirect_to dashboard_path and return
respond_to do |format|
format.html { render "#modal_edit_notes"}
end
end
So at point I have the unique note id, and instantiating something so when hopefully the modal loads up I can create a form based on that. The issue that I'm having is getting the controller at this point to go back to the dashboard, and pop up the modal, now that I have the note.id.
To trigger the modal, I normally would do a
href = #modal_edit_notes, data-toggle = "modal"
Thanks!
OK, you have two options here.
Embed a form inside a hidden element for every single note you display, and then just have that pre-rendered form show up in the modal when you want to edit that particular note.
Load the content of the modal via ajax, this will require a little bit of custom JS to make it work with the bootstrap modals, but isn't too difficult. This is how I would do it.
Also, as a side point, the update_note method really should be a update method in a NotesController.
I've been following the wiki for Devise https://github.com/plataformatec/devise/wiki/How-To:-Require-admin-to-activate-account-before-sign_in. I get the page to display perfectly and everything but once I try to hit edit to change a user's status from pending to approved I get the error 'The action 'edit' could not be found for UsersController'.
I'm assuming I need to define the 'edit' method in my users_controller.rb file...I'm just not sure how I would code it tell the database to switch the user's status from pending to approved.
The wiki just gives you the index action and view. You'll also need edit and update controller actions and an edit view for users with a form containing an "approved" checkbox (or select box, whatever floats your boat).