Routing error for rails - uninitialized constant SubscribersController - ruby-on-rails

I have a Subscriber model that takes in a "phone_number" and a "visit" integer. I have two controllers Subscribers and Visits(super and sub) I have never worked with nested controllers before and I'm having some issues with namespace I believe. Because I getting back the uninitialized constant error. Basically the subscriber controller signs up a subscriber and the visit controller counts the amount of times they've visited by user input of their phone_number. Why am I getting this error? I'll show my code for clarity.
CONTROLLERS
class Subscribers::VisitsController < ApplicationController
def new
#subscriber = Subscriber.new
end
def create
#subscriber = Subscriber.find_by_phone_number(params[:phone_number])
if #subscriber
#subscriber.visit += 1
#subscriber.save
redirect_to subscribers_visits_new_path(:subscriber)
else
render "new"
end
end
end
class SubscribersController < ApplicationController
def index
#subscriber = Subscriber.all
end
def new
#subscriber = Subscriber.new
end
def create
#subscriber = Subscriber.create(subscriber_params)
if #subscriber.save
flash[:success] = "Subscriber Has Been successfully Created"
redirect_to new_subscriber_path(:subscriber)
else
render "new"
end
end
ROUTES
Rails.application.routes.draw do
devise_for :users
resources :subscribers, except: :show
get '/subscribers/visits/new', to: 'subscribers/visits#new'
root "welcomes#index"
VIEWS
<h1>hey</hey>
<%= form_for #subscriber do |form| %>
<div class="form-group">
<p>
<%= form.label :phone_number %>
<%= form.text_field :phone_number %>
</p>
<% end %>
ERROR

Hmm, my guess is you are trying to route url subscriber/visits/new to new action in VisitsController?How about changing this line:
get '/subscribers/visits/new', to: 'subscribers/visits#new'
to:
namespace :subscribers do
get '/visits/new', to: 'visits#new'
end
Also try to move this block above resources :subscribers, except: :show if you still get the error.
Cheers

You probably do not need to inherit one controller from another. Simply define the controllers as you normally would:
app/controllers/subscribers_controller.rb
class SubscribersController < ApplicationController
# methods for Subscribers
end
in app/controllers/visits_controller.rb
class VisitsController < ApplicationController
# methods for Visits
end
Note that these must to be located in separate files, so that Rails can find the correct source file by the name of the object that it's looking for. This is a Rails naming convention.
Regarding your routes, you'll need to change to use one of 4 route formats. Reading the section on Adding More RESTful Actions in the Rails Routing from the Outside In guide might help.
1) To route visits as a nested resource, which is what it appears you're actually trying to do, you would use this:
resources :subscribers, except: :show do
resources :visits
end
This will produce these routes:
GET /subscribers/new
POST /subscribers
GET /subscribers
GET /subscribers/:id/edit
PATCH /subscribers/:id/update
DELETE /subscribers/:id/destroy
GET /subscribers/:id/visits/new
POST /subscribers/:id/visits
GET /subscribers/:id/visits
GET /subscribers/:id/visits/:id
GET /subscribers/:id/visits/:id/edit
PATCH /subscribers/:id/visits/:id/update
DELETE /subscribers/:id/visits/:id/destroy
This is the typical route structure for nested resources and separate controllers.
2) To make visits#new a simple collection (non-member) action in the VisitsController, then you likely want this:
resources :subscribers, except: :show do
collection do
get 'visits/new', to 'visits#new'
post 'visits', to 'visits#create'
end
end
This will produce these routes:
GET /subscribers/new
POST /subscribers
GET /subscribers
GET /subscribers/:id/edit
PATCH /subscribers/:id/update
DELETE /subscribers/:id/destroy
GET /subscribers/visits/new
POST /subscribers/visits
This is typically used to add new top-level routes in an existing resource and controller.
3) To construct visits as member actions, use this:
resources :subscribers, except: :show do
member do
get 'visits/new', to 'visits#new'
post 'visits', to 'visits#create'
end
end
This will produce these routes:
GET /subscribers/new
POST /subscribers
GET /subscribers
GET /subscribers/:id/edit
PATCH /subscribers/:id/update
DELETE /subscribers/:id/destroy
GET /subscribers/:id/visits/new
POST /subscribers/:id/visits
This is normally used to add new member routes in an existing resource and controller.
4) To simply make visits routes appear to be included in subscribers, you could use this:
get '/subscribers/visits/new', to: 'visits#new'
post '/subscribers/visits', to: 'visits#create'
resources :subscribers, except: :show
This will produce these routes:
GET /subscribers/visits/new
POST /subscribers/visits
GET /subscribers/new
POST /subscribers
GET /subscribers
GET /subscribers/:id/edit
PATCH /subscribers/:id/update
DELETE /subscribers/:id/destroy
This may be used to make arbitrary routes appear to be included in an existing resource, when they really may be independent.

