Delete subscription with a form Rails 4 - ruby-on-rails

I'm trying to have subscribers unsubscribe via a delete form where they enter their email and then submit and then delete the subscription. Not sure why this isn't working. I've tried a number of things via my controller. Would love some suggestions or alternatives.
Currently getting this error
Couldn't find Subscription without an ID
Subscriptions controller
def destroy
#subscriptions = Subscription.all
#subscription = #subscriptions.find(params[:id])
if #subscription.email == params[:email]
#subscription.destroy
flash[:notice] = "You have been unsubscribed"
redirect_to root_path
else
end
end
Routes
Rails.application.routes.draw do
get 'password_resets/new'
get 'password_resets/edit'
get 'sessions/new'
get 'users/new'
resources :posts
root 'static_pages#new_home'
resources :subscriptions, only: [:new, :create, :edit, :update, :show, :destroy]
get '/home' => 'static_pages#home'
get 'subscriptions' => 'subscriptions#show'
delete 'subscriptions' => 'subscriptions#destroy'
get '/about' => 'static_pages#about'
get '/author' => 'static_pages#author'
get '/contact' => 'static_pages#contact'
get '/book' => 'static_pages#book'
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]
resources :posts do
resources :comments
end
end
Unsubscribe partial in subscriptions view
<%= form_for #subscription, method: :delete do |f| %>
<div class="row">
<h2>Unsubscribe</h2>
</div>
<div class="row newsletter">
<form method="post" action="#" class="contact-form">
<div class="row email-label">
<%= f.label :email, :class => 'label-email' %>
<%= f.email_field :email %>
</div>
<div class="row">
<%= f.submit 'Unsubscribe', :class => 'btn-full-subscribe' %>
</div>
</form>
</center
<% end %>
I've tried a number of things with no luck. Help would be appreciated. Thanks. Subscriptions are not related to User model.

This line #subscription = #subscriptions.find(params[:email]) is causing the issue.
Try #subscription = #subscriptions.find_by_email(params[:email]) or better yet, use the id #subscription = #subscriptions.find(params[:id]).
ActiveRecord::find only uses ids: http://api.rubyonrails.org/classes/ActiveRecord/FinderMethods.html#method-i-find.

Problem is here
#subscription = #subscriptions.find(params[:email])
because find uses id to fetch the record if you want to fetch by any other field use find_by_"attribute_name", Replace it with
#subscription = Subscription.find_by_email(params[:email])
Or no need to write down extra code. No need to fetch all the subscriptions. To delete use
#subscription = Subscription.find_by_email(params[:email])
or
#subscription = Subscription.find(params[:id])
if #subscription.destroy
flash[:notice] = "You have been unsubscribed"
redirect_to root_path
end

Related

How to Create an Instance of Model A, from a Form inside a view for Model B

