writing method for destroy and creating link to destroy the object - ruby-on-rails

I am building presentation builder, and I don't know how to destroy the chosen presentation presented in the list when I click on the button Remove.
My controllers looks like that:
def create
if logged_in?
presentation = current_user.presentations.create data: params.to_yaml
redirect_to edit_presentation_path(presentation)
end
end
def edit
render action: :new
end
# def destroy
# current_presentation.destroy
# end
def show
render action: :new
end
def list
#presentations = current_user.presentations
end
def update
current_presentation.update_attributes(data: params.to_yaml)
end
def home
if logged_in?
#presentations = current_user.presentations
end
end
My list of created presentations looks like that:
<% #presentations.each do |p| %>
<a > <%= p.id %>
Show
<a class="action"> Remove </a>
</a>
<% end %>
My goal is: to write correct destroy method and create a link Remove that executes this method for a particular presentation.

<%= link_to "Delete", p, method: :delete %>
Something like that should do it.
More here http://api.rubyonrails.org/classes/ActionView/Helpers/UrlHelper.html

<%= link_to "Delete", your_destroy_path(p), method: :delete %>

Related

how to pass parameters in page

I have this page (called "page"). I tried calling those pages by id with <%= link_to page.title, page_path(page.id) %>which is working, but I want to call those pages using params, I don't want their link to be direct like http://localhost:3000/pages/6 but I want that id 6 to be passed through a params, so I'll have a link like http://localhost:3000/pages?category_id=1.
Here's my pages controller
class PagesController < ApplicationController
def show
#pages = Page.find(params[:id])
end
def all
#category = Category.find_by(id: params[:category_id])
#pages = #category.pages
end
def index
if params[:id].present?
show
else
#Code of index action
#pages = Page.all
end
end
end
and my show.html.erb
<%= #page.title %>
<%= #page.body %>
and then the link to this page
<% #pages.each do |page| %>
<h4>
<b>
<%= link_to page.title, page_path(page.id)%>
</b>
</h4>
<% end %>
There may be many ways to do this and my way is as follow.
Change index action of pages_controller as follow
def index
if params[:id].present?
show
else
#Code of index action
#pages = Page.all
end
end
Change show action of pages_controller as follow
def show
#page = Page.find(params[:id])
end
And pass page id in link_to function as follow
<% #pages.each do |page| %>
<h4><b><%= link_to page.title, pages_path(:id => page.id)%> </b></h4>
#<h4><b>Page Title</b></h4>
<% end %>
I hope this will solve your problem.

Rails Error: ActiveRecord::RecordNotFound

