Routing error when using Destroy in nested routes - ruby-on-rails

I have a strange BUG in a nested resources thing. I have a Seller/Car relationship where a Seller has_many Cars. Now I need to delete a Car from those that belong to a seller (the seller is authentication through Sessions#create and its id is stored in session[:seller_id]:
This is the Car Index View listing all cars that belong to this particular seller:
<%= #cars.each do |car| %>
<tr>
<td><%= car.brand %></tr></td>
<td><%= link_to 'Edit', edit_seller_car_path(session[:seller_id], car) %></td>
<td><%= link_to 'Destroy', seller_car_path(session[:seller_id], car) %></td>
</tr>
<% end %>
Standing on the Car index listing all cars belonging to the authenticated seller, the URL looks like localhost:3000/sellers/2/cars. This page displays the table listing cars with the edit and destroy buttons (edit works fine)
Here is the Cars#destroy:
#seller = Seller.find(params[:seller_id])
#car = #seller.cars.find(params[:id])
#car.destroy
flash[:notice] = "Deleted"
redirect_to seller_cars_url(session[:seller_id])
Here is the Cars#edit (it's working fine when editing):
#seller = Seller.find(params[:seller_id])
#car = #seller.cars.find(params[:id])
When I click on the destroy button, this BUG happens:
1) Strangely, the car is still deleted successfully.
2) I get routing error:
No route matches {:action => "edit", :controller => "cars", :seller_id=>nil, id=>#<Car id:23, brand:"Opel"...
Looks like the problem here arises in the Edit button in the index page. The car it's referring to is the first car in the table and the seller_id is nil here, meaning the seller_id is no longer held in session[:seller_id], which is the act of Sessions#destroy
3) I noticed that the Seller is logged out. As if the destroy in Car controller invokes the Destroy in Sessions controller that clears the session.
4) The URL seems to be the correct one for the Cars index: localhost:3000/sellers/2/cars, but I still see that routing error mentioned in 2.
I would appreciate if you please help guide me in this strange behavior. Thank you.

Related

Updating rails 6 params with a link_to

Hello I have a lists of invoices that belong to a business and also the business belongs to a user, I am trying to have a button (link to) on a table in which all the invoices are listed for the user to be able to update the status of the invoice.
Pretty much if the user hits the link it will change from paid: true to paid: false and viseversa.
here are the routes:
resources :businesses do
resources :invoices
end
Here is the section of the table in which the link is:
<% if invoice.paid %>
<td><%= link_to "Mark as Not Paid", business_invoice_path(current_user, invoice), method: 'put', data: {paid: false} %></td>
<% else %>
<td><%= link_to "Mark as Paid", business_invoice_path(current_user, invoice), method: 'put', data: {paid: true}%></td>
<% end %>
Note: The paid column is a boolean on the db
Since, the paid column is present on Invoice, it is much better if you handle it at the controller or model level instead of getting the value from the form.
Remove if else conditions and combine it as below:
<%
invoice_text = invoice.paid ? 'Mark as Not Paid' : 'Mark as Paid'
%>
<td><%= link_to invoice_text, business_invoice_path(invoice), method: :put %></td>
In the Business::InvoicesController you can write the logic in update like this:
Business::InvoicesController < ApplicationController
before_action :authenticate_user!
before_action :set_invoice
def update
# TODO: find the business using the invoice
# have a check in place to authorize the
# transaction (if invoice belongs a business which
# belongs the current_user or not, if not then raise Unauthorized error)
# if business does belongs to the current_user then proceed to next step
# invert the value of paid column based on existing value
#invoice.update(paid: !#invoice.paid)
end
private
def set_invoice
#invoice = Invoice.find(params[:id])
end
end
With logic above, you can forget about maintain/finding the value of paid column since you have an option to revert the value of paid to true and back to false. Also, that I assumed you are using Devise for authentication.

Devise Invitable destroying users

My app uses devise and devise_invitable to handle invitations. On my new invitations view I have a table that lists all users that have been invited. I want to add a column to delete each listed user. If I understand correctly, the route expects a format that should probably be something like remove_user_invitation_path(something) and also that it appears to be an invitation_token (an attribute of the User model). I just don't know how to insert it into the URL as a format. I'm also not sure if this will delete the user itself or the invitation (* I placed the) given that a user can accept or ignore an invitation, I worry that it will only work for users that have a pending invitation. Any input is appreciated!
$ rails routes
remove_user_invitation GET /users/invitation/remove(.:format) users/invitations#destroy
# users/invitations/new
<% #invited_users.each do |invited| %>
<tr>
<td><%= invited.email %></td>
<td><%= link_to "Delete", remove_user_invitation_path, method: :delete, data: { confirm: "Are you sure you want to delete this user?" } %></td>
<tr>
<% end %>
# GET /resource/invitation/remove?invitation_token=abcdef
def destroy
resource.destroy
set_flash_message :notice, :invitation_removed if is_flashing_format?
redirect_to after_sign_out_path_for(resource_name)
end
# What my variable contains
#invited_users = User.where.not(invitation_sent_at: nil)

