How to manage errors with simple_form in rails 6 - simple-form

I have a form where I have added some validation, I would like the errors to be listed, I have an idea that it can be done this way.
= simple_form_for(#post) do |f|
.row.pt-4
.col-lg-3
-if f.object.errors[:base].present?
.alert.alert-danger
%ul
%li= f.error_notification message: f.object.errors[:base].to_sentence
The problem I have is that the first error is listing it correctly, but the others are not.
example:
example with more errors
it should be displayed every error with a bullet point

You need to loop over the errors:
= simple_form_for(#post) do |f|
.row.pt-4
.col-lg-3
-if f.object.errors.any?
.alert.alert-danger
%ul
= f.object.errors.each do |error|
%li= f.error_notification message: error.message

Related

JSON.parse: unexpected character at line 1 column 1 of the JSON data on sending Javascript

I am working on a simple message box, using "remote: true", and then replacing a flash_message div with a success or failure message. For some reason this keeps on giving the error "JSON.parse: unexpected character at line 1 column 1 of the JSON data".
My view:
= form_for Message.new, remote: true, format: :js do |f|
= hidden_field_tag :authenticity_token, form_authenticity_token
= f.text_field :name, placeholder: 'Naam'
= f.text_field :email, placeholder: 'E-mail'
= f.text_area :message, placeholder: 'Jouw bericht'
= f.submit
#flash-message
My controller:
def create
#message = Message.new(params[:message])
respond_to do |format|
if #message.valid?
# MessageMailer.contact(#message).deliver
format.html
format.js { flash.now[:success] = "Thank you for your message. I'll get back to you soon!" }
else
format.html
format.js { flash.now[:failure] = "Something went wrong!" }
end
end
end
My create.js.erb:
$('#flash-message').html("<%= j render 'flash' %>").delay(3000).fadeOut(4000);
On the terminal I see:
Started POST "/messages.js" for 127.0.0.1 at 2018-05-10 16:14:33 +0200
Processing by MessagesController#create as JS
Parameters: {"utf8"=>"✓", "authenticity_token"=>"/3VXW31YVYF/mfle+JiHHx1jRguLF4TkepPWGqXYhP4tc/qS2IfGWlWpvcW4A4pwwcTGmHZJHnpzajqT+ETLiw==", "message"=>{"name"=>"", "email"=>"", "message"=>""}, "commit"=>"Create Message"}
Rendering messages/create.js.erb
Rendered messages/_flash.html.slim (2.3ms)
Rendered messages/create.js.erb (3.8ms)
Completed 200 OK in 19ms (Views: 11.8ms | ActiveRecord: 0.0ms)
And in the browser I get
SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data
$('#flash-message').html("<div class=\"alert alert-failure\">Something went wrong!<\/div>").delay(3000).fadeOut(4000);
I'm apparently doing something very wrong, but don't understand why my javascript code suddenly gets parsed as json.
I've been googling the error, but to no avail.
Any suggestions on what I might be doing wrong?
As they say - never to old to learn... 10 minutes after posting this question, and after 3 hours of trying to find the cause of the problem, I suddenly saw I didn't include jquery_ujs into my application.js file, causing apparently all the above trouble.
//= require jquery_ujs
Hope this question helps someone in the future!

Rails route, show all elements on the same page

I need to show all my elements on the same page.
In routes:
namespace :nourishment do
resources :diets do
resources :nourishment_meals, :controller => 'meals'
get 'nourishment_meals/show_all_meals' => 'meals#show_all_meals', as: "show_all_meals"
end
end
which will generate:
nourishment_diet_nourishment_meals_path GET /nourishment/diets/:diet_id/nourishment_meals(.:format) nourishment/meals#index
POST /nourishment/diets/:diet_id/nourishment_meals(.:format) nourishment/meals#create
new_nourishment_diet_nourishment_meal_path GET /nourishment/diets/:diet_id/nourishment_meals/new(.:format) nourishment/meals#new
edit_nourishment_diet_nourishment_meal_path GET /nourishment/diets/:diet_id/nourishment_meals/:id/edit(.:format) nourishment/meals#edit
nourishment_diet_nourishment_meal_path GET /nourishment/diets/:diet_id/nourishment_meals/:id(.:format) nourishment/meals#show
PATCH /nourishment/diets/:diet_id/nourishment_meals/:id(.:format) nourishment/meals#update
PUT /nourishment/diets/:diet_id/nourishment_meals/:id(.:format) nourishment/meals#update
DELETE /nourishment/diets/:diet_id/nourishment_meals/:id(.:format) nourishment/meals#destroy
[**THIS**]
nourishment_diet_show_all_meals_path GET /nourishment/diets/:diet_id/nourishment_meals/show_all_meals(.:format) nourishment/meals#show_all_meals
The problem, when I do this:
<%= link_to "Show all meals", nourishment_diet_show_all_meals_path, :class=>"button green" %>
This error raise:
Problem:
Problem:
Document(s) not found for class NourishmentMeal with id(s) show_all_meals.
Summary:
When calling NourishmentMeal.find with an id or array of ids, each parameter must match a document in the database or this error will be raised. The search was for the id(s): show_all_meals ... (1 total) and the following ids were not found: show_all_meals.
Resolution:
Search for an id that is in the database or set the Mongoid.raise_not_found_error configuration option to false, which will cause a nil to be returned instead of raising this error when searching for a single id, or only the matched documents when searching for multiples.
The error is here, on my meals_controller.rb
private
# Use callbacks to share common setup or constraints between actions.
def set_nourishment_meal
#nourishment_diet = NourishmentDiet.find(params[:diet_id])
[***HERE***] #nourishment_meal = #nourishment_diet.meals.find(params[:id])
end
Method:
def show_all_meals
puts "This word does not appear"
end
Can someone help me?
The route below expects a :diet_id. A diet instance has to be provided as an argument for this path to call corresponding action.
nourishment_diet_show_all_meals_path GET /nourishment/diets/:diet_id/nourishment_meals/show_all_meals(.:format) nourishment/meals#show_all_meals
This should be changed:
<%= link_to "Show all meals", nourishment_diet_show_all_meals_path, :class=>"button green" %>
to:
<%= link_to "Show all meals", nourishment_diet_show_all_meals_path(diet), :class=>"button green" %>
Notice the argument (diet) above.
I think you should pass diet_id parameter in params. You should try something like this: <%= link_to "Show all meals", nourishment_diet_show_all_meals_path(#diet.id), :class=>"button green" %>. #diet.id is just an example, use whatever works for your application.

Rails 3: Loop shows more records than there should be

Not exactly sure of what to call this issue. Still new to rails.
Situation: An auction contains many lots.
I'm showing an auction's lots in a url like /auctions/3/lots/.
View:
<ul>
<% #lots.each do |lot| %>
<li><%= lot.auction_id %>: <%= lot.id %></li>
<% end %>
</ul>
Outputs this:
<ul>
<li>3: 1</li>
<li>3: </li>
</ul>
I only have one lot in my database. Not sure where the extra loop instance is coming from.
This happens on any lot listing no matter which auction I'm looking at.
Also,
<%= #lots.length %> displays 2
<%= #lots.size %> displays 2
<%= #lots.count %> displays 1
My lots_controller looks like this:
def index
#auction = Auction.find(params[:auction_id])
#lots = #auction.lots
end
def create
#auction = Auction.find(params[:auction_id])
#lot = #auction.lots.build(params[:lot])
if #lot.save
redirect_to auction_lots_path, :notice => 'Lot was successfully created.'
else
render :action => "index"
end
end
My models:
class Auction < ActiveRecord::Base
...
has_many :lots
end
class Lot < ActiveRecord::Base
belongs_to :auction
...
end
The ...s are just attr_accesssible and validates lines.
The log when I hit the page was requested, here it is.
Started GET "/auctions/8/lots" for 127.0.0.1 at 2013-02-13 16:35:51 -0500
Processing by LotsController#index as HTML
Parameters: {"auction_id"=>"8"}
Auction Load (0.1ms) SELECT "auctions".* FROM "auctions" WHERE "auctions"."id" = ? LIMIT 1 [["id", "8"]]
Lot Load (0.2ms) SELECT "lots".* FROM "lots" WHERE "lots"."auction_id" = 8
[#<Lot id: 18, description: "1923 Morgan", lot_number: 1, auction_id: 8, created_at: "2013-02-13 17:20:04", updated_at: "2013-02-13 17:20:04">]
Rendered layouts/_messages.html.erb (0.1ms)
Lot Exists (0.2ms) SELECT 1 AS one FROM "lots" WHERE "lots"."auction_id" = 8 LIMIT 1
Rendered lots/index.html.erb within layouts/application (9.4ms)
Completed 200 OK in 21ms (Views: 17.8ms | ActiveRecord: 0.5ms)
Update:
Someone mentioned that it looks like I'm using #auction.lots.build somewhere.
And yes, I am. I have a form on the same page (index) where I can add lots.
<%= form_for(#auction.lots.build, :url => auction_lots_path(#auction)) do |f| %>
...
<% end %>
Changing #auction.lots.build got rid of the extra row, although now I can't create lots successfully. I'm not sure what to do. I probably have to set up something in the index method of the lots_controller, but I don't know what.
Any help is appreciated.
This would happen in your create method if the lot failed to save. Because you used #auction.lots.build, that appends a lot record to the auction. If it doesn't save properly, it's still there unsaved. That explains why the "mystery" one doesn't have an id, and also why:
<%= #lots.size %> displays 2
<%= #lots.count %> displays 1
#lots.count is a database query, but #lots.size is just the size of the array in memory.
I would probably do something more like this in the create action:
def create
#auction = Auction.find(params[:auction_id])
#lot = #auction.lots.create!(params[:lot])
redirect_to auction_lots_path, :notice => 'Lot was successfully created.'
rescue ActiveRecord::RecordInvalid
render :action => "index"
end
... but of course others will prefer using if/else rather than rescuing the exception. There are other ways around this. You could do #auction.reload.lots to cull the unsaved one, but that's a little wierd. The normal rails thing to do in this case is re-render the form with the validation errors displayed and ask the user to fix them and try creating again.
This should help:
def create
params[:lot].merge!({:auction_id => params[:auction_id]})
#lot = Lot.new(params[:lot])
if #lot.save
redirect_to auction_lots_path, :notice => 'Lot was successfully created.'
else
render :action => "index"
end
end

If Statement inside Sinatra template

I'd like to to show a message only if on a specific route/page. Essentially, if on /route display a message.
I tried going through the Sinatra Docs, but I can't find a specific way to do it. Is there a Ruby method that will make this work?
EDIT: Here's an example of what I'd like to do.
get '/' do
erb :index
end
get '/page1' do
erb :page1
end
get '/page2' do
erb :page2
end
*******************
<!-- Layout File -->
<html>
<head>
<title></title>
</head>
<body>
<% if this page is 'page1' do something %>
<% else do something else %>
<% end %>
<%= yield %>
</body>
</html>
No idea what how to target the current page using Ruby/Sinatra and structure it into an if statement.
There are several ways to approach this (and BTW, I'm going to use Haml even though you've used ERB because it's less typing for me and plainly an improvement). Most of them rely on the request helper, most often it will be request.path_info.
Conditional within a view.
Within any view, not just a layout:
%p
- if request.path_info == "/page1"
= "You are on page1"
- else
= "You are not on page1, but on #{request.path_info[1..]}"
%p= request.path_info == "/page1" ? "PAGE1!!!" : "NOT PAGE1!!!"
A conditional with a route.
get "/page1" do
# you are on page1
message = "This is page 1"
# you can use an instance variable if you want,
# but reducing scope is a best practice and very easy.
erb :page1, :locals => { message: message }
end
get "/page2" do
message = nil # not needed, but this is a silly example
erb :page2, :locals => { message: message }
end
get %r{/page(\d+)} do |digits|
# you'd never reach this with a 1 as the digit, but again, this is an example
message = "Page 1" if digits == "1"
erb :page_any, :locals => { message: message }
end
# page1.erb
%p= message unless message.nil?
A before block.
before do
#message = "Page1" if request.path_info == "/page1"
end
# page1.erb
%p= #message unless #message.nil?
or even better
before "/page1" do
#message = "Hello, this is page 1"
end
or better again
before do
#message = request.path_info == "/page1" ? "PAGE 1!" : "NOT PAGE 1!!"
end
# page1.erb
%p= #message
I would also suggest you take a look at Sinatra Partial if you're looking to do this, as it's a lot easier to handle splitting up views when you have a helper ready made for the job.
Sinatra has no "controller#action" Rail's like concept, so you wont find a way to instantiate the current route. In any case, you can check request.path.split('/').last to get a relative idea of what is the current route.
However, if you want something so be shown only if request.path == "x", a much better way is to put that content on the template, unless that content has to be rendered in a different place within your layout. In that case you can use something like Rail's content_for. Check sinatra-content-for.

Ruby Undefined Local Variable

The following is code from an ERB tutorial. When I tried to execute the code, the compiler complained saying "(erb):16: undefined local variable or method `priority' for main:Object (NameError)". I cannot figure out the reason. Could someone please help me out?
require "erb"
# Create template.
template = %q{
From: James Edward Gray II <james#grayproductions.net>
To: <%= to %>
Subject: Addressing Needs
<%= to[/\w+/] %>:
Just wanted to send a quick note assuring that your needs are being
addressed.
I want you to know that my team will keep working on the issues,
especially:
<%# ignore numerous minor requests -- focus on priorities %>
% priorities.each do |priority|
* <%= priority %>
% end
Thanks for your patience.
James Edward Gray II
}.gsub(/^ /, '')
message = ERB.new(template, 0, "%<>")
# Set up template data.
to = "Community Spokesman <spokesman#ruby_community.org>"
priorities = [ "Run Ruby Quiz",
"Document Modules",
"Answer Questions on Ruby Talk" ]
# Produce result.
email = message.result
puts email
That ERB template looks mangled, a problem caused by your indentation. You just need to fix the middle:
<% priorities.each do |priority| %>
* <%= priority %>
<% end %>
The alternate syntax is to have a % at the very beginning of the line. In your case you have inadvertently added some spaces which are rendering that part of the ERB invalid.

Resources