Delete checked items Rails - ruby-on-rails

I have array selected_ids[] with items id from form, and see them in console when click on the button, but can't delete them in action.
My form:
<% for task in #tasks.where(active: true) %>
<li class="task">
<%= check_box_tag 'selected_ids[]', task.id, false, class: 'selectable' %>
<%= link_to task.title, task, class: "task-title text-dark" %>
</li>
<% end %>
</ul>
My action:
def delete_all
Task.where(id: params[:selected_ids]).destroy_all
#tasks = Task.where(user_id: current_user)
render "index"
end
My routes:
resources :tasks do
get :delete_all, on: :collection
end
Console, when click button:
Started DELETE "/tasks/delete_all" for 127.0.0.1 at 2019-01-18 10:44:18 +0200
Processing by TasksController#destroy as HTML
Parameters: {"utf8"=>"?", "authenticity_token"=>"3BlLqPDnC9IzaVqnCv6qO0KkKP7VNBU9yEnmm8eAKyb76f5eCEIYUq9Gxx4YNbtbcJo0AEi2c/ORs2E87sg0Aw==", "commit"=>"Delete selected", "selected_ids"=>["2", "1"], "id"=>"delete_all"}
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT ? [["id", 1], ["LIMIT", 1]]
? app/controllers/tasks_controller.rb:2
Task Load (0.3ms) SELECT "tasks".* FROM "tasks" WHERE "tasks"."id" = ? ORDER BY "tasks"."id" ASC LIMIT ? [["id", 0], ["LIMIT", 1]]
? app/controllers/tasks_controller.rb:101
Rendering public/404.html within layouts/application
Rendered public/404.html within layouts/application (0.4ms)
Filter chain halted as :set_task rendered or redirected
Completed 404 Not Found in 682ms (Views: 676.8ms | ActiveRecord: 0.6ms)

You have a before_action called set_task in your controller. This is code that will run before delete_all. If you don't want it to run for delete_all, add , except: [:delete_all] to the before_action line:
example:
# change this line somewhere near the top of your controller
before_action :set_task, except: [:delete_all]
If the before_action is set somewhere else like ApplicationController, you can add this line to TasksController instead instead for the same effect:
skip_before_action :set_task, only: [:delete_all]

Related

Uploading image on Rails with Carrierwave. Not updating attribute in database

I'm using the carrierwave gem to upload images
I have this form in my users view which provides an upload button for a file (image)
<%= form_for(#user, html: { multipart: true }) do |f| %>
Update your profile pic:
<span class="avatar">
<%= f.file_field :avatar %>
</span>
<%= f.submit "Update", class: "btn btn-primary" %>
<% end %>
Here's my users controller
class UsersController < ApplicationController
def show
#user = User.find(params[:id])
end
def update
#user = User.find(params[:id])
end
private
def user_params
params.require(:user).permit(:avatar)
end
end
When I click the submit button on the form from the browser, I get this http request come through.
Started PATCH "/users/1" for 127.0.0.1 at 2018-07-05 13:15:39 +0100
Processing by UsersController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"VXaEvnTD7nl+2d/0n1+iB/zwRX+Mf3nbMt0/Qr7m/nYpTmyXCxih981pIbGKGT9qdSfB7zyB6l
CKGdA9uiLouw==", "user"=>{"avatar"=>#<ActionDispatch::Http::UploadedFile:0x00007fbf2a794af0 #tempfile=#<Tempfile:/var/folders
/42/plkmf9zn755b0lvwc2_5k30c0000gn/T/RackMultipart20180705-37847-7s1tba.png>, #original_filename="Screen Shot 2018-07-03 at 1
0.23.17.png", #content_type="image/png", #headers="Content-Disposition: form-data; name=\"user[avatar]\"; filename=\"Screen S
hot 2018-07-03 at 10.23.17.png\"\r\nContent-Type: image/png\r\n">}, "commit"=>"Update", "id"=>"1"}
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2 [["id", 1], [
"LIMIT", 1]]
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
No template found for UsersController#update, rendering head :no_content
Completed 204 No Content in 161ms (ActiveRecord: 0.6ms)
But nothing is updated in the database (i.e. the avatar attribute for the current user still has a value of nil). I also can't see that the image has been saved anywhere.
It's your controller update method which is incomplete, for example :
def update
user = User.find(params[:id]) # Set user
if user.update(user_params) # Save to database
# Success, redirect to show/index/whatever
else
# Fail, render form again
end
end
And i recommend you to read this: http://guides.rubyonrails.org/action_controller_overview.html

