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.
Related
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.
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.
So, I added the edit function to my payments controller, like this:
def edit
#payment = Payment.edit
if #payment.save
redirect_to showCompany_path, notice: 'Successfully edited!'
else
render :edit
end
end
I have a corresponding edit.html.haml view in my payments/view.
This is my routes rb:
resources :companies do
put :edit, :on => :collection
resources :payments do
put :edit, :on => :collection
end
end
And I want to have a link to this payments edit in my other view, which I defined like this:
<%= link_to 'Edit Payment Info', edit_company_payment_path(company), {:style=>'color:black; display:inline;', :class=>"btn btn-primary" } %>
I think I have done everything I should, but still I get this error from the title. Please help.
In order to generate a url to companies/:company_id/payments/:payment_id, Rails needs to know th e payment as well.
In other words, you are missing the payment param:
edit_company_payment_path(company, payment)
From your error, :company_id is an object not an integer. Try this,
edit_company_payment_path({:company_id => company.id, :payment_id => #payment.id})
I'm getting the following error on a page that contains a link to credit/edit an object:
Routing Error
No route matches {:controller=>"connections", :action=>"edit", :id=>nil}
My app has user profile pages (#show action in users_controller.rb) with a link to create or edit an existing "connection" (a relationship between users like Facebook or LinkedIn). If the connection does not exist, the link will send the user to create a new connection. If the connection already exists, the link will send the user to edit the existing connection. My create functionality works fine. However, once the connection has been created, visiting the user page throws the routing error. It clearly does not like my link_to for the edit action.
Here is the link_to on the user page:
<% unless current_user == #user %>
<% if #contact.present? %>
<%= #user.first_name %> is your <%= #connection.description %> (<%= link_to "edit contact", { :controller => 'connections', :action => 'edit', :id => #connection.id} %> )
<% else %>
How do you know <%= #user.first_name %>? (<%= link_to "edit contact", { :controller => 'connections', :action => 'create', :user_id => #user.id }, :method => 'post' %> )
<% end %>
The error also specifically states that :id is set to nil (null). The problem must be here. How can I my app to refer to the correct connection? My instance variable should have done the trick.
Here's the connection controller:
class ConnectionsController < ApplicationController
def index
end
def update
#connection = current_user.connections.find(params[:id])
if #connection.update_attributes(params[:connection])
flash[:notice] = "Contact relationship updated"
render 'activities'
end
end
def edit
#connection = current_user.connections.find(params[:id])
end
def create
##user = User.find(params[:user_id])
#connection = current_user.connections.build(params[:connection])
#user = User.find(params[:user_id])
if #connection.save
flash[:success] = "Contact relationship saved!"
else
render #user
end
end
end
And here's the User controller show action (where the link_to exists):
def show
#user = User.find(params[:id])
#connection = current_user.connections.build(:otheruser_id => #user)
#contact = current_user.connections.where(user_id: current_user, otheruser_id: #user)
end
routes.rb:
authenticated :user do
root :to => 'activities#index'
end
root :to => "home#index"
devise_for :users, :controllers => { :registrations => "registrations" }
resources :users do
member do
get :following, :followers, :posts, :comments, :activities, :works, :contributions, :connections
end
end
resources :works do
resources :comments
end
resources :relationships, only: [:create, :destroy]
resources :posts
resources :activities
resources :reposts
resources :comments do
member do
put :toggle_is_contribution
end
end
resources :explore
resources :connections
Any ideas on how to fix the link_to? Thanks!
EDIT 1: relevant rake routes:
connections GET /connections(.:format) connections#index
POST /connections(.:format) connections#create
new_connection GET /connections/new(.:format) connections#new
edit_connection GET /connections/:id/edit(.:format) connections#edit
connection GET /connections/:id(.:format) connections#show
PUT /connections/:id(.:format) connections#update
DELETE /connections/:id(.:format) connections#destroy
Your problem is in:
#connection = current_user.connections.build(:otheruser_id => #user)
That instantiates a connection object and assigns it to #connection. This object hasn't been saved, therefore it doesn't have an id. Conceptually it's wrong too, how can you edit something that doesn't exist yet? If you want to send the user to create a new connection, Connections#new is what you're after.
I have the following destroy method in my Tracks controller:
def destroy
if params[:product_id].present?
#product = Product.find(params[:product_id])
#track = #product.tracks.find(params[:id])
#track.destroy
redirect_to product_path(#product)
elsif params[:release_id].present?
#release = Release.find(params[:release_id])
#track = #release.tracks.find(params[:id])
#track.destroy
redirect_to release_path(#release)
end
end
I can destroy a Release Track using:
<%= link_to 'Destroy', release_track_path(#release,track), :confirm => 'Are you sure?', :method => :delete %>
But I get a routing error " No route matches [POST] "/products/74/tracks/43" " when I try to destroy Product Track:
<%= link_to 'Destroy', product_track_path(#product,track), :confirm => 'Are you sure?', :method => :destroy %>
I've taken a look at my Routes file and think it's probably an issue there, but having tried a few things i'm stumped! Can anyone help? This is driving me crazy. I'm using the same if els on my create method and it works fine for both Release Track and Product Track.
Here's my routes.rb (I suspect this is a big mess!)
Dashboard::Application.routes.draw do
get "home/index"
root :to => "home#index"
get "tracks/new"
get "tracks/create"
get "tracks/update"
get "tracks/edit"
get "tracks/destroy"
get "tracks/show"
get "tracks/index"
get "help/index"
resources :helps
resources :roles
resources :labels
devise_for :users
resources :users
resources :releases do
resources :artists
resources :tracks
resources :products do
resources :tracks
resources :itunes_data
end
end
resources :itunes_data
resources :tracks do
collection { post :sort }
end
resources :products do
resources :tracks
collection do
get 'schedulecsv'
get 'schedule'
get 'new_releases'
get 'active_lines'
get 'deleted_lines'
get 'gemsetup'
get 'amazonsetup'
get 'search'
end
end
resources :artists
end
You seem to have mixed up :delete and :destroy and the second line. :method expects an HTTP verb, so it should be :delete.
In order to manage your controllers in a much more maintainable way, you should really checkout the ressource_controller. It hides all the standard stuff away and lets you concentrate on the stuff you want to customize.