Adding a button on a specific page with backlinks - ruby-on-rails

First post, so i'm a newbie in StackOverflow. I'm trying for several days to make appear a Return button on a page form but only on a specific one.
So, I was advised to use backlink to make it appears.
Here's my code from the form where I want the return button
<% if #backlink.present? %>
<div class="spacer30"></div>
<% if #backlink == 'infos' %>
path = membre_path(menu: 'infos')
<% end %>
<% end %>
<%= link_to "Retour", path, class: "btn-rounded btn-turquoise btn-small" %>
Here's my code controller
def edit
super do |user|
puts "TEST PARAMS BACKLINK #{params[:backlink]}"
#backlink = params[:backlink]
end
end
and my route's :
get 'change_password', to: 'users/registrations#edit'
put 'update' => 'users/registrations#update', :as => 'user_registration'
get 'edit_password', to: 'users/registrations#edit', :as => 'user_edit'
So i should have in my log my PUTS 'TEST PARAMS BACKLINK' but nothing appear, only :
Started GET "/change_password.1?backlink=infos" for ::1 at 2017-10-04 10:07:41 +0200
Processing by Users::RegistrationsController#edit as
Parameters: {"backlink"=>"infos"}
User Load (9.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2 [["id", 1], ["LIMIT", 1]]
Rendering users/registrations/edit.html.erb within layouts/application
Rendered users/registrations/edit.html.erb within layouts/application (14.4ms)
Rendered shared/_navbar.html.erb (4.0ms)
Rendered shared/_flashes.html.erb (1.1ms)
Completed 200 OK in 231ms (Views: 217.0ms | ActiveRecord: 9.1ms)
Any ideas why it doesn't work?
Many thanks.

I just had to delete some lines, here's what i changed from my registration controller :
def edit
#backlink = params[:backlink]
super
end
This way, it appears exactly the way I wanted to.
Many thanks :)

Related

Can't purge active storage attachments