Rails: Item not saving to database (routing with nested resources)

I'm running into a problem when trying to create a new object using nested resources in Rails. My routing is set up as:
resources :coins do
resources :questions
resources :events
end
When I attempt to create a new event, it does not save. Adding ! to event.save gave me an error that says "Validation failed: Coin must exist".
I don't have a validation set up for the coin (in the Event model at least, if that is what its referring to). Checking the log file shows the following, which as far as I can tell shows that the correct coin is selected:
Started GET "/coins/1/events/new" for 127.0.0.1 at 2018-01-24 18:52:19 -0500
Processing by EventsController#new as HTML
Parameters: {"coin_id"=>"1"}
[1m[36mCoin Load (0.1ms)[0m [1m[34mSELECT "coins".* FROM "coins" WHERE "coins"."id" = ? LIMIT ?[0m [["id", 1], ["LIMIT", 1]]
[1m[36mUser Load (0.2ms)[0m [1m[34mSELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT ?[0m [["id", 1], ["LIMIT", 1]]
Rendering events/new.html.erb within layouts/application
Rendered events/new.html.erb within layouts/application (3.9ms)
Rendered layouts/_rails_defaults.html.erb (34.8ms)
Rendered layouts/_shim.html.erb (0.6ms)
Rendered layouts/_header.html.erb (6.2ms)
Completed 200 OK in 67ms (Views: 62.3ms | ActiveRecord: 0.3ms)
Started POST "/coins/1/events" for 127.0.0.1 at 2018-01-24 18:54:46 -0500
Processing by EventsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"dAXQ3uwxR2IN2rbAYD//gulHebIOdZWFPYCKnxcUKTuV4QnUp+SZYHMpZUsGOgEXQjOAnhFUO9MpJkIIAKcQlQ==", "event"=>{"content"=>"LKNA", "link"=>"asd"}, "commit"=>"Submit", "coin_id"=>"1"}
[1m[36mCoin Load (0.2ms)[0m [1m[34mSELECT "coins".* FROM "coins" WHERE "coins"."id" = ? LIMIT ?[0m [["id", 1], ["LIMIT", 1]]
[1m[36mUser Load (0.2ms)[0m [1m[34mSELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT ?[0m [["id", 1], ["LIMIT", 1]]
[1m[35m (0.1ms)[0m [1m[36mbegin transaction[0m
[1m[35m (0.0ms)[0m [1m[31mrollback transaction[0m
Completed 401 Unauthorized in 66ms (ActiveRecord: 3.0ms)
ActiveRecord::RecordInvalid (Validation failed: Coin must exist):
app/controllers/events_controller.rb:23:in `create'
I have it set up the same way for my Questions model, as they are almost identical aside from names, and that one works with no issues. I'm at a loss as to what I'm doing incorrectly here.
controller:
class EventsController < ApplicationController
before_action :find_event, only: [:show, :edit, :update, :destroy ]
before_action :find_coin
def index
#events = Event.where(coin_id: #coin.id).order("created_at DESC")
end
def show
end
def new
#event = current_user.events.build
end
def create
#event = current_user.events.build(event_params)
if #event.save!
flash[:success] = "Event Saved"
redirect_to coin_event_path(#coin.id, #event.id)
else
flash[:notice] = "Event *NOT* Saved!!!"
render 'new'
#event.errors.full_messages
end
end
.
.
.
private
def find_event
#event = Event.find(params[:id])
end
def find_coin
#coin = Coin.find(params[:coin_id])
end
def event_params
params.require(:event).permit(:content, :link)
end
end
model:
class Event < ApplicationRecord
belongs_to :user
belongs_to :coin
end
coin model:
class Coin < ApplicationRecord
validates :link_name, :currency_name, presence: true
has_many :questions
has_many :events
end
If anyone has any idea what I may be doing wrong or any tips on how to figure it out, I would really appreciate the assistance.
Making an answer for anyone else who needs it and doesn't read comments :)
When you do:
#event = current_user.events.build(event_params)
You actually create an event related for the user, and it is not related to the coin anymore.
Try to set the coin as well for the event before saving:
#event.coin = #coin
Or you can do it the other way - build the event on the current coin, and then set the user:
#event = #coin.events.build(event_params)
#event.user = current_user
That way - the coin_id will be set automatically because you build an event on that coin.
I have solved the same issue adding 'optional: true' to belongs_to method.
belongs_to :user, optional: true
By default 'belongs_to' require the user_id.
You can use too: 'required: false'.
belongs_to :user, required: false
Good luck.

Ruby on Rails Article Load Rollback on show.html.erb

I can't understand why this is happening, seems that id of article is being queried even though friendly.id has been found. ID being found is "0" for any article that i click, even though the correct article_id (59) is found when associated with a comment.
Processing by ArticlesController#show as HTML
Parameters: {"id"=>"javascript-8"}
User Load (0.6ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2 [["id", 1], ["LIMIT", 1]]
Article Load (0.7ms) SELECT "articles".* FROM "articles" WHERE "articles"."slug" = $1 LIMIT $2 [["slug", "javascript-8"], ["LIMIT", 1]]
(1.9ms) BEGIN
Article Load (0.3ms) SELECT "articles".* FROM "articles" WHERE "articles"."id" = $1 LIMIT $2 [["id", 0], ["LIMIT", 1]]
(1.1ms) ROLLBACK
Rendering articles/show.html.erb within layouts/application
Rendered comments/_comment_form.html.erb (19.3ms)
Comment Load (0.7ms) SELECT "comments".* FROM "comments" WHERE "comments"."article_id" = 59 ORDER BY created_at DESC
Rendered comments/_comment.html.erb (25.2ms)
EDITED: Articles controller
class ArticlesController < ApplicationController
before_action :authenticate_user!
before_action :set_article, only: [:show, :edit, :update, :destroy, :toggle_vote]
impressionist :actions=>[:show]
def show
#article_categories = #article.categories
#comments = Comment.where(article_id: #article).order("created_at DESC")
if #article.status == "draft" && #article.user != current_user
redirect_to root_path
end
end
private
def set_article
#article = Article.friendly.find(params[:id])
end
end
friendly_id :foo, use: :slugged # you must do
MyClass.friendly.find('bar')
or...
friendly_id :foo, use: [:slugged, :finders] # you can now do
MyClass.find('bar')
In your case
def set_article
#article = Article.friendly.find(params[:id])
end
It was because i was using impressionist gem.
I should remove
impressionist :actions=>[:show]
at top of controller, and instead add this in show
def show
impressionist(#article)
end
As written in impressionist gem usage guide (https://github.com/charlotte-ruby/impressionist#usage), "f you're using friendly_id be sure to log impressionist this way, as params[:id] will return a string(url slug) while impressionable_id is a Integer column in database. "

Can I customize Devise's Registration Controller without creating my own set of views?

I have my app/views/devise views, and all I want to do is be able to pass a few instance variables into my edit.html.erb.
Is there a way for me to do that without having to move my registrations/edit.html.erb to another folder?
Edit 1
This is what I have done.
app/views/users/registrations_controller.rb:
class Users::RegistrationsController < Devise::RegistrationsController
def edit
if current_user_subscribed?
#plan = Stripe::Plan.retrieve(current_user.plan_name)
end
super
end
end
This is my routes.rb:
devise_for :users, controllers: {
invitations: 'invitations',
registrations: 'users/registrations'
},
path_names: { :sign_up => "register",
:sign_in => "login",
:sign_out => "logout",
:settings => "settings" }
This is my app/views/devise/registrations/edit.html.erb:
<% if current_user_subscribed? %>
<div class="col-md-12 subscribed-card">
<%= render partial: "subscriptions/card_brand", locals: { brand: current_user.card_brand, plan: #plan } %>
</div>
<% end %>
This is my app/views/subscriptions/_card_brand.html.erb
<div class="payment-card">
<div class="row">
<h2>Subscribed To: <%= plan.name %> for <%= formatted_price(plan.amount) %></h2>
</div>
</div>
But this is the error I am getting:
NoMethodError at /settings
undefined method `name' for nil:NilClass
Edit 2
This is my server log, which doesn't seem to be sending the request to Users::RegistrationsController like I would want:
Processing by Devise::RegistrationsController#edit as HTML
User Load (3.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2 [["id", 7], ["LIMIT", 1]]
Rendering devise/registrations/edit.html.erb within layouts/devise
Role Load (3.4ms) SELECT "roles".* FROM "roles" INNER JOIN "users_roles" ON "roles"."id" = "users_roles"."role_id" WHERE "users_roles"."user_id" = $1 AND (((roles.name = 'coach') AND (roles.resource_type IS NULL) AND (roles.resource_id IS NULL))) [["user_id", 7]]
School Load (1.6ms) SELECT "schools".* FROM "schools" WHERE "schools"."school_type" IN (1, 2)
Rendered subscriptions/_card_brand.html.erb (12.2ms)
Rendered devise/registrations/edit.html.erb within layouts/devise (904.5ms)
Completed 500 Internal Server Error in 994ms (ActiveRecord: 35.1ms)
What am I missing?
You want to expand on the default behaviour of the Devise::RegistrationsController, without moving the files around.
The easiest solution in my opinion would be to inherit the registrations controller into a new class and override the controller used.
Start by creating a new controller, let's say RegistrationsController -> app/controllers/registrations_controller.rb.
Inherit the Devise::RegistrationsController to keep all behaviours and views and add your code to edit action under super.
class RegistrationsController < Devise::RegistrationsController
def edit
super
#my_instance = "Hello World"
end
end
Then point devise's routes to the correct registrations controller.
devise_for :users, :controllers => {:registrations => "registrations"}
Now you should have access to your instance within app/views/devise/registrations/edit.html.erb.
https://gist.github.com/kinopyo/2343176
OP Edit
Make sure to specify the devise_scope to the right path:
devise_scope :user do
get "settings", to: "users/registrations#edit"
end
Which is based on the fact that my version gets routed to the controller users/registrations.

best_in_place with a many to many relationship in rails 4

I have made a github repo that you can find here just for this question. I have 3 models:
class User < ActiveRecord::Base
has_many :user_countries
has_many :event_countries,
-> { where(user_countries: {:event => true}) },
:through => :user_countries,
:source => :country
has_many :research_countries,
-> { where(user_countries: {:research => true}) },
:through => :user_countries
:source => :country
end
class UserCountry < ActiveRecord::Base
belongs_to :country
belongs_to :user
end
class Country < ActiveRecord::Base
# ...
end
So a user should be able to choose event_countries and research_countries.
here's my users controller (nothing complicated):
class UsersController < ApplicationController
respond_to :html, :json
before_action :get_user, only: [:show, :edit, :update]
before_action :get_users, only: [:index]
def index
end
def show
end
def edit
end
def update
#user.update_attributes(user_params)
respond_with #user
end
private
def get_user
#user = User.find(params[:id])
end
def get_users
#users = User.all
end
def user_params
params.require(:user).permit(:first_name, :event_countries => [:id, :name])
end
end
And here's my user show page:
<%= best_in_place #user, :first_name %>
<p> event countries: </p>
<%= best_in_place #user, :event_countries, place_holder: "click here to edit", as: :select, collection: Country.all.map {|i| i.name} %>
<%= link_to "users index", users_path %>
So there's really nothing complicated here. I can also succesfully edit my users first name, best_in_place is working fine.
The question is: how do I edit the event_countries ? As you can see I tried to use the collection option with the countries but when I try to select a country I get the following:
Processing by UsersController#update as JSON
Parameters: {"user"=>{"event_countries"=>"3"}, "authenticity_token"=>"l5L5lXFmJFQ9kI/4klMmb5jDhjmtQXwn6amj1uwjSuE=", "id"=>"6"}
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 6]]
(0.1ms) begin transaction
(0.1ms) rollback transaction
Completed 500 Internal Server Error in 3ms
NoMethodError (undefined method `each' for nil:NilClass):
app/controllers/users_controller.rb:17:in `update'
I don't understand what it's doing, I know it must be a problem with the collection option. If you need to see any file please check my repo here:
https://github.com/spawnge/best_in_place_join_models_twice . I have a spent a lot of time on this any answer/suggestion would be greatly appreciated :)
update:
I have tried this:
<%= best_in_place #user, :event_country_ids, as: :select, collection: Country.all.map { |i| i.name }, place_holder: "click here to edit", html_attrs: { multiple: true } %>
and I have added :event_country_ids to my user params:
params.require(:user).permit(:first_name, :event_country_ids)
And now I can see all the countries but when I select one here's what I get:
Started PUT "/users/3" for 127.0.0.1 at 2014-12-18 01:19:27 +0000
Processing by UsersController#update as JSON
Parameters: {"user"=>{"event_country_ids"=>"1"}, "authenticity_token"=>"aZAFIHgzdSL2tlFcGtyuu+XIJW3HX2fwQGHcB9+iYpI=", "id"=>"3"}
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 3]]
(0.0ms) begin transaction
Country Load (0.0ms) SELECT "countries".* FROM "countries" WHERE "countries"."id" = ? LIMIT 1 [["id", 1]]
Country Load (0.0ms) SELECT "countries".* FROM "countries" INNER JOIN "user_countries" ON "countries"."id" = "user_countries"."country_id" WHERE "user_countries"."event" = 't' AND "user_countries"."user_id" = ? [["user_id", 3]]
SQL (0.1ms) DELETE FROM "user_countries" WHERE "user_countries"."user_id" = ? AND "user_countries"."country_id" = 2 [["user_id", 3]]
SQL (0.0ms) INSERT INTO "user_countries" ("country_id", "event", "user_id") VALUES (?, ?, ?) [["country_id", 1], ["event", "t"], ["user_id", 3]]
(20.9ms) commit transaction
Completed 204 No Content in 28ms (ActiveRecord: 21.3ms)
As you can see it seems that it insert the right content: INSERT INTO "user_countries" ("country_id", "event", "user_id") VALUES (?, ?, ?) [["country_id", 1], ["event", "t"], ["user_id", 3]] However I get the Completed 204 No Content just after that. I don't understand when I refresh the page the input is empty. Any suggestion ?
Update 2:
I checked in the console and it works, I can add event_countries to a user. However it doesn't display the user's event_countries when I refresh the page, I guess that's because I'm using the event_country_ids object.
I think the following code should work:
<%= best_in_place #user, :event_country_ids, as: :select,
collection: Country.all.each_with_object({}) { |i, memo| memo[i.id] = i.name },
place_holder: "click here to edit",
html_attrs: { multiple: true } %>
Assuming you want the user to be able to assign multiple event_countries.
Reference
http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many, specifically the collection_singular_ids= method created by has_many.
https://github.com/bernat/best_in_place#select, the structure of the collection needs to be a hash. For each key => value pair, the key is what's submitted with the form and the value is what's displayed to the user.
http://ruby-doc.org/core-2.1.5/Enumerable.html#method-i-each_with_object, each_with_object is a part of the core Ruby library.

Resources