So I have a Message model, and a ChatRoom model.
When I display a chat room, I use the show action on the ChatRoom controller. In the view for this action, there is a little form for the user to create a post, and submit that post to the chat room being shown.
When I run my tests, however, I get an error "no route matches [POST] /messages/an_id_of_some_sort". Specifically, in this little test:
post message_path, params: {message: {body: "yo ho ho and a bottle of rum!"}}
assert_redirected_to chat_room_path(#channel)
the error pops up in the post message_path.
The show method on the chat room controller looks like
def show
if(#user = current_user)
#chats = #user.chat_rooms
#chosen = ChatRoom.find_by(id: params[:id])
if(#chosen.messages.any?)
#messages = #chosen.messages
else
#messages = nil
end
#message = Message.new
end
end
Then the little form bit of the view is:
<div class="message-input">
<%= form_for(#message) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= f.text_area :body, placeholder: "Write Message..." %>
<%= f.hidden_field :room, :value => params[:room] %>
<%= button_tag(type: "submit", class: "message-submit-btn", name: "commit", value: "") do %>
<span class="glyphicon glyphicon-menu-right"></span>
<% end %>
<% end %>
</div>
I have a create action on the Messages Controller which does the saving to the database:
#message = current_user.messages.build(message_params);
#message.chat_room = params[:room]
if #message.save
redirect_to chat_room_path(#message.chat_room)
end
and routing-wise I have
Rails.application.routes.draw do
root 'welcome#welcome'
get '/login', to: 'sessions#new'
post '/login', to: 'sessions#create'
delete '/logout', to: 'sessions#destroy'
get '/signup', to: 'users#new'
post '/signup', to: 'users#create'
get 'users/signup_success'
delete '/chat_rooms/leave/:id', to: 'chat_rooms#leave', as: 'current'
get 'welcome/welcome'
resources :users
resources :account_activations, only: [:edit] #Only providing an Edit route for this resource.
resources :password_resets, only: [:new, :edit, :create, :update]
resources :chat_rooms, only: [:new, :create, :show, :index]
resources :messages, only: [:create, :edit, :destroy]
end
I have tried playing around with explicitly setting the :url on the form_for, but no dice. There is another question on this problem, but the solution there hasn't really helped.
I would greatly appreciate any help.
With this line you're running POST /messages/:id
post message_path, params: {message: {body: "yo ho ho and a bottle of rum!"}}
In your routes file you have this:
resources :messages, only: [:create, :edit, :destroy]
This will create the routes POST /messages, PUT/PATCH /messages/:id, and DELETE /messages/:id. You can verify this with rake routes.
None of these generated routes handle POST /messages/:id.
If you're trying to have the test create a new message, then you can use messages_path instead. message_path (with singular message) takes a message argument as a message, e.g. message_path(Message.first) and uses that to build the url.

partials not displaying on new charges controller (stripe)

I made a new controller to integrate Stripe Checkout, but it's acting as its own entire website and none of my partials (_header, _footer) are displaying.
The current setups is straight from their tutorial https://stripe.com/docs/checkout/guides/rails
Charges Controller
class ChargesController < ApplicationController
def new
end
def create
# Amount in cents
#amount = 100
customer = Stripe::Customer.create(
:email => params[:stripeEmail],
:source => params[:stripeToken],
:plan => "tier1",
)
rescue Stripe::CardError => e
flash[:error] = e.message
redirect_to new_charge_path
end
end
Routes
Rails.application.routes.draw do
get 'password_resets/new'
get 'password_resets/edit'
get 'sessions/new'
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'
get 'charges' => 'charges#new'
resources :users
resources :account_activations, only: [:edit]
resources :password_resets, only: [:new, :create, :edit, :update]
resources :charges
end
/layouts/charges.html.erb (controller view)
<% provide(:title, 'Edit Billing') %>
<%= yield %>
views/charges/new.html.erb (form with Stripe Checkout on it)
<%= form_tag charges_path do %>
<article>
<% if flash[:error].present? %>
<div id="error_explanation">
<p><%= flash[:error] %></p>
</div>
<% end %>
<label class="amount">
<span>Amount: $1.00</span>
</label>
</article>
<script src="https://checkout.stripe.com/checkout.js" class="stripe-button"
data-key="<%= Rails.configuration.stripe[:publishable_key] %>"
data-description="Tier 1 Monthly Subscription"
data-amount="100"
data-locale="auto"
data-image="images/marketplace.png"
data-name="Pallet Tier 1"
data-description="Tier 1 Monthly Subscription"
data-label="Join" >
</script>
views/charges/create.html.erb (redirect after successful charge)
<% provide(:title, 'Edit Billing') %>
<h2>Thanks, you paid <strong>$1.00</strong>!</h2>

No route matches in Rails code

This code is all based on the Ruby on Rails tutorial by Michael Hartl. I created an assigned action in my users_controller with
def assign
puts "in assign..."
#scout = User.find(params[:follower_id])
#der = User.find(params[:followed_id])
end
I realize this doesn't do anything currently, but in the _follow partial, I have
<%= form_for #user, url: { action: "assign" } do |f| %>
<div><%= hidden_field_tag :follower_id, #user.id %></div>
<%= f.label :followed_id, "Assign #{#user.name} to" %>
<%= f.collection_select :following, #ders, :id, :name, prompt: true %>
<%= f.submit "Assign", class: "btn btn-primary" %>
<% end %>
But I'm getting the error No route matches {:action=>"assign", :controller=>"users", :id=>"4"}. I'm new to rails so this could just be a stupid question. What am I doing wrong? Do I need to modify my routes.rb file? Also, if I tried <%= form_for #user do |f| %>, how does the controller know which action to use? Is it based on the action displaying the form?
Edit: my routes.rb file is
Rails.application.routes.draw do
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 do
member do
get :following, :followers
end
end
resources :account_activations, only: [:edit]
resources :password_resets, only: [:new, :create, :edit, :update]
resources :relationships, only: [:create, :destroy]
end
Edit 2: the HTML generated by #Rich's form_for block is
<form class="edit_user" id="edit_user_5" action="/users/5/assign" accept-charset="UTF-8" method="post">
<input name="utf8" type="hidden" value="✓">
<input type="hidden" name="_method" value="patch">
<input type="hidden" name="authenticity_token" value="...">
<label for="user_followed_id">Assign Mr. Marley Muller to</label>
<select name="user[following]" id="user_following">
<option value="1">Example User</option>
<option value="2">Matthew Swartz</option>
<option value="3">Joseph Swartz</option>
</select>
<input type="submit" name="commit" value="Assign" class="btn btn-primary">
</form>
Which makes sense why I'm currently getting a can't find id error since it's not sending a real id (edit_user_5)
Edit 3: Here are the parameters being passed for the request
Started PATCH "/users/6/assign" for 68.100.59.128 at 2015-12-15 03:54:39 +0000
Processing by UsersController#assign as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"...", "user"=>{"following"=>"2"}, "commit"=>"Assign", "id"=>"6"}
User Load (0.5ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 6]]
Unpermitted parameter: following
User Load (0.5ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", nil]]
Completed 404 Not Found in 9ms (ActiveRecord: 1.0ms)
ActiveRecord::RecordNotFound (Couldn't find User with 'id'=):
app/controllers/users_controller.rb:69:in `assign'
Edit 4: With the following routes file,
Rails.application.routes.draw do
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 do
member do
get :following, :followers
match :assign, to: :assign, via: [:post, :patch]
end
end
resources :account_activations, only: [:edit]
resources :password_resets, only: [:new, :create, :edit, :update]
resources :relationships, only: [:create, :destroy]
end
and the following form for assigning one user to follow another,
<%= form_for #user, url: { action: "assign" } do |f| %>
<%= f.label :follower_id, "Assign #{#user.name} to" %>
<%= f.collection_select :following, #ders, :id, :name, prompt: true %>
<%= f.submit "Assign", class: "btn btn-primary" %>
<% end %>
I am getting the ActiveRecord::RecordNotFound in UsersController#assign error of Couldn't find User with 'id'=, but with the following parameters:
{"utf8"=>"✓",
"_method"=>"patch",
"authenticity_token"=>"...",
"user"=>{"following"=>"3"},
"commit"=>"Assign",
"id"=>"4"}
The ID's are correct: "user"=>{"following"=>"3"} and "id"=>"4", I believe I am just trying to access them incorrectly. This is the assigns action in the users controller:
def assign
#scout = User.find(params[:id])
#der = User.find(params_hash[:followed_id])
# make scout follow der here
redirect_to #scout
end
Thoughts?
In your routes.rb file you have to define the route for the specific controller action like that:
resource :users do
member do
post 'assign' # change the request method to 'put'
end
end
It will then generate a route for your assign method in the controller like: users/4/assign
For more info visit guides
To add to Emu's answer, the code you have won't work...
def assign
puts "in assign..."
#scout = User.find(params[:follower_id])
#der = User.find(params[:followed_id])
end
The params you'd get from the form_for object would be structured as:
params[:user][:follower_id]
params[:user][:followed_id]
You'd have to use the following:
#app/controllers/users_controller.rb
class UsersController < ApplicationController
def assign
#scout = User.find params[:id]
#der = User.find params_hash[:followed_id]
end
private
def params_hash
params.require(:user).permit(:followed_id)
end
end
You could also get rid of the hidden field in your form if you're using the same #user object to populate it:
<%= form_for #user, url: { action: "assign" } do |f| %>
<%= f.label :followed_id, "Assign #{#user.name} to" %>
<%= f.collection_select :following, #ders, :id, :name, prompt: true %>
<%= f.submit "Assign", class: "btn btn-primary" %>
<% end %>
Update
You need to include :assign in your routes:
Rails.application.routes.draw do
root 'static_pages#home'
resources :static_pages, only: [], path: "" do
collection do
get :help, :about, :contact
end
end
resources :sessions, only: [:new, :create, :destroy], path_names: {new: "login", create: "login", destroy: "logout"}
resources :users, path_names: { new: "signup" } do
member do
get :following, :followers, :assign
end
end
resources :account_activations, only: [:edit]
resources :password_resets, only: [:new, :create, :edit, :update]
resources :relationships, only: [:create, :destroy]
end
It turns out it was a combination of Emu and Rich's answers. The form in the HTML is
<%= form_for #user, url: { action: "assign" } do |f| %>
<%= f.label :follower_id, "Assign #{#user.name} to" %>
<%= f.collection_select :following, #ders, :id, :name, prompt: true %>
<%= f.submit "Assign", class: "btn btn-primary" %>
<% end %>
With controller action
def assign
#scout = User.find(params[:id])
#der = User.find(params[:user][:following])
#scout.follow(#der)
redirect_to #scout
end
and routes as
Rails.application.routes.draw do
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 do
member do
get :following, :followers
match :assign, to: :assign, via: [:post, :patch]
end
end
resources :account_activations, only: [:edit]
resources :password_resets, only: [:new, :create, :edit, :update]
resources :relationships, only: [:create, :destroy]
end

Ruby on Rails, Promote to Admin function

I'm quite new to Ruby on Rails and I'm trying to learn a bit, so I tried making a new function.
The error I'm getting right now is:
ActionController::RoutingError (No route matches [POST] "/users/2"):
I'm trying to make a function to promote other users to admin, which is only possible as an admin.
My users_controller.rb contains:
def promote
if !User.find(params[:id]).admin?
User.find(params[:id]).toggle!(:admin)
flash[:success] = "User is promoted to admin."
redirect_to users_url
else
flash[:danger] = "Admins can't demote other admins."
redirect_to users_url
end
end
My _user.html.erb contains:
<%= link_to user.name, user %>
<% if current_user.admin? && !current_user?(user) %>
<% if !user.admin? %>
<br /> <%= link_to "Delete User", user, method: :delete,
data: { confirm: "You sure?" } %>
| <%= link_to "Promote to Admin", user, method: :promote,
data: { confirm: "You sure?" } %>
<% end %>
<% end %>
And then we have my routes.rb, which contains:
Rails.application.routes.draw do
get 'password_resets/new'
get 'password_resets/edit'
get 'sessions/new'
get 'users/new'
# The priority is based upon order of creation: first created -> highest priority.
# See how all your routes lay out with "rake routes".
# You can have the root of your site routed with "root"
# root 'welcome#index'
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 do
member do
get :following, :followers
end
end
resources :users
resources :account_activations, only: [:edit]
resources :password_resets, only: [:new, :create, :edit, :update]
resources :microposts, only: [:create, :destroy]
resources :relationships, only: [:create, :destroy]
end
I can't exactly find what's going wrong. Some advice would be awesome!
def promote
#user = User.find(params[:id])
if #user.admin?
#user.toggle!(:admin)
flash[:success] = "User is promoted to admin."
redirect_to users_path
else
flash[:notice] = "Admins can't demote other admins."
redirect_to users_path
end
end
<%= link_to #user.name, #user %>
<% if current_user.admin? && !current_user?(#user) %>
<% if !#user.admin? %>
<br />
<%= link_to "Delete User", #user, method: :delete, data: { confirm: "You sure?" } %>
| <%= link_to "Promote to Admin", promote_users_path(user), method: :put, data: { confirm: "You sure?" } %>
<% end %>
<% end %>
in route
resources :users do
member do
get :following, :followers,
put :promote
end
end
or
match '/users', to: 'users#promote', via: :put

Routing Error No route matches

I'm trying to get a user from his profile (user_path) can register his vehicles (new_user_car_path). but i got this error:
Routing Error
No route matches {:action=>"new", :controller=>"cars"}
for that i have the next routes.rb
Estaciones::Application.routes.draw do
root :to => "static_pages#home"
match '/contact', :to=>'static_pages#contact'
match '/about', :to=>'static_pages#about'
devise_for :users
resources :users do
resources :cars, :only => [:new, :create, :edit, :destroy]
end
here is part of the user_path
<div class="container">
<fieldset>
<h1><%= #user.email %></h1>
<br>
<h2>options</h2>
<p>
<strong>new car registration</strong>
<%= link_to "Sign up now!", new_user_car_path, :class => "btn btn-primary" %>
</p>
<p>
<strong>all cars view</strong>
</p>
</fieldset>
</div> <!-- /container -->
and my CarsController
class CarsController < ApplicationController
def new
#car = Car.new
end
def create
#car = current_user.cars.build(params[:car])
if #car.save
redirect_to current_user, :flash => { :success => "car created!" }
else
redirect_to new_user_car_path, :flash => { :success => "sorry try again" }
end
end
end
you need to pass information to route, so that it can determine where to go.
if you want to create a new car for a user, you need to pass the user. otherwise rails will not know where to get the user from... which is kind of logical if you think about it for more then a second...
new_user_car_path(user)

Resources