I am working on my first Rails project and I am running into a persistent issue. I suspect it has something to do with the routing, however, I can't seem to find anything about it online.
I assume it a rather simple fix, so please take a look and let me know if you can help.
TL;DR
What I was trying to achieve
Account detail Cards display Name, Phone number, and a note.
A delete and edit button would allow users to delete or edit.
What is happening:
Edit and Delete buttons return a weird param.
see image
Image of error, Showing Rails getting a different ID
Controller
class AccountdetailsController < ApplicationController
def index
#accountdetail = Accountdetail.all
end
#I can't find the ID to show the relevent card.
def show
#accountdetail = Accountdetail.find(params[:id])
if #accountdetail.nil?
redirect_to accountdetail_path
end
end
def new
#accountdetail = Accountdetail.new
end
def edit
#accountdetail = Accountdetail.find(params[:id])
end
def create
#accountdetail = Accountdetail.new(accountdetail_params)
if #accountdetail.save
redirect_to #accountdetail
else
render 'new'
end
end
#it affects this
def update
#accountdetail = Accountdetail.find(params[:id])
if #accountdetail.update(accountdetail_params)
redirect_to accountdetail
else
render 'edit'
end
end
#and this
def destroy
#accountdetail = Accountdetail.find(params[:id])
#accountdetail.destroy
redirect_to accountdetail_path
end
private def accountdetail_params
params.require(:accountdetail).permit(:first_name, :last_name, :phone, :notes, :id)
end
end
Index.HTML.ERB
<div class="ui card">
<div class="content">
<a class="header"><%= account.first_name %> <%= account.last_name %> </a>
<div class="meta">
<span class="date"><%= account.phone %></span>
<strong><p><%= account.notes %></p></strong> <br>
<%= link_to "edit", edit_accountdetail_path(#accountdetail) %>
<%= link_to 'Inspect', accountdetail_path(#accountdetail) %>
</div>
</div>
</div>
<% end %>
Routes
Rails.application.routes.draw do
get 'welcome/index'
resources :articles do
resources :comments
end
resources :accountdetails
root 'welcome#index'
end
In you index.html.erb replace following
<%= link_to "edit", edit_accountdetail_path(#accountdetail) %>
<%= link_to 'Inspect', accountdetail_path(#accountdetail) %>
with
<%= link_to "edit", edit_accountdetail_path(account) %>
<%= link_to 'Inspect', accountdetail_path(account) %>
#accountdetail was providing you all the records of account, as it was firing select query in controller. But here we need only one instance, so account.
Hope this helps.

Rails 4 passing variables in the views or templates

I have an app that will allow the owner (but not public users) to upload photo album files and photos. When coding my views, I noticed something strange.In the do block in my albums/index.html.erb file, if I pass in the variable #album.id, I get a NoMethodError for NilClass.Yet, if I remove the "#", (or remove that variable entirely), it works fine.
But in my albums/show.html.erb file, in the link_to line of code for editing an album title, I need the "#album.id" to be passed (or the variable left out entirely) in order for it to work.
Why is that?
Here is my albums/index.html.erb file and code
<div class="admin_login"><%= link_to "Admin Login", new_album_path %></div>
<div class="home"><%= link_to "Home", root_path %></div>
<h1>Albums Gallery</h1>
<% #albums.each do |album| %>
<div>
<%= link_to album.name, album_path(album.id) %>
</div>
<% end %>
And here is my albums/show.html.erb file:
<h3><%= link_to #album.name %></h3>
<div class="album">
<%= link_to "Edit", edit_album_path(#album.id) %>
<%= link_to "Delete", #album, method: :delete, data:{confirm: "Are you sure you want to delete this album? All photos in it will be permanently deleted!"} %>
</div>
<br><%= link_to "Back", albums_path %>
For clarity, here is my albums controller code:
class AlbumsController < ApplicationController
def index
#albums = Album.all
end
def new
#album = Album.new
end
def create
#album = Album.new(album_params)
#album.save
redirect_to albums_path
end
def show
#album = Album.find(params[:id])
end
def edit
#album = Album.find(params[:id])
end
def update
#album = Album.find(params[:id])
if #album.update(album_params)
redirect_to album_path(#album.id)
else
render 'edit'
end
end
def destroy
#album = Album.find(params[:id])
#album.destroy
redirect_to albums_path
end
private
def album_params
params.require(:album).permit(:id, :name, :category)
end
end
In your index action, you're defining a series of albums as #albums. In your show action, you define just a single #album. These variables are accessible only in the action in which they are defined.
The reason that 'album' works in your index view is that the each block is defining a local 'album' variable within the block's scope.
<% #albums.each do |album| %>
<div>
<%= link_to album.name, album_path(album.id) %>
</div>
<% end %>
That |album| after the do block says "for this iteration, assign the current value to the variable album"
You need to setup instance variables in the controller. Make sure you set #albums in AlbumsController index action and #album in show action. The do block uses block variable, not instance, so there is no need for #.

deleting users in devise generated model

First of all I am new to rails. I used devise gem for user authentication. Now I want to provide admin a way to delete other users. id of the user is not passing to my destroy action. Here is my code
user_controller.rb
class UsersController < ApplicationController
def destroy
User.find(params[:id]).destroy
redirect_to dashboard_path
end
end
dashboard.html.erb
<% if current_user.admin == true %>
<% #users = User.all %>
<% #users.each do |user| %>
<%= user.email %>
| <%= link_to "delete", destroy_path, method: :delete, data: { confirm: "Are you sure"} %><br>
<% end %>
<% end %>
First of all, You shouldn't assign instance variables directly in your views. This is a Controller responsibility. So, in the above example, the right thing to do is something like this:
# users_controller.rb
class UsersController < ApplicationController
def dashboard
#users = User.all
end
def destroy
User.find(params[:id]).destroy
redirect_to dashboard_path
end
end
And your view should look something like this:
# dashboard.html.erb
<% if current_user.admin == true %>
<% #users.each do |user| %>
<%= user.email %>
| <%= link_to "delete", user, method: :delete, data: { confirm: "Are you sure"} %><br>
<% end %>
<% end %>
And last but not least =P make sure your routes.rb have something like this:
# routes.rb
delete "/users/:id" => "users#destroy", as: :user
Of course it's just an example based on your question, but it should work like a charm =P

Rails app gives "no method error" when it sees <% if current_user.admin? %>

I used this code in my "users" views and had no trouble: <% if current_user.admin? %>. But using it in a set of views associated with a different controller throws up the "No method Error."
Background: the app allows admins to create scavenger hunts. Admins should be able to delete hunts. I thought I knew how to configure everything, but apparently, I'm missing something. Here's my code:
controller.rb
class HuntsController < ApplicationController
def index
#title = "All Hunts"
#hunts = Hunt.order("name ASC")
end
def show
#hunt = Hunt.find(params[:id])
#title = #hunt.name
end
def new
#hunt = Hunt.new
#title = "New Hunt"
end
def create
#hunt = Hunt.new(params[:hunt])
if #hunt.save
flash[:success] = "Hunt created!"
redirect_to hunts
else
#title = "New Hunt"
render 'new'
end
end
def edit
#hunt = Hunt.find(params[:id])
#title = "Edit hunt"
end
def delete
Hunt.find(params[:id]).destroy
flash[:success] = "Hunt destroyed."
redirect_to index
end
end
Views/Index.html.erb
<h1>All Hunts</h1>
<ul>
<% #hunts.each do |hunt| %>
<%= render hunt %>
<% end %>
</ul>
<%= link_to( "Create New Hunt", '/hunts/new') %>
Views/_hunt.html.erb
<li>
<%= link_to hunt.name, hunt %>
<% if current_user.admin? %>
<%= link_to "delete", hunt, :method => :delete, :confirm => "You sure?",
:title => "Delete #{hunt.name}" %>
<% end %>
</li>
Error Message when trying to head to /hunts:
NoMethodError in Hunts#index
Showing ...../app/views/hunts/_hunt.html.erb where line #3 raised:
undefined method `admin?' for nil:NilClass
current_user is nil, and thus does not know how to respond to admin?. Either ensure that current_user is always a user instance, or check that it's not nil.
In Ruby 2.3+, one can use the “safe navigation” operator (&.):
if current_user&.admin?
In Ruby 2.2 and earlier, instead use boolean short-circuiting:
if current_user && current_user.admin?
Note that ActiveSupport has try, but that has different behavior which will potentially hide bugs. For similar behavior, use try! instead.
Getting "undefined method _____ for nil:NilClass" is a very common occurrence in Ruby, so get used to it happening often :).
You have to sign in the user in order to instantiate current_user. If you are using devise, use:
class HuntsController < ApplicationController
before_filter :authenticate_user!
def index
...
end
.......
end
in your controller. And make sure that .admin? method is defined in your User model.

Resources