While processing a new user registration, the log shows an expected
Completed 422 Unprocessable Entity in 462ms (ActiveRecord: 18.7ms | Allocations: 62328)
ActiveRecord::RecordInvalid (Validation failed: Email has already been taken):
[...]
Rendering layout layouts/application.html.erb
Rendering acqs/registration_alt.html.erb within layouts/application
↳ app/views/users/registrations/_new.html.erb:19
Rendered users/shared/_error_messages.html.erb (Duration: 0.1ms | Allocations: 22)
The sequence is correct as registration_alt.html.erb calls <%= render 'users/registrations/new' %>
However the partial invoked in the form
<%= form_for(resource, as: resource_name, validate: true, url: registration_path(resource_name), html: {class: 'registration'}) do |f| %>
<%= render "users/shared/error_messages", resource: resource %>
the file /users/shared/_error_messages.html.erb defines:
<% if resource.errors.any? %>
<div id="error_explanation">
<h2>
<%= I18n.t("errors.messages.not_saved",
count: resource.errors.count,
resource: resource.class.model_name.human.downcase)
%>
</h2>
<ul>
<% resource.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
Is not rendering.
The registrations controller has an articulated create method, where it has to create an associated records.
def create
user_params = params[:user]
initialise_user_with_municipal(params[:user])
if user_params[:mobile].present?
sanitize_spaces(user_params[:mobile])
end
set_user_login_name
build_resource(sign_up_params)
# resource.save!
save_resource_and_roleshopuser(resource)
yield resource if block_given?
execute_devise_methods
end
def save_resource_and_roleshopuser(resource)
if resource.save!
#roleshopuser = Roleshopuser.create(role_id: 1, shop_id: #shop.id, user_id: resource.id)
if params[:user][:municipal_other].present?
set_shopzone(resource)
end
end
end
Now I suspect the chaining of record creation might be a source of issues. The error in this instance is occurring at the user creation stage build_resource(sign_up_params) for the line if resource.save! of method save_resource_and_roleshopuser so the errors should be filtering...
What is missing for the errors to percolate to the view?
Related
context testing rails-ujs functionality with Rails 7 turbo streams as a full replacement.
Class nesting is structured as follows:
class Cartitem < ApplicationRecord
belongs_to :article
belongs_to :cart
validates :quantity_ordered, numericality: { greater_than: 0 }, on: :create
validates :quantity_ordered, numericality: { greater_than_or_equal_to: 0 }, on: :update
end
A page of articles can potentially create cartitems, one per article.
Each article needs to be creatable, updatable, deletable (so it may be recreated for users who change their minds incessantly).
Accordingly, that page has a block for each article
<% articles.each do |article| %>
<%= render 'article', article: article %>
<% end %>
# article partial
<div>
<%= article.description_short %>
</div>
<div>
<%= turbo_frame_tag dom_id(article) do %>
<%= render 'cartitem_block', article: article %>
<% end %>
</div>
the partial then invokes a turbo frame:
<%= turbo_frame_tag dom_id(article) do %>
<%= form_with(model: #cartitem, local: false) do |f| %>
<%= f.number_field :quantity_ordered %>
<%= f.submit %>
<% end %>
<% end %>
The rendered HTML does call the dom_ids and renders as expected:
<turbo-frame id="article_1">
<form action="/cartitems" accept-charset="UTF-8" data-remote="true" method="post"><input type="hidden" name="authenticity_token" value="sgABxVmZX0TDditdtwuGrgG4t9fkdfFMg02tpDnfgX3ch_IqD_YGoFJroE4u3y9t-bdLfGAyXZBUyJe04RBqtQ" autocomplete="off">
<input min="1" type="number" name="cartitem[quantity_ordered]" id="cartitem_quantity_ordered">
<button name="button" type="submit" ></button>
</form>
</turbo-frame>
[...]
<turbo-frame id="article_5">
<form action="/cartitems" accept-charset="UTF-8" data-remote="true" method="post"><input type="hidden" name="authenticity_token" value="..." autocomplete="off">
<input min="1" type="number" name="cartitem[quantity_ordered]" id="cartitem_quantity_ordered">
<button name="button" type="submit" ></button>
</form>
</turbo-frame>
The controller:
def create
#article = Article.find(params[:cartitem][:article_id])
price_ordered = #article.sell_price * params[:cartitem][:quantity_ordered].to_d
#cartitem = Cartitem.create!(article_id: #article.id, quantity_ordered: params[:cartitem][:quantity_ordered].to_d, price_ordered: price_ordered, cart_id: params[:cartitem][:cart_id].to_i)
respond_to do |format|
if #cartitem.save
format.turbo_stream
format.html { redirect_to cartitem_url(#cartitem), notice: "Cartitem was successfully created." }
else
format.turbo_stream
format.html { render :new, status: :unprocessable_entity }
end
end
end
If #cartitem is valid, the process runs and renders as expected:
Rendered cartitems/_cartitem.html.erb (Duration: 1.0ms | Allocations: 953)
Rendered cartitems/create.turbo_stream.erb (Duration: 1.3ms | Allocations: 1082)
However upon submitting with an empty value, to test the validation, an unexpected result occurs:
Started POST "/cartitems" for 127.0.0.1 at 2022-01-22 08:24:38 +0100
Processing by CartitemsController#create as TURBO_STREAM
Parameters: {"authenticity_token"=>"[FILTERED]", "cartitem"=>{"price_ordered"=>"3.41", "cart_id"=>"1", "article_id"=>"1", "fulfilled"=>"false", "quantity_ordered"=>""}}
[...]
TRANSACTION (0.2ms) ROLLBACK
TRANSACTION (0.2ms) ROLLBACK
↳ app/controllers/cartitems_controller.rb:28:in `create'
Completed 422 Unprocessable Entity in 11ms (ActiveRecord: 1.1ms | Allocations: 4874)
ActiveRecord::RecordInvalid (Validation failed: Quantity ordered must be greater than 0):
As expected, the transaction rolls back. However, the response is an Unprocessable Entity.
and the return is not what the create.turbo_stream.erb is stated to do, i.e. if the cartitem is nil re-render the partial.
*note: the else portion of the respond_to block was tried both with and without a reference to turbo_stream with identical result.
<% if #cartitem %>
<%= turbo_stream.replace "article_#{article.id}", #cartitem %>
<% else %>
<%= render 'cartitem_block', article: #article %>
<% end %>
# _cartitem partial:
<%= turbo_frame_tag dom_id(#cartitem.article), class: 'fade-text' do %>
<%= form_with(url: update_q_cartitem_path(#cartitem), local: false, method: :patch) do |form| %>
<%= form.number_field :quantity_ordered, value: number_with_precision(#cartitem.quantity_ordered, precision: 0), min: 0, style: 'width: 69px; display: inline-block;' %>
<%= button_tag(style: 'display: inline-block;') do %>
<p class='button warning' style='margin-top: 10px;'><%= fa_icon('recycle', class: 'fa 3x') %></p>
<% end %>
<% end %>
<% end %>
Instead, the xhr response returned is the HTML page of an error returned when in development mode.
The browser console in addition complains with
Response has no matching <turbo-frame id="article_1"> element
which is untrue as the HTML still has a lingering:
<turbo-frame id="article_1"></turbo-frame>
What needs to be done to properly error handle the case, render the form partial in its rightfully recognized place?
The condition where params submitted do not create a valid object should be explicit, particularly as the situation depends on a parent object:
else
format.turbo_stream { render turbo_stream: turbo_stream.replace( #article, partial: 'carts/cartitem_block', locals: { article: #article } ) }
end
otherwise the turbo_stream insists on trying to render the create turbo_stream variant which, in one case is calling a NULL object #cartitem and thus fails and is not able to proceed.
In your controller, you save the cartitem twice. The first instance (create!) throws an exception and stops the processing. Instead of
#cartitem = Cartitem.create!(blaa blaa)
Try
#cartitem = Cartitem.new(blaa blaa)
Now the object will get validated at the #cartitem.save step, and your turbo_stream file should load.
Also, and not related to the error, you could use strong parameters to make the controller action tidier and improve security.
I am trying to save data, but on submitting the data, it just refreshes the page, but not actually stores data in table. and even it is not giving any errors too. What I want to do is after saving data, control should come on same page with empty textboxes.
Using Ruby 2.4.1, Rails 5.1.3, sqLite3
This is content of feedback_controller.rb
class FeedbackController < ApplicationController
def new
#feedback = Feedback.new
end
def create
#feedback = Feedback.new(feedback_params)
redirect_to root_path
respond_to do |f|
if #feedback.save
f.html {redirect_to #feedback, notice: 'feedback submitted'}
f.json {render :new, status: :created, location: :#feedback}
else
f.html {render :new }
f.json {render json: #feedback.errors, status: :unprocessable_entity}
end
end
end
private
# def set_feedback
# #feedback = Feedback.find(params[:id])
# end
def feedback_params
params.require(:feedback).permit(:name, :email, :message)
end
end
And here is new.html.erb file.
<%= form_with scope: :feedback, url: feedback_new_path, local: true do |form| %>
<% if #feedback.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(feedback.errors.count, "error") %> prohibited this feedback from being saved:</h2>
<ul>
<% #feedback.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= form.label :name %>
<%= form.text_field :name, id: :feedback_name %>
</div>
<div class="field">
<%= form.label :email %>
<%= form.text_field :email, id: :feedback_email %>
</div>
<div class="field">
<%= form.label :message %>
<%= form.text_area :message, id: :feedback_message %>
</div>
<div class="actions">
<%= form.submit "Submit Feedback"%>
</div>
<% end %>
<%= link_to 'Home', root_path %>
This is what puma server saying on log while storing data:
Started POST "/feedback/new" for 127.0.0.1 at 2017-09-14 21:33:41 +0530
Processing by FeedbackController#new as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"Dk1sGiKYryIOeU6HyO7zeX6wqXazj9BUfooJgIDH1JjHxuKwA5MT0E6zvuwFYXGA8xEOz+tGAiXWySKv7voKvg==", "feedback"=>{"name"=>"sheshang", "email"=>"sid#gm.co", "message"=>"this is demo message"}, "commit"=>"Submit Feedback"}
Rendering feedback/new.html.erb within layouts/application
Rendered feedback/new.html.erb within layouts/application (3.8ms)
Completed 200 OK in 75ms (Views: 55.2ms | ActiveRecord: 1.3ms)
In addition to this problem, I want to know that how to debug in rails app. Like in C or any other program we used to put printf statements to check whether the control is going inside or not. How we can do in Rails?
As you can see, you're posting to the new action:
Started POST "/feedback/new" for 127.0.0.1 at 2017-09-14 21:33:41 +0530
Processing by FeedbackController#new as HTML
But the new action doesn't do a save.
So, you probably want:
<%= form_with scope: :feedback, url: feedbacks_path, local: true do |form| %>
By convention, if you do (in your routes.rb file):
resources :feedbacks
then you should get:
feedbacks GET /feedbacks(.:format) feedbacks#index
POST /feedbacks(.:format) feedbacks#create
new_feedback GET /feedbacks/new(.:format) feedbacks#new
edit_feedback GET /feedbacks/:id/edit(.:format) feedbacks#edit
feedback GET /feedbacks/:id(.:format) feedbacks#show
PATCH /feedbacks/:id(.:format) feedbacks#update
PUT /feedbacks/:id(.:format) feedbacks#update
DELETE /feedbacks/:id(.:format) feedbacks#destroy
As you can see, this does not generate a POST verb for the new action, which suggests that you're not using conventional routes. If that is true, then you may need to update your routes so that you get feedbacks_path.
I recommend following convention as it often makes life easier.
As far as printing to console, I tend to do:
puts "#{self.class}.#{__method__}, var: #{var}"
I replace var with whatever variable I want to inspect. I like to include the #{self.class}.#{__method__} bit because it let's me know which class and method I'm in.
I'd like to pass parameter not related to model by form_for on rails.I want to pass 'address' data, that is not related to product model, from view to controller. The following is my code, however it returned the next error. Could you tell me how to solve this problem?
Completed 500 Internal Server Error in 11ms (ActiveRecord: 0.1ms)
ActionView::Template::Error (wrong number of arguments (1 for 2..5)):
products_controller
class ProductsController < ApplicationController
~~~~
def transfer
#product = Product.new
end
def transfer_done
my_address = params[:my_address]
wallet = Wallet.find_by(address:my_address)
redirect_to root_url
end
~~~~
end
transfer.html.erb
<% provide("transfer") %>
<p>
<%= form_for #product, :url => {:action => 'transfer_done'} do |f| %>
<div>
<%= check_box :my_address %> <---Error occurred here.
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
</p>
You may try <%= text_field_tag :my_address %> inside your form
I have Realization model:
# encoding : utf-8
class Realization < ActiveRecord::Base
attr_accessible :city, :street, :title, :work, :photo, :date
has_attached_file :photo
end
Controller:
# encoding : utf-8
class RealizationsController < ApplicationController
before_filter :admin_required, :except => [:index,:show]
# GET /realization/new
def new
#realization = Realization.new
#realization.date = Time.now.__send__(:to_date).to_s
end
# POST /realization
def create
#realization = Realization.new(params[:realization])
if #realization.save
redirect_to #realization, notice: 'realization was successfully created.'
else
render action: "new"
end
end
(...) others
View of form:
<%= form_for #realization, :html => { :multipart => true } do |f| %>
<% if #realization.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#realization.errors.count, "error") %> prohibited this realization from being saved:</h2>
<ul>
<% #realization.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :title %><br />
<%= f.text_field :title %>
</div>
(...)
<div class="field">
<%= f.file_field :photo %>
</div>
<div class="actions">
<%= f.submit "Submit" %>
</div>
<% end %>
And routes :
resources :realizations
And WEBrick server info is that:
Started POST "/realizacje" for 127.0.0.1 at 2013-04-12 12:26:35 +0200
Processing by RealizationsController#index as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"zK5jP4ChBBY+R21TjrZkp4xGvCHViTFJ+8Fw6Og28YY=", "realization"=>{"title"=>"wwwwww", "street"=>"", "city"=>"", "work"=>"", "date"=>"2013-04-12"}, "commit"=>"Submit"}
(1.0ms) SELECT COUNT(*) FROM "realizations"
Realization Load (2.0ms) SELECT "realizations".* FROM "realizations" ORDER BY created_at DESC LIMIT 7 OFFSET 0
User Load (1.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 LIMIT 1
Rendered realizations/index.html.erb within layouts/application (156.0ms)
Completed 200 OK in 340ms (Views: 333.0ms | ActiveRecord: 4.0ms)
While I use the form and push the submit it redirects/randers realizations/index without notice or errors even!
I have completely no idea why? Especialy that it worked before...
Maybe javascript added later on may be the reason?
Paperclip works well in update so it isn't it...
You might check your new action to see what you're passing in to the form_for.
You want to be passing in a brand new instance of your Realization model.
i.e. in the new action you should have a line that reads #realization = Realization.new
The reason I suggest this is because form_for calls a method (#new_record?) on the object you give it and will submit a post or put request depending on whether that method call returns true or false.
I have a nav menu with 2 tabs/links in the show.html.erb file, in UsersController.rb, I would like to use ajax to render different partial for the tabs.
In the show.html.erb I have a div named profile-data where I want to show the content.
So I do something like this:
The link structure:
<li><%= link_to "College friends", college_friends_path, :remote => true %></li>
<li><%= link_to "Highschool friends", highschool_friends_path, :remote => true %></li>
I define the routes:
match "college_friends" => "users#college_friends", :as => "college_friends"
match "highschool_friends" => "users#highschool_friends, :as => "highschool_friends"
And I define in my UserController.rb the necessary methods:
class UsersController < ApplicationController
def show
#user = User.find(params[:id])
end
def college_friends
respond_to do |format|
format.js
end
end
def highschool_friends
respond_to do |format|
format.js
end
end
end
Last thing we have the JS files:
*college_friends.js.erb*
$('#profile-data').html("<%= escape_javascript(render(:partial => 'college_friends')) %>");
*highschool_friends.js.erb*
$('#profile-data').html("<%= escape_javascript(render(:partial => 'highschool_friends')) %>");
The partial code: _college_friends.html.erb
<% groups = #user.friends.group_by(&:college_name) %>
<% sorted_groups = groups.sort_by{|key, values| values.count}.reverse %>
<% sorted_groups.each do |collegename, friends| %>
<% next if collegename.blank? %>
<div class="contentbox">
<div class="box-header">
<h3><%= collegename %></h3>
<div class="meta-info">
<p><i class="icon-map-marker"></i> Malmö</p>
<p><i class="icon-user"></i><span class="count"> <%= friends.count %></span> vänner</p>
</div>
</div>
<ul class="friends-list">
<% friends.map do |friend| %>
<li><%= image_tag(friend.image) %>
<% end %>
</ul>
</div>
<% end %>
Nothing happens when I click the the links, and get this error in the console:
Started GET "/universitet_friends" for 127.0.0.1 at 2012-07-29 01:53:39 +0200
Processing by UsersController#universitet_friends as JS
Rendered users/_universitet_friends.html.erb (1.6ms)
Rendered users/universitet_friends.js.erb (3.1ms)
Completed 500 Internal Server Error in 7ms
ActionView::Template::Error (undefined method `friends' for nil:NilClass):
1: <% groups = #user.friends.group_by(&:college_name) %>
2: <% sorted_groups = groups.sort_by{|key, values| values.count}.reverse %>
3: <% sorted_groups.each do |collegename, friends| %>
4: <% next if collegename.blank? %>
app/views/users/_universitet_friends.html.erb:1:in `_app_views_users__universitet_friends_html_erb___1983680250475155079_70236040373720'
app/views/users/universitet_friends.js.erb:1:in `_app_views_users_universitet_friends_js_erb__1317362850668628869_70236044930260'
app/controllers/users_controller.rb:19:in `universitet_friends
Any help would be appreciated.
ActionView::Template::Error (undefined method `friends' for
nil:NilClass):
This is telling you that your #user variable is nil. This happened because when you went back to your controller for the AJAX request, you never actually set the #user variable. It does not persist between requests. You need to pass that variable during the ajax request. One way to do it is to add a user_id param to the ajax URL.
May be you can do something like this too
<%=link_to "Highschool friends", college_friends_path(:user_id => #user.id), :remote => true %>
The best way to do however would be to pass the user_id param to ajax url..you can fire the ajax request on link "on-click" event.