Errors not displaying when rendering edit in Rails 7 - ruby-on-rails

My app is running Rails Rails 7.0.2.3
In my update controller action I have the line:
return render(:edit) unless #user_form.save
This renders the edit view on error .... but errors are not displayed.
In my edit view I am defining the form with:
form_for #user_form, url: user_path(#user_form), method: :patch do |f|
The form submits via turbo. I can see the error being added to #user_form.errors in the controller, but the instance of #user_form in the view is not changing on each form submission. If I output #user_form.inspect to the view - the id remains the same on each submission.
I have tried adding remote: false to the form_for call, but this does not seem to have an effect.
The only solution I have found is to add data: { turbo: false } to the form_for call.
Is there a better way of handling this?

you'll want to use a partial to show the errors.
you'll need to add an update.turbo_stream.erb file to this view's directory. In that file have something like:
<%= turbo_stream.update 'id_of_div_where_you_want_to_show_errors' do %>
<%= render partial: 'partial_that_displays_errors' %>
<% end %>
or your controllers update action you'll want to have something like
respond_to do |format|
format.turbo_stream { turbo_stream.update 'id_of_div_where_you_want_to_show_errors', render partial: 'partial_that_displays_errors' %>
end
Treat all this more like pseudocode and apply it to your own app, it's hard to say what's going on without seeing your code.

Related

Dealing with 2 models in 1 view

I have two models I'm trying to interact with in 1 view. The first model is Room and the second is Availability. 1 Room has many Availabilities.
On 1 Rooms page, I render out availabilities through a partial like this:
<% #room.availabilities.where("booking_id is NULL").order("start_time").each_with_index do |a|%>
Beside each availability I have a button to delete and update. The delete worked out fine since it was in my loop so I could do something like this.
<%= link_to("Delete", availability_path(a.id), method: :delete, remote: true) %>
But I'm having trouble with edit. I'm trying to do it through a modal which doesn't have access to the 'a' variable from the loop. So I'm not sure how to pass in the unique availability to the form
Button:
<!-- Edit button -->
<button type="button" class="btn btn-xs btn-primary" data-toggle="modal" data-target="#editAvailability"><i class='fa fa-pencil'></i></button>
<!-- Edit Availability Form -->
<%= simple_form_for #facility.availabilities.find(???), method: :put, remote: true do |f| %>
You should be able to do this with AJAX. I have an app that has a modal dropdown that lets me toggle pieces of equipment in or out of service with a button in the dropdown. You can use a route that points towards the Availabilities controller that renders a form in the modal. Mine is simple in that it just toggles, but I don't see why you can't use a form. I would move your query out of your view and make a helper that gives you the results of your query in a variable.
I can provide more detail but need to see a lot more of your current code. If you can post your controller and all of your view code for the modal. I don't know understand why you don't have access to the variable you need in the modal? If the modal has an AJAX call you should be able to populate it with any data available to your controllers.
edit
Take a look at this: https://coderwall.com/p/ej0mhg/open-a-rails-form-with-twitter-bootstrap-modals . Be sure and read the links at the end of this article, it has some StackOverflow examples that are spot on. I'm thinking link_to is the way to go:
<%= link_to 'Update, availabilities_edit_path(a.id), {:remote => true, 'data-controls-modal' => "modal-window", 'data-backdrop' => true, 'data-keyboard' => true} %>
This should open a modal and ask the availabilities#edit controller for a JS response. Make sure you have an edit action, I don't see one in your controller:
availabilities.rb
def edit
#availability = Availability.find_by(id: params[:id])
respond_to do |format|
format.html
format.js
end
So the JS call will cause it to look in the /views/availabilities/ folder for a file called edit.js.erb with content like:
$('#editAvailability').html('<%= escape_javascript(render :partial => 'editForm') %>');
In your edit form you you now have the #availability instance variable to use in your form:
<%= simple_form_for #availability, method: :put, remote: true do |f| %>
...
So your modal gets built using an AJAX lookup that returns a form built using the needed instance variable. I'm putting this together from stuff I've written and other stuff I've read, so there will probably be some errors and tweaking to get your code working. Let me know how far this gets you.
You can store all the information necessary in your update button within your loop like this:
<%= link_to("Update", method: :put, remote: true, data: { attr1: a.attr1, attr2: a.attr2 }) %>
Then every button knows what entity they are operating for.

Why does form_for(#object) do |f| work in the _form.html.erb but not in the index.html.erb

Ok, So i'm trying to place the form found in the "_form.html.erb" in the "index.html.erb" of my ruby project crashes with the error
"First argument in form cannot contain nil or be empty"
<%= form_for(#customer) do |f| %>
I know that changing the #customer to Customer.new could fix this but I would like to know why this isn't necessary in one file and it is in another
Why is this happening and how do I make a form that will update the sqlite db on the index page.
#customer is a variable that must be created somewhere in the corresponding controller action. If your #index controller action defines a variable by that name, then you'll be able to use it in the view template; otherwise you'll need to create it like this:
#customer = Customer.new # (or whatever the value is)
When Rails processes a request, it just executes a big (and complex) lump of code that's created from a bunch of different files. First it executes the appropriate controller action, then it executes any Ruby code found inside the corresponding view template. So any variable (or any method name) that is used in the view template, was first defined at some point before that: either in the controller action, or in one of Rails' countless built-in helper files.
When I am using form_for in a index or show page I like to do is set it to new
<%= form_for Customer.new, url: {controller: "customers", action: "create"} do |f| %>
...
<%= f.submit %>
<% end %>
that way there is a object to be created, I also I like to pass in the controller and the action.

Rails: flash message shows in the url as param

Hi all my flash messages work in the normal fashion but there is an action in one of my controllers where the flash message does not work.
This is the view:
<%= form_tag update_status_order_path(update_status), method: :put do |f| %>
<%= select(:order, :status, [['Active', 1], ['Inactive', 0]]) %>
<%= submit_tag "Update" %>
<% end %>
This is the controller action
def update_status
if #order.update_order_status! params[:order][:status]
redirect_to show_orders_ofert_path #order.ofert, success: "Updated!."
else
redirect_to show_orders_ofert_path #order.ofert, error: "Error."
end
end
When I send the form the action is performed correctly, but the flash message is not displayed in the layout, instead is displayed in the url as a param, just after click the Update button it reloads and shows the url like this:
http://localhost:3000/oferts/48/show_orders?success=Updated!
I have tried changing put to patch but it did not worked, even changing the action to work with respons_to block but it did not work, any idea?
this problem is only happening with that specific action because with the other actions I have the flash messages are isplayed normally.
Thanks
The success and error keys are being used as parameters to the show_orders_ofert_path because there are no parenthesis. Add parenthesis around the path helper arguments:
redirect_to show_orders_ofert_path(#order.ofert), success: "Updated!."

Display form on index page

I have a index page and wish to display a form from a different controller that I created on the index page. I have 3 folders in my view. In the folder called index, I have a html file called index and in the folder called job I have form.html and show.html.
so in my index.html I have
<h1>Complete Job Applications</h1>
<%= render 'job/form'%>
When I run the code I receive this error First argument in form cannot contain nil or be empty. I think I know why but am not too sure. Instead of displaying the form so the user can fill out all the needed text fields so it can be submitted it's submitting it right away (just a guess though). Does anyone have any ideas to how I can display a form from another controller on my index page
You will need to initialize the object that is passed to the form, for example, lets say your view looks like this:
# job/form
<%= form_for(some_model_instance, method: :get) do |form|
...
<% end %>
To render that form from another controller's action, make sure to initialize some_model_instance before rendering the partial, so:
# controller which has the index action
def index
#some_model_instance = SomeModel.where(id: 1).first
end
# index.html.erb
<h1>Complete Job Applications</h1>
<%= render partial: 'job/form', locals: { some_model_instance: #some_model_instance } %>

Adding extra layout to specific controllers and actions in rails 3?

In my application.html.erb I have a header partial. which I rendered with the render tag
<%= render 'layouts/header' %>
So this header applies to all the controller and all the actions.
I have a dropdown partial which i want to show, in addition to the header partial, in all the controllers except one one controller. I want something like
<%= render 'layouts/dropdown' except_controller_anycontroller %>
When I put
render :partial => 'layouts/dropdown'
It just renders the dropdown partial and all other layouts are lost (like the footer,header,body). I want to add the extra dropdown partial only to certain actions and controllers.
How can I achieve that in Rails 3.2.13?
Replace your render with this:
<%= render 'layouts/dropdown' unless #disable_dropdown %>
Then you can simply set disable_dropdown to true in any controller you like:
def test_method
#disable_dropdown = true
end
call this method in your controller filter, in which you dont want to show this:
write this on top of your controller above your first method:
before_filter :test_method
it will automatically be called when your request comes to this controller.
Hope it will help. Thanks
I would suggest something like:
<%= render 'layouts/dropdown' unless params[:controller] == "controller_to_avoid" %>

Resources