Related

Rails Routing Precedence favors the first

So Ive been working on a rails project that defines two different create actions in the same controller. Here's my controller:
class SmsSendsController < ApplicationController
def new
#at = SmsSend.new
#contact = Contact.find_by(id: params[:id])
end
def create
#at = SmsSend.create(sms_params)
if #at.save!
#con = current_user.contacts.find_by(id: #at.contact_id)
AfricasTalkingGateway.new("trial-error").sendMessage(#con.phonenumber, #at.message)
end
end
def new_all
#at = SmsSend.new
#contact = Contact.find_by(id: params[:id])
end
def create_all
#at = SmsSend.create(sms_params)
if #at.save!
current_user.contacts.each do |c|
AfricasTalkingGateway.new("trial-error").sendMessage(c.phonenumber, #at.message)
end
end
end
private
def sms_params
params.require(:sms_send).permit(:mobile, :message, :contact_id)
end
end
In my
routes.rb
file, Ive used both custom and resourceful routes to define routes for the first and the second new/create actions:
Rails.application.routes.draw do
devise_for :users
get 'sms_sends/new_all', to: 'sms_sends#new_all'
post 'sms_sends', to: 'sms_sends#create_all'
resources :contacts
resources :sms_sends
root 'contacts#index'
end
So both post actions will work if and only if its routes are placed before the other. Is there a way I can get rid of the precedence? Or where am I going wrong?
Thankie.
So both post actions will work if and only if its routes are placed
before the other.
That is how you should define for the routes to work. Because the routes that defined in the routes.rb will be compiled from top-to-bottom. So if your custom routes gets preceded by resourceful routes, then the custom routes will conflict with your resourceful routes.
Is there a way I can get rid of the precedence?
Define them as collection routes like so,
resources :sms_sends do
get 'sms_sends/new_all', to: 'sms_sends#new_all', on: :collection
post 'sms_sends', to: 'sms_sends#create_all', on: :collection
end
The above will generate routes with path helpers like below
sms_sends_new_all_sms_sends GET /sms_sends/sms_sends/new_all(.:format) sms_sends#new_all
sms_sends_sms_sends POST /sms_sends/sms_sends(.:format) sms_sends#create_all
For a better readability, you can change your custom routes like so
resources :sms_sends do
get 'new_all', to: 'sms_sends#new_all', on: :collection
post 'create_all', to: 'sms_sends#create_all', on: :collection
end
This will generate the path helpers like below
new_all_sms_sends GET /sms_sends/new_all(.:format) sms_sends#new_all
create_all_sms_sends POST /sms_sends/create_all(.:format) sms_sends#create_all

Save Form Data to database Ruby on Rails

Am trying to save the form data into my database
but for some reason I keep getting an error.
Am fairly new to ruby so am not too sure what the problem is.
Am trying to create a new book entry and here is what I have so far.
books.controller
class BooksController < ApplicationController
def new
#book = Book.new
end
def create
#book = Book.new(book_params)
if #book.save
redirect_to new_book_path
end
end
private
def book_params
params.require(:book).permit(:title, :description, :author, :status, :isbn_number)
end
end
There error am getting is:
NameError in BooksController#create
undefined local variable or method `new_book_path' for #<BooksController:0xe3f5ae8>
I have a form that I fill in all those details but when I try to submit, I get that error. Its saying the error is on the redirect but I don't know whats wrong.
routes
Rails.application.routes.draw do
resources :books, :only => [:new, :create]
get 'page/books'
get 'page/about'
get 'page/contact'
get 'page/home'
devise_for :users
# 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 'page#home'
end
looks like your routes file has an issue:
your config/routes.rb file should have the following
resources :books, :only => [:new, :create]
For a more complete answer:
The error you are getting is saying the line
redirect_to new_book_path
is throwing an error because it does not understand the variable new_book_path.
This variable gets created/handled via your routes file.
Just try changing this line
redirect_to new_book_path
to
render 'new'

Rails nested Resources not working in controller

I have this nested resource:
resources :services do
resources :users do
put "assign" => "services#users#assign", as: :assign
end
end
My form contains this:
<%= button_to 'submit', service_user_assign_url(service.id, abstractor.id), method: :put %>
this generates the following url, which looks fine to me:
http://localhost:3000/services/1/users/2/assign
and the following is in my services controller:
def assign
#service = Service.find(params[:service_id])
#service.users << User.find(params[:user_id])
redirect_to dashboards_path
end
However I get this error:
The action 'users' could not be found for ServicesController
I'm not sure what this means - I have a has and belongs to many relationship between users and services and I am trying to associate an existing user to a service
You need to tell rails if this action is a member action or a collection action, from the url you mentioned that you want to use, it's a member action:
resources :services do
resources :users do
member do
put :assign
end
end
end

Routing Error - custom controller

I have a has many through association.
Firms have many Users through Follows.
I want Users to be able to Follow Firms. - I am using Devise for the users.
I have the following action in my firms controller.
def follow
#firm.users << current_user
end
in my routes.rb
resources :firms do
post :follow, on: :member
end
and in my firms view
<%= link_to "Follow", follow_firm_path(#firm), method: :post %>
However when I keep getting the following Routing Error in the browser
No route matches {:action=>"follow", :controller=>"firms"}
Rake Routes confirms the following
follow_firm POST /firms/:id/follow(.:format) firms#follow
Any ideas what the problem may be?
Many thanks
Edit: Controller code
class FirmsController < ApplicationController
before_filter :authenticate_user!, :except => [:show, :index]
def index
#firm_names = Firm.all.map &:name
direction = params[:direction]
direction ||= "ASC"
#firms = Firm.order("name #{direction}")
respond_to do |format|
format.html # index.html.erb
format.js
end
end
def follow
#firm.users << current_user
end
I am using the follow action in a partial in the index view.
everything looks good and this should work perfectly. Except that I see a typo in the following line
<%= link_to "Follow", follow_firm_path(#firm), method: :post %>
after the :method there should an => not a : . this will make the link a get request not a post request, that might be the issue, try using a simple link and replace post will get in your routes.rb just to test if the issue is arising due to this.
you can also test route methods from the console
rails c
app.follow_firm_path(2)
I noticed you also have an error in your routes, there should be an => not a : after :on
resources :firms do
post :follow, :on => member
end
You should define methods like this...
resources :firms do
collection
post :follow, on: :member
end
end
I think if this method does not create anything its type should be get.
Try it

Resourceful Routes helpers _path and _url dont work

I am trying to redirect user to show_city_url or show_city_path but i get an exception that they are both undefined.In the city controller i have three actions show,like, and dislike. unlike_city_path and like_city_path works but show_city_path doesnt.Also when i put this in all_cities action redirect_to :controller=>"city",:action=>"show" works.What am i doing wrong?Thank you.
class HomeController < ApplicationController
def all-cities
redirect_to show_city_url
end
end
In the Routes
resources :city do
member do
post :like
post :dislike
get :show
end
end
according to your comments:
resources :cities, :controller => 'city' do
collection do
get :show, :as => :show
end
member do
post :like
post :dislike
end
end
now you can call show_cities_url and you'll land in the show action of your CityController.
PS: Following the Rails' convention makes your life easier ;)
RoR Guide: Rails Routing from the Outside In

Resources