Rails link_to pass :id from show to another controller action

I'm viewing 1 product in show.html.erb and there's a link below that says "View other products from this company". This link_to connects to another non-restful action in same controller which retrieves from DB other products of same company as was shown in show.html.erb.
Can link_to pass the :id of the current product in show to action it's rendering? I'm new to rails and please let me know if question is not making sense. I'm not sure if routes need to be defined as well. Thanks.
products_controller.rb
def show
#company_products = Product.by_company
end
show.html.erb
<%= link_to "View other products from this company", company_products_path(:anchor => "#{#company_products}") %>
routes.rb
get '/company_products_' => 'products#company_products'
I finally resolved it by passing the :id of object in show via link_to to a non-restful action.
I'm open to suggestions if entire #company_products in #show can be passed as it is because I'm first finding if there are any other products for that company and if there are, passing an id only in link_to and in controller#company again running a query to get same data of all products to display. so running same query twice is not DRY.
controller#show remains the same as originally posted.
routes.rb
resources :products do
get :company, on: :member
end
show.html.erb
<%= link_to "View other products from #{#company_name}", company_product_path(#product.company_id) %>
controller#company
def company
#products_of_company = Product.where(company_id: params[:id])
end
Now in company.html.erb, the list is just displayed.
You want to do something like this:
#company_products.each do |company|
link_to "View other products from this company", products_path(company)
end
routes:
resources :products

Rails Nil Method Issue

I've been borrowing some code from an old ruby on rails 3 app of mine for a new rails 4 app. The code works on the old site, but on the new one it doesn't.
Here's my routes.rb:
scope ':username' do
resources :recipes
end
get "/:username" => "recipes#index"
Here's my controller index:
def index
#user = User.find_by_username params[:username]
#recipes = Recipe.all
end
and my view:
<% #recipes.each do |recipe| %>
<tr>
<td><%= recipe.name %></td>
<td><%= link_to recipe.name, recipe_path(username: #user.username, id: recipe.id) %></td>
<td><%= link_to 'Edit', edit_recipe_path(recipe) %></td>
<td><%= link_to 'Destroy', recipe, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
but the error pops up:
undefined method `username' for nil:NilClass
but the current user username is set to test so its not nil, and the error shouldn't be popping up.
Thanks for all help!
When you have variables that could be potentially be nil, you should handle the case where they are nil, unless you explicitly wish for it to fail in these circumstances.
The dynamic find_by methods return nil when no records are found. Hence, as alfonso pointed out, you are getting a null value for #user.
In this particular instance, I would question how you are using the username param; if recipes are associated with recipes, then I would set up a has_many :recipes in my user model, and belongs_to :user in my recipe model.
Since the user is the 'parent' here, I would opt to create a recipes action in the UsersController. It seems more logical to me to put the recipes that belong to a user in the user's controller, and access the recipes as a collection from the user.
Alternatively, if you are trying to show recipes associated with a user, I would put the action in the RecipesController, and get the user that belongs to a recipe by using the #user method set up from the belongs_to relationship in the database.
In either case, you'll want to guarantee that the users and/or any recipes are defined before trying to render a page. You might want to display a 501 error or something similar if a user doesn't exist that's trying to be accessed, etc.
If you insist that there should always be a user for a recipe, then you should add that type of validation to the recipes model, so that adding a recipe without a user is disallowed:
validates :user, :presence => true
Sorry if I went a little off tangent.
get "/:username"
Here - :username is in position of id
#user = User.find_by_username params[:username]
Here you are trying to find it by params.
Link should look like this http://localhost:3000/user_name/user_name?username=user_name
to find some user, and it is obviously not what you want to achieve.
get "/:id" => "recipes#index"
#user = User.find(params[:id])

Creating a view that display all records that belongs_to an association

I'm trying to create a view that display all records that belongs to an association and not sure on how to go about this.
I've created an erb file in view/members/showmembers.html.erb, added 'showmembers' method in members_controller.rb but when I go to http://localhost:3000/members/showmembers it says 'Couldn't find Member with id=showmembers' and its pointing to the show method in the controller *'app/controllers/members_controller.rb:29:in `show'*.
def showmembers
#organization = Organization.find(1)
#shmembers = #organization.members.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #members }
end
end
showmembers.html.erb
<% #shmembers.each do |shmember| %>
<tr>
<td><%= shmember.id %></td>
<td><%= shmember.first_name %></td>
</tr>
<% end %>
Thanks.
the error indicates that Rails don't know which action to use to process this request : http://localhost:3000/members/showmembers.
and since this request is "GET", Rails chose the "show" action.
so the solution is simply edit your config/routes.rb, and add this route:
resources :members do
collection do
get :showmembers # add this line
end
end
Please paste this into your route file otherwise it map to show action that cause this error please define route first\
resources :members do
collection do
get :showmembers
end
end
And then in controller
hmembers = #organization.members
no need to this members = #organization.members.all
If you define association well....

Resources