I have a custom method to update a join table row that used to work and is for some reason errorlessly-failing.
The app is a basic course portal with courses and lessons joined by lesson_completions, which have user_ids, lesson_ids, and a boolean value for complete.
The link I'm using looks like this:
<% if #lesson_completion.complete %>
<td class="pr-1"><%= link_to "<i class='far fa-check-square'></i>".html_safe, uncomplete_lesson_path(#lesson), method: :post, class: "text-red" %></td>
<td><%= link_to "Mark as Unfinished".html_safe, uncomplete_lesson_path(#lesson), method: :post, class: "text-red" %></td>
<% else %>
<td class="pr-1"><%= link_to "<i class='far fa-square'></i>".html_safe, complete_lesson_path(#lesson), method: :post, class: "text-red" %></td>
<td><%= link_to "Mark Lesson as Completed".html_safe, complete_lesson_path(#lesson), method: :post, class: "text-red" %></td>
<% end %>
The methods are in my lesson_completion_controller:
def complete_lesson
#lesson_completion = LessonCompletion.find(params[:id])
if #lesson_completion.update_attributes(complete: true)
redirect_to course_module_path(CourseModule.find(Lesson.find(#lesson_completion.lesson_id).id))
flash[:notice] = "Congratulations on completing that lesson!"
else
redirect_to lesson_path(Lesson.find(#lesson_completion.lesson_id))
flash[:warning] = "Oops! Something went wrong!"
end
end
def uncomplete_lesson
#lesson_completion = LessonCompletion.find(params[:id])
if #lesson_completion.update_attributes(complete: false)
redirect_to lesson_path(Lesson.find(#lesson_completion.lesson_id))
flash[:notice] = "Congratulations on completing that lesson!"
else
redirect_to lesson_path(Lesson.find(#lesson_completion.lesson_id))
flash[:warning] = "Oops! Something went wrong!"
end
end
If I use a debugger and look at the value for #lesson_completion on that page it confirms the correct user_id and lesson_id values.
My routes look like this:
post "lesson_completion/:id/complete_lesson" => "lesson_completion#complete_lesson", as: "complete_lesson"
post "lesson_completion/:id/uncomplete_lesson" => "lesson_completion#uncomplete_lesson", as: "uncomplete_lesson"
When I click the button, the server log shows no errors:
Started POST "/lesson_completion/1/complete_lesson" for ::1 at 2020-09-17 15:17:37 -0700
Processing by LessonCompletionController#complete_lesson as HTML
Parameters: {"authenticity_token"=>"HlCIdRVnOJZIHwPqWoJcu3XpNppi5LNSFvL4odU7DsR42Mw6Ld60IXJxzO/8yEw0qX/LH2PuWFuaywP4Ci3VRw==", "id"=>"1"}
LessonCompletion Load (0.8ms) SELECT "lesson_completions".* FROM "lesson_completions" WHERE "lesson_completions"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
↳ app/controllers/lesson_completion_controller.rb:4
(0.1ms) BEGIN
↳ app/controllers/lesson_completion_controller.rb:5
Lesson Load (1.2ms) SELECT "lessons".* FROM "lessons" WHERE "lessons"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
↳ app/controllers/lesson_completion_controller.rb:5
User Load (1.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
↳ app/controllers/lesson_completion_controller.rb:5
(0.1ms) COMMIT
↳ app/controllers/lesson_completion_controller.rb:5
CACHE Lesson Load (0.0ms) SELECT "lessons".* FROM "lessons" WHERE "lessons"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
↳ app/controllers/lesson_completion_controller.rb:6
CourseModule Load (0.8ms) SELECT "course_modules".* FROM "course_modules" WHERE "course_modules"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
↳ app/controllers/lesson_completion_controller.rb:6
Redirected to http://localhost:5000/course_modules/1
Completed 302 Found in 19ms (ActiveRecord: 4.3ms)
Can anyone see why this value isn't updating? It used to work and is driving me absolutely bonkers now!
Related
I am trying to implement a search method that will automaticaly populate a form through the use of Ajax.
I have a simple_form_form that is feed with a collection of Client instance. Once I select a client, a js code submit the form and then goes to the corresponded controller method.
This part is working, but when the code hits the Client#search it stops at my "respond_to |format|" line. Stating that this is an unknown format.
I looked differents stackover posts, but I could'nt find any concrete answers.
Thanks,
here is the code:
My error:
error messages
routes.rb
Rails.application.routes.draw do
class OnlyAjaxRequest
def matches?(request)
request.xhr?
# raise
end
end
get 'search', to: 'invoices#search', as: 'search', constraint: OnlyAjaxRequest.new
end
formSubmit.js
let clientOption = document.querySelector('#search_client');
const form = document.querySelector('.search');
clientOption.addEventListener('change', (event) => {
form.submit();
})
Client Controller:
def search
if params[:search]
#client_found = Client.find(params[:search][:client]) if Client.find(params[:search][:client]).present?
respond_to do |format|
#format.html {}
format.js { render :search}
end
end
end
Search.js.erb
console.log('hello');
$('#ajx-cli').html("<%= escape_javascript(render partial: 'invoices/invoice_new_partial/find_client')%>");
Client Selection Form
<%= simple_form_for :search, url: search_path, remote: true, method: :get, html: { id: :find_cli } do |f| %>
<%= f.input :client, label:"Sélectionnez un client", collection: #my_clients, label_method: :company_name, value_method: :id, include_blank: true, as: :select %>
<% end %>
Updated Form
<div id='ajx-cli'>
<%= f.fields_for :client do |client| %>
<%= render partial: "invoices/invoice_new_partial/oneoff_client",locals: {f: client, client_found: #client_found} %>
<% end %>
</div>
Also, my search action seems to be processed as html instead of js.
Logs terminal
Started GET "/search?utf8=%E2%9C%93&search%5Bclient%5D=176" for ::1 at 2020-10-17 14:15:07 +0200
Processing by InvoicesController#search as HTML
Parameters: {"utf8"=>"✓", "search"=>{"client"=>"176"}}
User Load (0.5ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2 [["id", 92], ["LIMIT", 1]]
↳ /Users/utilisateur/.rvm/gems/ruby-2.6.3/gems/activerecord-5.2.3/lib/active_record/log_subscriber.rb:98
Invoice Exists (0.7ms) SELECT 1 AS one FROM "invoices" WHERE (due_date < '2020-10-17') AND "invoices"."status" != $1 LIMIT $2 [["status", 3], ["LIMIT", 1]]
↳ app/controllers/application_controller.rb:32
Invoice Update All (0.9ms) UPDATE "invoices" SET "status" = 4 WHERE (due_date < '2020-10-17') AND "invoices"."status" != $1 [["status", 3]]
↳ app/controllers/application_controller.rb:34
Client Load (0.2ms) SELECT "clients".* FROM "clients" WHERE "clients"."id" = $1 LIMIT $2 [["id", 176], ["LIMIT", 1]]
↳ app/controllers/invoices_controller.rb:56
CACHE Client Load (0.0ms) SELECT "clients".* FROM "clients" WHERE "clients"."id" = $1 LIMIT $2 [["id", 176], ["LIMIT", 1]]
↳ app/controllers/invoices_controller.rb:56
Completed 406 Not Acceptable in 9ms (ActiveRecord: 2.3ms)
ActionController::UnknownFormat (ActionController::UnknownFormat):
app/controllers/invoices_controller.rb:58:in `search'
EDIT
Trying to force format didn't work either. My request was correctly processed as JS, so I didn't have the same error, but my search.js.erb was rendered instead of being executed.
New Invoice#search
def search
if params[:search]
#client_found = Client.find(params[:search][:client]) if Client.find(params[:search][:client]).present?
respond_to do |format|
format.js { render layout: false, content_type: 'text/javascript'}
end
end
New Client Selection Form
<%= simple_form_for :search, url: search_path(format: :js), remote: true, method: :get, html: { id: :find_cli } do |f| %>
<%= render partial: "invoices/invoice_new_partial/client_selection",locals: {my_clients: #my_clients, f: f, client_found: #client_found} %>
<% end %>
Logs:
Started GET "/search.js?utf8=%E2%9C%93&search%5Bclient%5D=178" for ::1 at 2020-10-17 19:19:43 +0200
Processing by InvoicesController#search as JS
Parameters: {"utf8"=>"✓", "search"=>{"client"=>"178"}}
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2 [["id", 92], ["LIMIT", 1]]
↳ /Users/utilisateur/.rvm/gems/ruby-2.6.3/gems/activerecord-5.2.3/lib/active_record/log_subscriber.rb:98
Invoice Exists (0.6ms) SELECT 1 AS one FROM "invoices" WHERE (due_date < '2020-10-17') AND "invoices"."status" != $1 LIMIT $2 [["status", 3], ["LIMIT", 1]]
↳ app/controllers/application_controller.rb:32
Invoice Update All (6.5ms) UPDATE "invoices" SET "status" = 4 WHERE (due_date < '2020-10-17') AND "invoices"."status" != $1 [["status", 3]]
↳ app/controllers/application_controller.rb:34
Client Load (0.3ms) SELECT "clients".* FROM "clients" WHERE "clients"."id" = $1 LIMIT $2 [["id", 178], ["LIMIT", 1]]
↳ app/controllers/invoices_controller.rb:56
CACHE Client Load (0.1ms) SELECT "clients".* FROM "clients" WHERE "clients"."id" = $1 LIMIT $2 [["id", 178], ["LIMIT", 1]]
↳ app/controllers/invoices_controller.rb:56
Rendering invoices/search.js.erb
Rendered invoices/invoice_new_partial/_find_client.html.erb (0.5ms)
Rendered invoices/search.js.erb (2.2ms)
Completed 200 OK in 24ms (Views: 5.6ms | ActiveRecord: 7.9ms)
I couldn't wrapped my mind around why my js.erb was rendered as a plain text, instead of being executed, so I started over.
I updated my form Submit.js and it worked like a charm.
New routes.rb
post 'search', to: 'invoices#search', as: 'search'
New Client Selection form
<%= simple_form_for :search, remote: true, html: { id: :find_cli } do |f| %>
<%= render partial: "invoices/invoice_new_partial/client_selection",locals: {my_clients: #my_clients, f: f, client_found: #client_found} %>
<% end %>
New formSubmit.js
let clientOption = document.querySelector('#search_client');
const form = document.querySelector('.search');
clientOption.addEventListener('change', (event) => {
let selector = document.querySelector('#search_client')
let client = selector.options[selector.selectedIndex].value;
Rails.ajax({
type: "post",
url: `/search?utf8=✓&search%5Bclient%5D=${client}`,
headers: {
accept: '*/*',
'X-CSRF-Token': Rails.csrfToken()
}
});
});
As everything working as expected, i'm trying to save the new values in the database but i'm getting a rollback error on update
my model.rb
class User < ApplicationRecord
before_update :update_password
def self.update_password(username, new_password, new_password_conf, old_password)
user = find_by_username(username)
if new_password == new_password_conf && BCrypt::Engine.hash_secret(old_password, user.salt) == user.encrypted_password
new_salt = BCrypt::Engine.generate_salt
new_pass = BCrypt::Engine.hash_secret(new_password, new_salt)
user.update(encrypted_password: new_pass, salt: new_salt)
else
puts "Something went Wrong"
end
end
end
my users_controller.rb
def change_password
user = User.update_password( User.find(session[:user_id]).username,params[:password],params[:password_confirmation],params[:old_password])
end
my html.erb
<%= form_for(:user, :url => {:controller => 'users', :action => 'change_password'}) do |f| %>
<center><p> Παλιός Κωδικός Πρόσβασης</br> <%= f.password_field :old_password, placeholder: "Παλιός Κωδικός Πρόσβασης", name: "old_password"%> </p></center>
<center><p> Νέος Κωδικός Πρόσβασης</br> <%= f.password_field :password, placeholder: "Νέος Κωδικός Πρόσβασης", name: "password"%></p></center>
<center><p> Επιβεβαίωση Νέου Κ.Πρόσβασης</br> <%= f.password_field :password_confirmation, placeholder: "Επιβεβαίωση Νέου Κ.Πρόσβασης", name: "password_confirmation" %></p></center>
<center><%= f.submit "Αποθήκευση", class: 'log_in_button' %><center>
<% end %>
Console output
Started POST "/users/change_password" for 127.0.0.1 at 2020-08-10 01:13:18 +0300
Processing by UsersController#change_password as HTML
Parameters: {"authenticity_token"=>"ORVdeLRZYMjP7XIMqligykYH7YqnjzprTpQnCl3G9XPj36hgEEcC+C/Y1F6Tp3QTOVrheaYD/SZM0BX+i3YERQ==", "old_password"=>"[FILTERED]", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]", "commit"=>"Αποθήκευση"}
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
↳ app/controllers/users_controller.rb:76:in `change_password'
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."username" = $1 LIMIT $2 [["username", "mauras"], ["LIMIT", 1]]
↳ app/models/user.rb:36:in `update_password'
(0.2ms) BEGIN
↳ app/models/user.rb:41:in `update_password'
User Exists? (0.4ms) SELECT 1 AS one FROM "users" WHERE "users"."username" = $1 AND "users"."id" != $2 LIMIT $3 [["username", "mauras"], ["id", 1], ["LIMIT", 1]]
↳ app/models/user.rb:41:in `update_password'
User Exists? (0.4ms) SELECT 1 AS one FROM "users" WHERE "users"."email" = $1 AND "users"."id" != $2 LIMIT $3 [["email", "asdas#adasd.com"], ["id", 1], ["LIMIT", 1]]
↳ app/models/user.rb:41:in `update_password'
(0.3ms) ROLLBACK
↳ app/models/user.rb:41:in `update_password'
Rendering users/change_password.html.erb within layouts/application
Rendered users/change_password.html.erb within layouts/application (Duration: 0.8ms | Allocations: 365)
[Webpacker] Everything's up-to-date. Nothing to do
Completed 200 OK in 608ms (Views: 6.3ms | ActiveRecord: 2.1ms | Allocations: 10770)
also try user.save still nothing,
Just added a new comment feature to my rails app and stumbled upon this issue. I'm getting a NoMethodError in Pics#show which comes from my _comment.html.haml partial.
I can see the comment thread on my show page but after I post the comment I'm getting this. Can go back to uncommented pics, but can't go to the ones I've already commented on.
I've been staring at the code for a while now and I need a fresh pair of eyes.
Started GET "/pics/14" for 127.0.0.1 at 2018-12-19 23:44:51 +0000
(0.5ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC
↳ /Users/alexfurtuna/.rvm/gems/ruby-2.4.0/gems/activerecord-5.2.2/lib/active_record/log_subscriber.rb:98
Processing by PicsController#show as HTML
Parameters: {"id"=>"14"}
Pic Load (0.4ms) SELECT "pics".* FROM "pics" WHERE "pics"."id" = $1 LIMIT $2 [["id", 14], ["LIMIT", 1]]
↳ app/controllers/pics_controller.rb:53
CACHE Pic Load (0.0ms) SELECT "pics".* FROM "pics" WHERE "pics"."id" = $1 LIMIT $2 [["id", 14], ["LIMIT", 1]]
↳ app/controllers/pics_controller.rb:9
Rendering pics/show.html.haml within layouts/application
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
↳ app/views/pics/show.html.haml:14
(0.7ms) SELECT COUNT(*) FROM "votes" WHERE "votes"."votable_id" = $1 AND "votes"."votable_type" = $2 AND "votes"."vote_flag" = $3 [["votable_id", 14], ["votable_type", "Pic"], ["vote_flag", true]]
↳ app/views/pics/show.html.haml:20
Comment Load (0.5ms) SELECT "comments".* FROM "comments" WHERE "comments"."commentable_id" = $1 AND "comments"."commentable_type" = $2 [["commentable_id", 14], ["commentable_type", "Pic"]]
↳ app/views/pics/show.html.haml:28
Rendered collection of comments/_comment.html.haml [1 times] (153.0ms)
Rendered pics/show.html.haml within layouts/application (220.1ms)
Completed 500 Internal Server Error in 267ms (ActiveRecord: 13.0ms)
ActionView::Template::Error (undefined method `comment_comments_path' for #<#. <Class:0x007fa535ee08b8>:0x007fa535ee9d50>
Did you mean? pic_comment_comments_path):
2: = comment.body
3: %small
4: Submitted #{time_ago_in_words(comment.created_at)} ago
5: = form_for [comment, Comment.new] do |f|
6: = f.text_area :body, placeholder: "Add a Reply"
7: %br/
8: = f.submit "Reply"
app/views/comments/_comment.html.haml:5:in `_app_views_comments__comment_html_haml___2866288612795974586_70173756400620'
app/views/pics/show.html.haml:28:in `_app_views_pics_show_html_haml___2738689311384334047_70173775563600'
And this is my _comment partial.
%li
= comment.body
%small
Submitted #{time_ago_in_words(comment.created_at)} ago
= form_for [comment, Comment.new] do |f|
= f.text_area :body, placeholder: "Add a Reply"
%br/
= f.submit "Reply"
%ul
= render partial: 'comments/comment', collection: comment.comments
Everything is fixed now and working properly. Had to pass the #pic variable. Thanks
I understand that this has been asked many times, but for some reason none of the other solutions worked for me. I'm still unable to save a field with an enum on update.When I pass a non-enum value, like first_name, with the same form, it updates just fine, but the enum value, gender, never saves even though it shows that it is...
View:
<%= form_for(#patient, url: patient_path(params[:id])) do |f| %>
<%= f.fields_for :role do |r| %>
<%= r.fields_for :user do |u| %>
<div class="keyvalue">
<div class="key"><p>Gender</p></div>
<div class="value">
<%= u.select :gender, User.genders.map { |key, value| [key.humanize, key] }, include_blank: '-Select A Gender-' %>
</div>
<div class="push"></div>
</div><!--keyvalue-->
<% end %>
<% end %>
<% end %>
Controller:
def update
#patient = Patient.find(params[:id])
if #patient.update(patient_params)
flash[:success] = "Patient's record has been updated."
redirect_to patient_path(params[:id])
else
flash[:error] = #patient.errors.full_messages.to_sentence
redirect_to patient_path(params[:id])
end
end
Log:
Parameters: {"utf8"=>"✓", "authenticity_token"=>"*********", "commit"=>"Update", "patient"=>{"role_attributes"=>{"user_attributes"=>{"first_name"=>"John", "middle_name"=>"Joseph", "last_name"=>"Doe", "date_of_birth"=>"1943-12-25", "gender"=>"male", "blood_type"=>"", "ethnicity"=>"", "marital_status"=>"", "id"=>"1"}, "id"=>"1"}}, "id"=>"1"}
Patient Load (0.1ms) SELECT "patients".* FROM "patients" WHERE "patients"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
(0.0ms) begin transaction
Role Load (0.1ms) SELECT "roles".* FROM "roles" WHERE "roles"."roleable_id" = ? AND "roles"."roleable_type" = ? LIMIT ? [["roleable_id", 1], ["roleable_type", "Patient"], ["LIMIT", 1]]
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
User Exists (0.1ms) SELECT 1 AS one FROM "users" WHERE "users"."username" = ? AND ("users"."id" != ?) LIMIT ? [["username", "dev"], ["id", 1], ["LIMIT", 1]]
SQL (0.3ms) UPDATE "users" SET "gender" = ?, "updated_at" = ? WHERE "users"."id" = ? [["gender", 0], ["updated_at", "2018-04-24 02:11:23.126843"], ["id", 1]]
(2.6ms) commit transaction
Redirected to http://localhost:3000/patients/1
Completed 302 Found in 10ms (ActiveRecord: 3.2ms)
Enum in User model:
enum gender: [:male, :female, :non_binary, :rather_not_say]
Migration:
t.integer :gender
The log shows no issue, it shows the gender field being updated, but if I go to the rails console it shows gender as nil
I want to implement a way of clicking a button and running a method without having to switch to the view of the specifid item/object found by id. I'm using PostgrSQL.
In my PaymentsController I have a method called withdraw, which looks something like this:
def withdraw
#payment = Payment.find(params[:id])
#payment.withdrawn = true
#payment.amount_interest = withdraw.amount * 1.1
#payment.save
head :ok
end
And the route:
patch '/withdraw/:id', to: 'payments#withdraw', as: :withdraw
each statement with link_to:
<% #payments.each do |withdraw| %>
<tr>
<td><%= withdraw.amount %></td>
<td><%= link_to 'Withdraw', withdraw_path(withdraw), method: :patch, remote: true %></td>
</tr>
<% end %>
EDIT: Upon clicking "Withdraw" I get an unending database query that looks like this:
Started PATCH "/withdraw/1" for 127.0.0.1 at 2016-11-11 21:20:34 +0200
Processing by PaymentsController#withdraw as JS
Parameters: {"id"=>"1"}
Started PATCH "/withdraw/1" for 127.0.0.1 at 2016-11-11 21:20:34 +0200
Processing by PaymentsController#withdraw as JS
Member Load (40.0ms) SELECT "members".* FROM "members" WHERE "members"."id" = $1 ORDER BY "members"."id" ASC LIMIT $2 [["id", 1], ["LIMIT", 1]]
Parameters: {"id"=>"1"}
Member Load (1.4ms) SELECT "members".* FROM "members" WHERE "members"."id" = $1 ORDER BY "members"."id" ASC LIMIT $2 [["id", 1], ["LIMIT", 1]]
Payment Load (0.0ms) SELECT "payments".* FROM "payments" WHERE "payments"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Payment Load (2.0ms) SELECT "payments".* FROM "payments" WHERE "payments"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Payment Load (1.1ms) SELECT "payments".* FROM "payments" WHERE "payments"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Payment Load (0.0ms) SELECT "payments".* FROM "payments" WHERE "payments"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
My Payments model has the following:
account:string amount:decimal paid:boolean withdrawn:boolean amount_interest:decimal
belongs_to :member
Any assistance will be greatly appreciated.
The issue was a bug in my withdraw method.
changed:
#payment.amount_interest = withdraw.amount * 1.1
to:
#payment.amount_interest = #payment.amount * 1.1