I have an index of all items from database listed in my view. I want to create a destroy button to destroy the current record in the database using Ruby on Rails 4. Here is my code:
<div>
<h1>All Incomes</h1>
<% #user_incomes.each do |income| %>
<div>
<p><%= income.title %></p>
<p><%= income.description %></p>
<p><%= number_to_currency(income.amount) %>
<p><%= income.user_id %></p>
<%= button_to "Destroy", {action: "destroy", id: income.id}, method: :destroy, data: { confirm: "Are you sure?" } %>
</div>
<br />
<%end%>
</div>
My Income Controller:
class IncomesController < ApplicationController
before_action :authorize, only: [:new, :index, :show, :create]
def index
#incomes = Income.all #income refers to the db model income
#user_incomes = Income.all.where(:user_id=>current_user.id)
end
def show
#income = Income.find(params[:id])
end
def new
#income = Income.new
end
def create
#income = Income.create(income_params)
end
def destroy
#income.destroy
end
## Strong Parameters alias Rails 3's attr_accessible
private
def income_params
params.require(:income).permit(:title, :user_id, :description, :type, :amount)
end
def declare_income
#income = Income.find(params[:id])
end
end
Here is my route file:
Rails.application.routes.draw do
get 'member_content/new'
#get 'sessions/new' ## this is generated with rails g controller sessions new
resources :sessions
resources :incomes
resources :users
resources :abl_deductions
get 'main/index'
# Example of regular route:
# get 'products/:id' => 'catalog#view'
get 'signup', to: 'users#new', as: 'signup'
get 'login', to: 'sessions#new', as: 'login'
get 'logout', to: 'sessions#destroy', as: 'logout'
get 'content', to: 'member_content#new', as: 'content'
get 'add_income', to: 'incomes#new', as: 'add_income'
get 'add_deduction', to: 'abl_deductions#new', as: 'add_deduction'
get 'deductions', to: 'abl_deductions#index', as: 'deductions'
end
I am newb to rails, would it be easier for this action if I had use a scaffold with rails generate scaffold?
Let's assume your controller is called IncomesController. When you run bin/rails routes in your app folder, you should also see something like:
DELETE /incomes/:id(.:format) incomes#destroy
To achieve this, you need to have proper routes.rb records. Easy thing to achieve standard CRUD operations over incomes is to have resources :incomes in routes.rb
You also need to have destroy method in IncomesController to perform actual destroy.
Related
I'm kind of new to rails. I have a model called follows that has to values (requestor and following). I am having trouble creating a button that destroys a select model with two values
<dt>User ID:</dt>
<dd><%= #user.id %></dd>
<dt>User email:</dt>
<dd><%= #user.email %></dd>
<% if Follow.where(:requestor => current_user.id, :following =>#user.id).present? %>
<%= button_to 'Unfollow', follow_url, method: :delete, class: "text-danger", data: { confirm: 'Are you sure?' } %>
<% else %>
<%= button_to "Follow", {:controller => 'follows', :action => 'create', :requestor => current_user.id, :following => #user.id}, {:method => :post} %>
<% end %>
The Follow button below in the else statement works, but I cannot figure out how to get the destroy button to work. I'm executing these buttons on the User show page instead of on the follow index.
def destroy
#follow.destroy
respond_to do |format|
format.html { redirect_to follows_url, notice: 'Follow was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_follow
#follow = Follow.find(params[:id])
end
# Only allow a list of trusted parameters through.
def follow_params
params.permit(:requestor, :following)
end
def require_permission
if Follow.find(params[:id]).user != current_user
redirect_to goals_url, flash: { error: "You do not have permission to do that."}
end
end
end
I keep getting couldn't find Follow with 'id' error. It deletes sometimes, but the majority of the time I get this error.
Routes. uses general format
require 'sidekiq/web'
Rails.application.routes.draw do
resources :follows
resources :accounts
resources :goals
resources :retirements
get '/users', to: 'users#index'
get '/user/:id', to: 'users#show', as: 'user'
resources :calculate_debts
get '/privacy', to: 'home#privacy'
get '/terms', to: 'home#terms'
authenticate :user, lambda { |u| u.admin? } do
mount Sidekiq::Web => '/sidekiq'
end
resources :notifications, only: [:index]
resources :announcements, only: [:index]
devise_for :users, controllers: { omniauth_callbacks: "users/omniauth_callbacks" }
root to: 'home#index'
# For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
end
It deletes sometimes, but the majority of the time I get this error
If it works "sometimes" then my guess would be that you are not re-rendering your page after your delete, and you might end up clicking the "Unfollow" button twice on the same record, which will raise a RecordNotFound error like you showed.
Your html redirect seems fine but make sure you are also refreshing the page when the request is in json format.
I have previewed all questions with similar topics and none of those solutions help me. I am attempting to create a twitter like feed that will display posts of a certain category in rails.
This is my industries controller:
class IndustriesController < ApplicationController
def index
#wads = Wad.order('created_at DESC')
end
def music
#music_wads = Wad.where(category: "Music").paginate(page: params[:page], per_page: 20)
#wad = #music_wads.pluck(:id)
end
end
This is part of my posts controller:
class WadsController < ApplicationController
before_action :find_wad, only: [:show, :edit, :update, :destroy]
def index
#wads = Wad.all
end
def show
#wad = Wad.find(params[:id])
end
def new
#wad = Wad.new
end
def create
#wad = current_user.wads.build(wad_params)
if #wad.save
redirect_to #wad
else
flash[:error] = 'Error try again'
render 'new'
end
end
end
And this is my show view for my industries controller:
<h1>Music Wads</h1>
<%= will_paginate #music_wads %>
<% #music_wads.each do |music_wad| %>
<%= link_to 'wads/:id' do %>
<div class="flex-rectangle">
<%= music_wad.user.name %>
<%= music_wad.short_form %>
<% end %>
</div>
<%= will_paginate #music_wads %>
<% end %>
Here is my routes file:
Rails.application.routes.draw do
root 'static_pages#home'
get '/help', to: 'static_pages#help'
get '/about', to: 'static_pages#about'
get '/contact', to: 'static_pages#contact'
get '/signup', to: 'users#new'
get '/login', to: 'sessions#new'
post '/login', to: 'sessions#create'
delete '/logout', to: 'sessions#destroy'
get '/industries', to: 'industries#index'
get '/music', to: 'industries#music'
get '/tech', to: 'industries#tech'
resources :users
resources :account_activations, only: [:edit]
resources :password_resets, only: [:new, :create, :edit, :update]
resources :wads
end
I am attempting to make it so that clicking on a post among the lists of post carries you to page of that post (/wads/id). I've been baffled all day and am now at my wits end. I am aware I am a noob and this is a nooby question but any help would gladly be appreciated.
Thanks
resources :wads will create some routes that you can use.
Running rails routes (on rails 5) or rake routes (on rails 4 and lower) in the console will give you the list of your routes.
Under the prefix column you could find the correct route name you should use and under the URI Pattern you could see the actual address it links to.
You asked for wads/:id so the link should be <%= link_to wad_path(wad_music) do %> (the prefix is wad_path and you need to give it the object which holds the id - or an id...)
Since you want to link to a singular action - meaning that the action will get and id of an object - and get it (gets a single object!) the link prefix will be in singular form as well: wad_path and not wads_path
(wads_path will link to the index action in the controller and doesn't need to get any object or id)
I have installed devise to my rails app and was originally able to sign out using <%= link_to('Logout', destroy_user_session_path) %>
However, somewhere along the line after adding more code and a few gems (paperclip, act_as_votable, social_share_button) I was not able to use the same link. When I click the link_to I receive the error
No route matches [GET] "/users/sign_out"
I have also tried adding config.sign_out_via = :get to my devise.rb file but still got the same error. What have I done wrong?
routes.rb
Rails.application.routes.draw do
devise_for :users, controllers: { registrations: 'users/registrations', sessions: 'users/sessions' }
root to:'ideas#index'
get "/page", to: 'pages#index'
resources :ideas, only: [:index, :show, :create, :destroy, :new] do
member do
put "like", to: "ideas#upvote"
put "dislike", to: "ideas#downvote"
end
end
resources :comments, only: [:create]
end
sessions controller
class Users::SessionsController < Devise::SessionsController
def new
super
end
def create
super
end
def destroy
super
end
end
I believe <%= link_to 'Logout', destroy_user_session_path, method: :delete %> is what you're looking for
I've managed to make an app that works only to sign up and to log in. Currently, I'm allowing users by mail account activation (following this tutorial: https://www.railstutorial.org/book/account_activation_password_reset and by 'rails generate controller AccountActivations --no-test-framework') but I want admin to be able to activate or deactivate users. In my users model, I managed to define two methods:
def activate_account!
update_attribute :is_active, true
end
def deactivate_account!
update_attribute :is_active, false
end
And on my users partial view, I managed to
<% if current_user.admin? && !current_user?(user) %>
<%= button_to "Deactivate", user, data: { confirm: "Are you sure?" } %>
<% end %>
My routes look like this:
get 'password_resets/new'
get 'password_resets/edit'
root 'static_pages#home'
get 'help' = 'static_pages#help'
get 'about' = 'static_pages#about'
get 'contact' = 'static_pages#contact'
get 'signup' = 'users#new'
get 'login' = 'sessions#new'
post 'login' = 'sessions#create'
delete 'logout' = 'sessions#destroy'
resources :users
resources :account_activations, only: [:edit]
resources :password_resets, only: [:new, :create, :edit, :update]
The problem is that I don't know how to proceed. I don't want to use either Devise or CanCan because, as a beginner, I want to know how to do it manually. Please help me in implementing activation and deactivation of users from application (Admin can only this).
Here is my app.
Ok, first read chapters 9 and 10 of Hartl's Rails Tutorial.
Add and admin flag to users
rails g migration add_admin_to_users admin:boolean
This will give you .admin? "for free" as Active Record will generate this method.
And I'd write your button like this
<% if current_user.admin? && #user != current_user %> <%=link_to "deactivate", deactivate_path(user_id: #user), method: :post, data: { confirm: "Are you sure?" } %> <% end %>
Then in your controller:
def deactivate
user = User.find(params[:user_id])
if current_user.admin?
user.deactivate_account!
redirect_to users_path
else
redirect_to :back
end
end
And in your routes, something like:
post "/deactivate", to: "users#deactivate"
Anyway, I'm giving you a rough guide, but do read Hartl's tutorial, as your use case is almost covered there.
Good luck!
According to Rails convention:
PUT is used for updating an existing resource
POST is used for creating a new resource
So, you should make this a PUT request rather than POST as it is updating the user record.
You should define your route like this:
put 'deactivate/:id(.:format)', :to => 'users#deactivate', :as => :deactivate_user
And, in your user partial:
<%=link_to "Deactivate", deactivate_user_path(user), method: :put, data: { confirm: "You sure?" }%>
Everything should work now with your existing code.
I have the following loop in my view
<% #posts.each do |post| %>
<%= link_to post do %>
Some html
<% end %>
<% end %>
The above code will generate link as localhost:3000/posts/sdfsdf-sdfsdf
But I would like to have the link as localhost:3000/sdfsdf-sdfsdf
Here is my route
resources :posts, except: [:show]
scope '/' do
match ':id', to: 'posts#show', via: :get
end
You could do this:
#config/routes.rb
resources :posts, path: "" #-> domain.com/this-path-goes-to-posts-show
--
Also, make sure you put this at the bottom of your routes; as it will override any preceding routes. For example, domain.com/users will redirect to the posts path unless the posts path is defined at the bottom of the routes.rb file
--
friendly_id
In order to achieve a slug-based routing system (which works), you'll be best suited to using friendly_id. This allows the .find method to look up slug as well as id for extended models:
#app/models/post.rb
Class Post < ActiveRecord::Base
extend FriendlyID
friendly_id :title, use: [:slugged, :finders]
end
This will allow you to use the following in your controller:
#app/controllers/posts_controller.rb
Class PostsController < ApplicationController
def show
#post = Post.find params[:id] #-> this can be either ID or slug
end
end
you need to tell routes what the name of the path gonna be.
in routes.rb you can do something like:
get '/:id', constraints: { the_id: /[a-z0-9]{6}\-[a-z0-9]{6}/ }, to: 'posts#show', as: :custom_name
after that when you run 'rake routes' you will see:
Prefix Verb URI Pattern Controller#Action
custom_name GET /:id(.:format) post#show {:id=>/[a-z0-9]{6}\-[a-z0-9]{6}/}
Now that you have the prefix verb, you can use it to generate the link:
<%= link_to 'Show', custom_name_path( post.id ) do %>
Some html
<% end %>