I have a model called Resource configured with:
class Resource < ActiveRecord::Base
has_many_attached :assets
end
I created an action in my resources_controller.rb as follows:
def delete_asset_attachment
#asset = ActiveStorage::Attachment.find_by(params[:id])
logger.debug "The value of #asset is #{#asset}"
#asset.purge
redirect_to #resource
end
I have a form that shows the resource and loops through the attached assets. Below is the snippet of code doing the loop through the assets:
<% #resource.assets.each do |asset| %>
<%= link_to 'Remove Attachment', delete_asset_attachment_resource_url(#resource, asset.id), method: :delete, data: { confirm: 'Are you sure?' } %>
<% end %>
The /resources page properly shows the resource along with the attached assets. However, when I try to click the link to delete one of the assets, I receive an error: "undefined method `purge' for nil:NilClass". However, in console I see the attachment exists.
Here is the output from the server console:
Started DELETE "/resources/10/delete_asset_attachment.18" for ::1 at 2019-03-09 17:27:28 -0500
Processing by ResourcesController#delete_asset_attachment as
Parameters: {"authenticity_token"=>"EFZO5V9Bii3dId0I6hn5DajFR5WJYZBc8qPAAi5ppQOFW3cws5I4FjyVP9IlvA+2a2kKUJhobnqd8atG4L3k+g==", "id"=>"10"}
Resource Load (0.1ms) SELECT "resources".* FROM "resources" WHERE "resources"."id" = ? LIMIT ? [["id", 10], ["LIMIT", 1]]
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT ? [["id", 1], ["LIMIT", 1]]
ActiveStorage::Attachment Load (0.1ms) SELECT "active_storage_attachments".* FROM "active_storage_attachments" WHERE (10) LIMIT ? [["LIMIT", 1]]
The value of #asset is #<ActiveStorage::Attachment:0x00007f8d7bd4df68>
ActiveStorage::Blob Load (0.2ms) SELECT "active_storage_blobs".* FROM "active_storage_blobs" WHERE "active_storage_blobs"."id" = ? LIMIT ? [["id", 27], ["LIMIT", 1]]
Completed 500 Internal Server Error in 5ms (ActiveRecord: 0.6ms)
NoMethodError - undefined method `purge' for nil:NilClass:
::1 - - [09/Mar/2019:17:27:28 EST] "POST /resources/10/delete_asset_attachment.18 HTTP/1.1" 500 76939
http://localhost:3000/resources/10/edit -> /resources/10/delete_asset_attachment.18
Started POST "/__better_errors/70da0e976a425fce/variables" for ::1 at 2019-03-09 17:27:28 -0500
ActiveStorage::Blob Load (0.2ms) SELECT "active_storage_blobs".* FROM "active_storage_blobs" WHERE "active_storage_blobs"."id" = ? LIMIT ? [["id", 27], ["LIMIT", 11]]
::1 - - [09/Mar/2019:17:27:28 EST] "POST /__better_errors/70da0e976a425fce/variables HTTP/1.1" 200 36499
http://localhost:3000/resources/10/delete_asset_attachment.18 -> /__better_errors/70da0e976a425fce/variables
I've searched for solutions everywhere. The couple that exist on stackoverflow didn't address my issue. There is an incredible lack of specific details and examples in the Rails guide or anywhere else on the web for specifically handling deleting attachments. Would appreciate any help.
UPDATE: Here are my routes.rb:
resources :resources do
get 'listing', :on => :collection
put :sort, on: :collection
member do
delete :delete_asset_attachment
end
end
UPDATE 2: rails routes output
resources GET /resources(.:format) resources#index
POST /resources(.:format) resources#create
new_resource GET /resources/new(.:format) resources#new
edit_resource GET /resources/:id/edit(.:format) resources#edit
resource GET /resources/:id(.:format) resources#show
PATCH /resources/:id(.:format) resources#update
PUT /resources/:id(.:format) resources#update
DELETE /resources/:id(.:format) resources#destroy
I've been able to make this work. Ahhhh. The rush, after hours of frustration.
Piecing things together after reading this article
Deleting ActiveStorage Attachments From the Controller, 3 Ways
I changed my controller code to be this:
def delete_asset_attachment
#resource.assets.find_by(params[:attachment_id]).purge
redirect_to #resource
end
and my form to be this:
<% #resource.assets.each do |asset| %>
<%= asset.filename %>
<%= link_to 'Remove Attachment', delete_asset_attachment_resource_url(#resource, asset.id), method: :delete, data: { confirm: 'Are you sure?' } %>
<% end %>
I believe the issue was that the line in my old code:
#asset = ActiveStorage::Attachment.find_by(params[:id])
...was only passing the #resource id and the attachment was not being found. The key was changing this line:
#resource.assets.find_by(params[:attachment_id]).purge
...which more properly points to the correct resource and then the specific asset (attachment) to be purged.
Fix the syntax of find_by and use safe ampersand, instead
#asset = ActiveStorage::Attachment.find_by(params[:id])
#asset.purge
try:
#asset = ActiveStorage::Attachment.find_by(id: params[:id])
#asset&.purge

How to pass data from view that came from an external API to a controller?

So I want to pass a data from a view that was rendered from an external api to a controller to be able to save the ID to a model/database table.
This is my view:
<h1>Heroes</h1>
<% #response.each do |hero| %>
<div class = "hero_wrap">
<div class = "img">
<img src="https://api.opendota.com<%= hero["img"]%>", id ="hero_img"/>
</div>
<div class = "fave_container">
<%= link_to(image_tag('fave.png', class: "fave_img"), new_hero_path) %>
<%= hero["id"]%>
</div>
<div class = "hero_name">
<%= hero["localized_name"] %>
</div>
</div>
<% end %>
My controller:
# heroes_controller
class HeroesController < ApplicationController
def index
#response = HTTParty.get("https://api.opendota.com/api/heroStats")
end
def create
#hero= Hero.new(params[:id])
#hero.save
redirect_to #hero
end
end
Routes:
Rails.application.routes.draw do
get '/signup', to: 'users#new'
get 'pages/home'
resources :pro_players
devise_for :users
resources :heroes
resources :users
root 'pages#home'
end
My hero model doesn't contain anything yet, I just want to pick the hero id and save it to my database.
this is my web app
server log upon clicking the star icon with link:
Started GET "/heros?custom_hero_id=1&method=post" for 127.0.0.1 at
2018-10-15 09:20:53 +0800
Processing by HerosController#index as HTML
Parameters: {"custom_hero_id"=>"1", "method"=>"post"}
User Load (0.7ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2 [["id", 1], ["LIMIT", 1]]
↳/home/don/.asdf/installs/ruby/2.5.1/lib/ruby/gems/2.5.0/gems/activerecord-
5.2.1/lib/active_record/log_subscriber.rb:98
Rendering heros/index.html.erb within layouts/application
Rendered heros/index.html.erb within layouts/application (42.2ms)
Rendered layouts/_header.html.erb (1.1ms)
Rendered layouts/_footer.html.erb (0.4ms)
Completed 200 OK in 770ms (Views: 83.3ms | ActiveRecord: 0.7ms)
Updated log:
Started POST "/heros?custom_hero_id=21" for 127.0.0.1 at 2018-10-15 10:13:17 +0800
Processing by HerosController#create as HTML
Parameters: {"authenticity_token"=>"PHDEXdDmPhPX+VdloU2y6yONY5HN5wI2lIfOaSbSKj9+RvTO5Ua3QPuTcreLZtGNDFPaSOXhDVyve6J69+1CQQ==", "custom_hero_id"=>"21"}
User Load (0.7ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2 [["id", 1], ["LIMIT", 1]]
↳/home/don/.asdf/installs/ruby/2.5.1/lib/ruby/gems/2.5.0/gems/activerecord-5.2.1/lib/active_record/log_subscriber.rb:98
(0.2ms) BEGIN
↳ app/controllers/heros_controller.rb:9
Hero Create (0.4ms) INSERT INTO "heros" ("created_at", "updated_at") VALUES ($1, $2) RETURNING "id" [["created_at", "2018-10-15 02:13:17.032248"], ["updated_at", "2018-10-15 02:13:17.032248"]]
↳ app/controllers/heros_controller.rb:9
(42.3ms) COMMIT
↳ app/controllers/heros_controller.rb:9
Redirected to http://localhost:3000/heros/10
Completed 302 Found in 59ms (ActiveRecord: 46.9ms)
Started GET "/heros/10" for 127.0.0.1 at 2018-10-15 10:13:17 +0800
AbstractController::ActionNotFound (The action 'show' could not be found for HerosController):
The :id attribute is by default a auto-increment attribute of datatype integer which sets its value under the hood whenever a new instance of the model is created. There are several ways to override the its behavior or setting its value explicitly, but considering that you are fairly new to the technology I don't recommend those for you. Instead I recommend a simpler solution of using another attribute to store hero["id"]
Steps:
1) Generate a migration to create a new column(say custom_hero_id) in the heroes table
rails g migration add_custom_hero_id_to_heroes custom_hero_id:integer
and do rake db:migrate
2) Change
<%= link_to(image_tag('fave.png', class: "fave_img"), new_hero_path) %>
to
<%= link_to(image_tag('fave.png', class: "fave_img"), heroes_path(custom_hero_id: hero["id"]), method: :post) %>
3) Finally change your create action to below
def create
#hero= Hero.create(custom_hero_id: params[:custom_hero_id])
redirect_to #hero
end
Update:
Due to unknown reason, custom_hero_id isn't saving to the DB. Probably due to forbidden attributes error. Try changing it to
def create
#hero = Hero.new(hero_params)
if #hero.save
redirect_to #hero
end
end
private
def hero_params
params.permit(:custom_hero_id)
end
Do you want to store the hero id or it's name ?
I would advise to create a method in your heroe model. Something like
// heroe.rb
def save_api_heroes_to_db(response)
response.each do |hero|
unless hero[:localized_name].exists?
hero.create(id: hero[:id], name: hero[:localized_name], image: hero[:img])
end
end
end
This method will save the heroe id, name and image in your database (unless it already exists).
You just have to call it in your index method, in your heroe controller.
Hope that helps.

Rails action being called multiple times per request

I have a controller action that's being called three times per browser request. Any ideas? config/routes.rb and application_controller.rb are totally straightforward.
Code below,
config/routes.rb
Rails.application.routes.draw do
root 'tiles#index'
+
controllers/tiles_controller.rb
class TilesController < ApplicationController
def index
puts "this line prints three times in the console per request"
end
+
tiles/index.html.erb
<% if notice %>
<p id="notice"><%= notice %></p>
<% end %>
<div id="tiles">
<%= render "tile", tile: { type: "sam", id: "0" } %>
<%= render "tile", tile: { type: "inputs", id: "1" } %>
<%= render collection: #tiles, partial: "tile" %>
<%= render "tile", tile: { type: "social", id: "1000" } %>
</div>
+
This is the console log:
log/development.log
Started GET "/" for 127.0.0.1 at 2017-08-31 16:56:28 -0400
Processing by TilesController#index as HTML
Started GET "/" for 127.0.0.1 at 2017-08-31 16:56:28 -0400
Processing by TilesController#index as HTML
[1m[36mProject Load (0.5ms)[0m [1m[34mSELECT "projects".* FROM "projects" ORDER BY "projects"."launch_date" ASC LIMIT $1[0m [["LIMIT", 10]]
[1m[36mProject Load (9.1ms)[0m [1m[34mSELECT "projects".* FROM "projects" ORDER BY "projects"."launch_date" ASC LIMIT $1[0m [["LIMIT", 10]]
Rendering tiles/index.html.erb within layouts/application
Rendered tiles/_tile_sam.html.erb (0.3ms)
Rendered tiles/_tile.html.erb (8.0ms)
Rendering tiles/index.html.erb within layouts/application
Rendered tiles/_tile_sam.html.erb (0.0ms)
Rendered tiles/_tile.html.erb (0.9ms)
Rendered tiles/_tile_instagram.html.erb (12.6ms)
...
Rendered tiles/_tile_twitter.html.erb (0.5ms)
Rendered collection of tiles/_tile.html.erb [48 times] (125.9ms)
Rendered tiles/_tile_project.html.erb (0.1ms)
Rendered tiles/_tile_social.html.erb (0.6ms)
Rendered tiles/_tile.html.erb (2.7ms)
Rendered tiles/index.html.erb within layouts/application (166.1ms)
Rendered tiles/_tile_twitter.html.erb (0.6ms)
...
Rendered collection of tiles/_tile.html.erb [48 times] (158.5ms)
Rendered tiles/_tile_social.html.erb (0.1ms)
Rendered tiles/_tile.html.erb (1.0ms)
Rendered tiles/index.html.erb within layouts/application (165.3ms)
Completed 200 OK in 1310ms (Views: 217.1ms | ActiveRecord: 9.1ms)
Completed 200 OK in 1325ms (Views: 204.5ms | ActiveRecord: 0.5ms)
Help!
WOW
Finally figured this one out by removing code related to this action/view line by line. Basically, I was generating a few img tags with empty src fields. Apparently this causes many modern browsers to load a website several times, possibly in an attempt to find missing images or assuming the root URL is the image itself?
Found the behavior cited here:
https://forums.asp.net/t/1804472.aspx?Bizzare+safari+thing+two+page+loads+for+each+page+
page loads twice in Google chrome

Multiple Users views for signup in Ruby on Rails

I want to create two different signup pages. So from my home view I created these buttons:
<% if not logged_in? %>
<%= link_to "I'm a Hero", signup_path, class: "btn btn-lg btn-primary" %>
<%= link_to "I'm a villain", villain_path, class: "btn btn-lg btn-primary" %>
<% end %>
Now the route obviously looks like this for the "I'm a Hero" button:
get 'signup' => 'users#new'
I can render a nice signup form in views -> user -> new.html.erb. I was thinking that I can do the same for my "I'm a villain" button.
First I wanted to create a new file views -> user -> villain.html.erb. Then I wanted to create a route like this:
get 'villain' => 'users#villain'
If I now click on my "I'm a villain" button, basically nothing happens. And as for localhost:3000/villain, I get redirected to localhost:3000.
What did I miss?
This is the server log when clicking on "Im a villain"
Started GET "/villain" for 130.75.71.234 at 2017-03-11 14:07:00 +0000
Cannot render console from 130.75.71.234! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
Processing by UsersController#villain as HTML
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" IS NULL LIMIT 1
Redirected to https://ruby-project.c9users.io/
Completed 302 Found in 601ms (ActiveRecord: 1.5ms)
Started GET "/" for 130.75.71.234 at 2017-03-11 14:07:01 +0000
Cannot render console from 130.75.71.234! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
Processing by StaticPagesController#home as HTML
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" IS NULL LIMIT 1
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" IS NULL LIMIT 1
Rendered static_pages/home.html.erb within layouts/application (4.6ms)
Rendered layouts/_shim.html.erb (0.5ms)
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" IS NULL LIMIT 1
Rendered layouts/_header.html.erb (2.0ms)
Rendered layouts/_footer.html.erb (0.8ms)
Completed 200 OK in 386ms (Views: 381.7ms | ActiveRecord: 0.5ms)
You need to define the "villain" action in the controller. You probably have the "new" action already defined because you created it through the generator. That is probably why the "new" action does work and not the "villain" one.

Adding items to a cart redirecting wrong

I've been following this Railscast on implementing Active Merchant in a new test app and it was going well, but now that I'm trying to add what I made to my main app its breaking.
When clicking 'add to cart' on my test app, it redirects to the current cart and lists the item as expected.
On my main app clicking the add to cart link redirects to:
http://mainapp.dev/line_items?product_id=1
The line_items controller looks like this:
class LineItemsController < ApplicationController
def create
#product = Product.find(params[:product_id])
#line_item = LineItem.create!(:cart => current_cart, :product => #product, :quantity => 1, :unit_price => #product.price)
flash[:notice] = "Added #{#product.name} to cart."
redirect_to current_cart_url
end
end
The add to cart link looks like this:
<%= link_to "Add to Cart", line_items_path(:product_id => product), :method => :post, :class => "product_actions" %>
edit - logs
Test version on adding an item (working):
Started POST "/line_items?product_id=5" for 127.0.0.1 at 2011-09-01 07:33:27 +0100
Processing by LineItemsController#create as HTML
Parameters: {"authenticity_token"=>"li7gkjksc9MENevuGz7emDwnbB6HrvPAE3CY=", "product_id"=>"5"}
[1m[35mProduct Load (0.4ms)[0m SELECT `products`.* FROM `products` WHERE `products`.`id` = 5 LIMIT 1
[1m[36m (33.1ms)[0m [1mBEGIN[0m
[1m[35mSQL (179.4ms)[0m INSERT INTO `carts` (`created_at`, `purchased_at`, `updated_at`) VALUES ('2011-09-01 06:33:28', NULL, '2011-09-01 06:33:28')
[1m[36m (48.3ms)[0m [1mCOMMIT[0m
[1m[35m (0.2ms)[0m BEGIN
[1m[36mSQL (0.2ms)[0m [1mINSERT INTO `line_items` (`cart_id`, `created_at`, `product_id`, `quantity`, `unit_price`, `updated_at`) VALUES (29, '2011-09-01 06:33:29', 5, 1, 250, '2011-09-01 06:33:29')[0m
[1m[35m (0.5ms)[0m COMMIT
Redirected to http://sell.dev/cart
Completed 302 Found in 1265ms
Started GET "/cart" for 127.0.0.1 at 2011-09-01 07:33:29 +0100
Processing by CartsController#show as HTML
[1m[36mCart Load (0.2ms)[0m [1mSELECT `carts`.* FROM `carts` WHERE `carts`.`id` = 29 LIMIT 1[0m
[1m[35mLineItem Load (0.3ms)[0m SELECT `line_items`.* FROM `line_items` WHERE `line_items`.`cart_id` = 29
[1m[36mProduct Load (0.5ms)[0m [1mSELECT `products`.* FROM `products` WHERE `products`.`id` = 5 LIMIT 1[0m
Rendered carts/show.html.erb within layouts/application (202.1ms)
Rendered layouts/_header.html.erb (0.8ms)
Rendered layouts/_footer.html.erb (0.7ms)
Completed 200 OK in 368ms (Views: 284.2ms | ActiveRecord: 79.5ms)
The main app version:
Started GET "/line_items?product_id=1" for 127.0.0.1 at 2011-09-01 07:34:59 +0100
Processing by LineItemsController#index as HTML
Parameters: {"product_id"=>"1"}
Rendered line_items/index.html.erb within layouts/application (0.3ms)
Rendered layouts/_header.html.erb (1.3ms)
Rendered layouts/_footer.html.erb (178.4ms)
Completed 200 OK in 218ms (Views: 182.3ms | ActiveRecord: 35.5ms)
I can't figure out why it's wanting to redirect to the line items index and not create, the code is the same.
edit - routes
get "cart" => "carts#show", :as => "current_cart"
resources :orders
resources :line_items
resources :carts
resources :products
resources :order_transactions
edit - taken from my application controller
def current_user
#current_user ||= User.find(session[:user_id]) if session[:user_id]
end
def current_cart
if session[:cart_id]
#current_cart ||= Cart.find(session[:cart_id])
session[:cart_id] = nil if #current_cart.purchased_at
end
if session[:cart_id].nil?
#current_cart = Cart.create!
session[:cart_id] = #current_cart.id
end
#current_cart
end
Thanks for any help its much appreciated!
If you add an item to your cart by clicking on the link "Add to cart" then you will need to call the create action in the LineItemsController controller as you have it now.
The last line of that method is
redirect_to current_cart_url
So you are indeed redirecting to the current_cart as you want but you are saying you are not redirecting to the current cart which is nonsense really.
Perhaps you have not yet set up the current_cart_url path or views or something?
I'm am not clear on what your actual problem is
Started GET "/line_items?product_id=1" for 127.0.0.1 at 2011-09-01 07:34:59 +0100
Processing by LineItemsController#index as HTML
Parameters: {"product_id"=>"1"}
Rendered line_items/index.html.erb within layouts/application (0.3ms)
Rendered layouts/_header.html.erb (1.3ms)
Rendered layouts/_footer.html.erb (178.4ms)
Completed 200 OK in 218ms (Views: 182.3ms | ActiveRecord: 35.5ms)
There MUST be something happening after this! ~What is it?
edit - solution
Sorry, I totally missed the obvious.
<%= link_to "Add to Cart", line_items_path(:product_id => product), :method => :post, :class => "product_actions" %>
is issuing a get request NOT a post request as indicated by your log file Started GET "/cart" for 127.0.0.1 at 2011-09-01 07:33:29 +0100
You are adding an item to the cart which means you are changing state on the server which means you should be using a POST request NOT a get (link) request and therefore you should use a form (button_to will give you that form). Unless you want loads of bot's spiders;/crawlers etc... adding stuff to your cart you should use
<%= button_to 'Add to Cart', line_items_path(:product_id => product) %>

Resources