HTML not updating when rendering tubostream in Rails 7 for a custom controller method - error-handling

I am running Rails 7.0.4 and attempting to use turboframe/tubostream with a customer controller. I am trying to add an error message to the screen when the field from the form is not updated. The custom controller update method is triggered by a stimulus function when the user clicks out of a form field. The controller methods works in that the controller receives that data and the database is updated, however the changes to the page never occur.
I do not receive any errors in my development log. In fact I think what I'm seeing is what I think should likely be seeing - that it's rendering the turbostream and the partial referenced in the turbostream file. One thing I'm wondering though is why it says it's rendering the turbostream file twice:
20:55:37 web.1 | TRANSACTION (0.2ms) ROLLBACK
20:55:37 web.1 | ↳ app/controllers/organization_controller.rb:34:in `api_update'
20:55:37 web.1 | Rendering organization/organization_edit_form_error.turbo_stream.erb
20:55:37 web.1 | Rendered organization/_error.html.erb (Duration: 0.5ms | Allocations: 134)
20:55:37 web.1 | Rendered organization/organization_edit_form_error.turbo_stream.erb (Duration: 0.9ms | Allocations: 272)
20:55:37 web.1 | Completed 200 OK in 37ms (Views: 1.6ms | ActiveRecord: 4.0ms | Allocations: 10991)
In my Network tab in my developer console, I see this which is also what I believe I should be seeing:
<turbo-stream action="replace" target="organization_715728df-0095-4dae-b2c4-9b6911003bfd_error"><template> test
<div role="alert">
Could not edit organization due to the following issues:
<ul>
<li>Website is not a valid URL</li>
</ul>
</div>
</template></turbo-stream>
The concerned files that I'm working with:
controllers/organization_controller.rb (abbreviated)
class OrganizationController < ApplicationController
def api_update
if organization.update(api_organization_params)
respond_to do |format|
format.html { render :edit, organization: #organization }
end
else
respond_to do |format|
format.turbo_stream { render :organization_edit_form_error }
end
end
end
end
/views/organization/edit.html.erb
<div data-controller="organizations" class="mt-10">
<%= turbo_frame_tag "#{dom_id(#organization)}_error" do %>
<%= render partial: 'error', organization: #organization %>
<% end %>
<%= render 'form', organization: #organization %>
</div>
/views/organization/organization_edit_form_error.turbo_stream.erb
<%= turbo_stream.replace "#{dom_id(#organization)}_error", partial: "error", organization: #organization %>
/views/organization/_error.html.erb
<% if #organization.errors.any? %>
<div role="alert">
Could not edit organization due to the following issues:
<ul>
<% #organization.errors.each do |error| %>
<li><%= error.full_message %></li>
<% end %>
</ul>
</div>
<% end %>
I tried adding a test output into the _error.html.erb partial within the if #organization.errors.any? block and seeing if the #organization is actually present and contains errors. It is indeed outputting to the Organization errors as expected in my development logs as expected.
I also tried a few different patterns of implementing turbostream from tutorials I saw. In particular, I tried just replacing the element without a turboform wrapper which was of course unsuccessful. I also tried adding the format.html to the respond_to block in my controller since I noticed that many implementations used this, however I'm assuming it's as a fallback.
I am quite new to turbostreams/turboforms and any help would be appreciated.

Related

Simple_Form and Bootstrap 3 Form Validation Notification Stopped Working

I'm still learning RoR and have followed various tutorials online. In that process I believe I have messed up the nice flash notifications that Bootstrap 2 showed when validating Simple_Form submissions. I have tried to update my code, but without success. Here is what I have so far...
Running:
Rails 3.2.13
Ruby 2.0.0
I just upgraded to Bootstrap 3 using this gem in my gemfile:
gem 'bootstrap-sass-rails'
In my application.html.erb I have:
<%= render 'layouts/messages' %>
In my _messages partial I have:
<% flash.each do |type, message| %>
<div class="alert <%= bootstrap_class_for(type) %> fade in">
<button class="close" data-dismiss="alert">×</button>
<%= message %>
</div>
<% end %>
In my application_helper.rb I have:
def bootstrap_class_for flash_type
case flash_type
when :success
"alert-success"
when :error
"alert-error"
when :alert
"alert-block"
when :notice
"alert-info"
else
flash_type.to_s
end
end
In my users_controller.rb I have:
def update
respond_to do |format|
if #user.update_attributes(params[:user])
format.html { redirect_to #user, notice: 'Account successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
And in my edit.html.erb view I have:
<%= simple_form_for(#user) do |f| %>
<%= f.input :firstname %>
<%= f.input :lastname %>
<%= f.input :email %>
<%= f.input :password %>
<%= f.input :password_confirmation %>
<%= f.submit "Save changes", class: "btn btn-lg btn-primary" %>
<% end %>
The validation works, but when returned to the edit view, no formatting (red for errors) or flash message appears. Only a very hard to spot message outside each field is displayed. I must be missing some link between Simple_Form and Bootstrap 3, just don't know what.
I found another post where poster suggested to add:
config.input_class = "form-control"
to my simple_form initializer, but that gave me an error (think I might not have the latest version?):
undefined method `input_class=' for SimpleForm:Module (NoMethodError)
I wish I knew what was going on but I really hope someone can help me get the formatting and flash messages back. Apologies if this is a total newbie question, but I feel a little lost and possibly regretting that I upgraded too soon to Bootstrap 3 maybe.
A thousand thanks in advance to anyone reading all this :)
I got the following mix of code from railscasts.com and other websites.
<% flash.each do |name, msg| %>
<div class="alert alert-<%= name == :notice ? "success" : "error" %>">
<a class="close" data-dismiss="alert">×</a>
<%= msg %>
</div>
<% end %>
Add this to the top of your controller:
respond_to :html, :json
Put this in each controller action:
def create
...
flash[:notice] = 'User was successfully created.'
respond_with(#user)
end
works with rails 3.2+ and 4.0 and twitter bootstrap rails 2, untested in tbsr 3 but will probably work fine.
This worked for me far much better than others as it;s shorter and includes all alert cases -> error, success, alert & notice provided by Bootstrap.
N.B: I renamed your _messages partial to _flash_messages because that is what most people use.
And for those who may be wondering where to generate the _flash_messages partial, it's pretty easy, just right-click your layouts folder in views and 'add new file'. You can call it _flash_messages as I've done, and ensure you have that first underscore (_) before 'flash...'. Tap 'Save'
Now in your _flash_messages.html.erb partial, use this
<% unless flash.blank? %>
<% flash.each do |type, message| %>
<div class="alert <%= flash_class(type.to_s) %>">
<button class="close" data-dismiss="alert">x</button>
<%= message %>
</div>
<% end %>
<% end %>
And in your application_helper.rb use this
def flash_class (type)
case type
when 'error'
"alert-error"
when 'notice'
"alert-info"
when 'alert'
"alert-block"
when 'success'
"alert-success
else
type.to_s
end
end
Then in your application.html.erb, add this as your first line in your first div
<%= render partial: 'layouts/flash_messages', flash: flash %>
Notice that we render the partial (any partial that is), without the 'starter' underscore(_), i.e before the word 'flash..'
You can check out this answer from teamtreehouse on displaying different alert cases.
Hope this helps!

Rails AJAX request 500 Internal Server Error details

I have a form partial as follows:
_internet_service_form.html.erb
<%= simple_form_for #internet_service, remote: true do |f| %>
<%= f.input :start_date %>
<%= f.button :submit %>
<% end %>
When I render it in the new action of the controller, it returns a 500 internal server with no further explanation.
When I render it in the edit action of the controller, it renders correctly.
If I replace the partial with a text block with no rails tags in it, it renders correctly, so I know it's not a routing error.
new.js.erb
$("#result-content").html("<%= escape_javascript(render(partial: 'new')) %>");
new.html.erb
<%= render partial: 'internet_service_form' %>
internet_service_controller.rb
def new
#internet_service = InternetService.new
end
def edit
#internet_service = InternetService.find(params[:id])
end
These actions are being performed through AJAX, and the most useful logs I'm getting out of the development log are:
Started POST "/accounts/29/internet_services/new.js" for 10.12.68.100 at 2013-02-13 00:28:11 +1300
Processing by InternetServicesController#new as JS
... snip ...
Rendered internet_services/_internet_service_form.html.erb (14.9ms)
Rendered internet_services/_new.html.erb (24.3ms)
Rendered internet_services/new.js.erb (32.2ms)
Completed 500 Internal Server Error in 231ms

Pagination in ruby on rails

I had got a task to do pagination.When i am doing pagination i had got these error
NoMethodError in ProductsController#index
undefined method `page' for []:ActiveRecord::Relation
Rails.root: /home/nithinv/store
Application Trace | Framework Trace | Full Trace
app/controllers/products_controller.rb:4:in `index'
This is my controller
def index
#products = Product.order(:name).page(params[:page]).per(2)
respond_to do |format|
format.html #index.html.erb
format.json { render :json=> #products }
end
end
This is my index.html.erb
<% title "Products" %>
<%= paginate #products %>
<% for product in #products %>
<div class="product">
<h2><%= link_to product.name, product %></h2>
<div class="details">
<%= number_to_currency(product.price) %> |
Released <%= product.released_at.strftime("%B %e, %Y") %>
</div>
</div>
<% end %>
<p><%= link_to "New Product", new_product_path %></p>
How can i solve this problem?
Ref this
I think you forgot to add following line in your gemfile
gem 'kaminari'
and then bundle install
I looks that the problem has to do with kaminari gem configuration (not your code). I'd recommend you to do this quick check:
Run bundle install
Restart the server (because changes may not have been loaded)
Check your gemfile because, kaminari gem may is misplaced (under :test group)
A bit obvious, but in occasions I've also found myself wasting time after forgetting some basic checks.

AJAX a form submission with Rails 3.2

This is my form, and it works fine, but now I want to AJAX it.
<%= form_tag variant_path(variant.id), :method => :put, :class => 'update_inv_form' do %>
<%= text_field_tag :inventory_quantity, variant.inventory_quantity %>
<%= submit_tag 'Update' %>
<% end %>
When I add the :remote => true attribute the form successfully submits via AJAX (I can see it happening on the server and I can see the changes when I refresh the page). I want to update the view properly to show the changes without refreshing the page. This is my update action: (Note that I am not working with ActiveRecord Models here.)
def update
variant = ShopifyAPI::Variant.find(params[:id])
variant.inventory_quantity = params[:inventory_quantity]
variant.save
redirect_to root_path
end
UPDATE
Thank you to the answer that helped me figure this out turns out the solution is exactly as he said, however I ran into a small problem. The view I wanted to update lives in app/views/home/index.html.erb and I was dealing with this: Variants#update. (Variants controller, update action)
I was putting my update.js.html in the same directory that my view was: app/views/home and my server was throwing a 500 error: Missing Template. Turns out, I had to create an app/views/variants/ directory and put the update.js.html file in there. Problem solved.
You'll need to change your action to respond to the JS format:
def update
#variant = ShopifyAPI::Variant.find(params[:id])
#variant.inventory_quantity = params[:inventory_quantity]
#variant.save
respond_to do |format|
format.html { redirect_to root_path }
format.js
end
end
You can then create an update.js.erb file with JavaScript that will update the page. Let's say you have a _variant.html.erb partial, you could append the variant to a div like this (assuming you are using jQuery):
$('.variant-list').append('<%= escape_javascript(render(:partial => "variant", :object => #variant)) %>');
update
Here's an example of how you would use the update.js.erb' file (Note: I have not tried this code). Let's say you have the following code in yourindex.html.erb`:
<ul class="variants">
<li id="101">Variant 1</li>
<li id="102">Variant 2</li>
<li id="103">Variant 3</li>
</ul>
Your updated.js.erb could look something like this:
$('.variants #<%= #variant.id %>').text('<%= #variant.title %>');
What this does is find the variant you just updated in the list, and change the variant title to the new one.

Rendered partial not receiving params

I'm trying to implement an 'edit' link that brings up a form to change a displayed attribute on a page.
My layout has:
<div id="company_info">
<%= yield :company_info %>
</div>
<div id="edit_company_info">
</div>
My view has:
<%= content_for :company_info do %>
<%= render 'company_info' %>
<%= link_to "Edit", 'company_info_form', :class => 'btn btn-mini', :method => :get, :remote => true %>
My controller has:
def company_info_form
#company = Company.get(params[:id])
respond_to do |format|
format.js
end
end
My company_info_form.js.erb file has:
$('#edit_company_info').html("<%= escape_javascript(render "company_info_form") %>");
Upon clicking the link, my server shows:
Started GET "/companies/company_info_form" for 127.0.0.1 at 2012-03-12 20:19:13 -0700
Processing by CompaniesController#show as JS
Parameters: {"id"=>"company_info_form"}
Completed 500 Internal Server Error in 1ms
RuntimeError (Called id for nil, which would mistakenly be 4 -- if you really wanted the id of nil, use object_id):
app/controllers/companies_controller.rb:9:in `show'
So I think this is a routing issue-- but I have no idea how to fix it. How do I get the company_id param that is on my current page to be recognized by the partial I'm loading as well?
I'm on /companies/1, but the link is to companies/company_info_form, losing the "company_id = 1" param.
Yes, the issue is with your routes and with your link as you have pointed out.
The first issue can be ascertained as it says Processing by CompaniesController#show as JS. So, its actually going to companies#show where it tries to find a company based on id. But, since no correct id is passed, it errors out.
The second issue is because your link is to companies/company_info_form, as you pointed out, since you have used 'company_info_form' as the path in your link for edit. And you haven't passed current company to the link either.
Since you haven't posted your routes file, which you should have, since you have identified a potential problem with routes , I'll present my own.
In your routes :
resources :companies do
member do
get 'company_info_form'
end
end
That will provide you with
company_info_form_company GET /companies/:id/company_info_form(.:format) companies#company_info_form
Then you can provide the link as :
<%= link_to "Edit", company_info_form_company_path(#company) %>