Rails routing error when routing to slug - ruby-on-rails

I have a the following link that goes to the correct page i.e. /events/tech/schedule but I get a routing error.
<%= link_to "View Schedule", event_sessions_path(#event.slug) %>
Error
ActionController::RoutingError at /events/tech/schedule
Not Found
Routes
resources :events do
resources :sessions, path: "schedule", only: [:index]
end
Sessions Controller
before_filter :find_event
private
def find_event
#event = Event.find_by(slug: params[:id])
##event = Event.find(params[:event_id]) This works if I use <%= link_to event_sessions_path(#event.id) %>
end
I don't get any error if I use the event id to link to but this looks ugly and isnt a very good solution.
Edit - add rake routes
event_sessions GET /events/:event_id/schedule(.:format) sessions#index

Here's your solution:
#event = Event.find_by(slug: params[:event_id])
When using resourceful routes in the structure you have, you'll end up wtih this:
events/:event_id/schedule #-> to schedules#index with params[:event_id]
The name of the variable doesn't matter - it's the content which does. :event_id can hold anything (id or slug), what matters is how you deal with it in the controller
If you change your Event.find_by method to use the event_id param, you'll be able to find what you need
friendly_id
A better way to handle this is with friendly_id
If you use the finders module in friendly_id, you'll be able to search either id or slug like this:
Event.find params[:event_id]

Related

Routing error for rails - uninitialized constant SubscribersController

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.

Rails 4 match all routes for one controller

I have a controller with a number of static pages and I would ideally like to route them all with a wildcard.
Is it possible to do something like the following?
get 'static/:action'
Why don't you just use the show action:
#config/routes.rb
resources :static, param: :page, only: :show #-> url.com/static/:page
#app/controllers/static_controller.rb
class StaticController < ApplicationController
def show
render "#{params[:page]}"
end
end
This way, you can pass the "page" directly through the link and have it all handled by Rails:
<%= link_to "About", static_path("page") %>
You probably need something like get 'static/:action', to: 'static#show' and then in your StaticController show action render the correct static page based on the params[:action] parameter.
See http://guides.rubyonrails.org/routing.html#defining-defaults for more.
You can route something like
get '*path', to: 'static#show'

Thumbs up gem routing error

I seek clarification on using the thumbs up gem with rails 4. I current have a user resource and a post resource and have set up thumbs up as follows.
add gem to gemfile and installed it using bundler.
Generated require migration
User model
class User < ActiveRecord::Base
acts_as_voter
end
Post model
class Post < ActiveRecord::Base
acts_as_voteable
end
Post controller
def vote_up
#post = Post.find(params[:id])
current_user.vote_for(#post)
respond_to do |format|
format.js
end
end
View
<%= link_to('vote for this post!', vote_up_post_path(#post) , :method => :post) %>
Route file
resources :posts do
member do
post :vote_up
end
end
However i keep getting this error
No route matches [POST] "/posts/vote_up"
And after running rake routes I can see that the following route is available to me:
vote_up_post POST /posts/:id/vote_up(.:format) posts#vote_up
any ideas what could be the cause of this error ?
Could you please show us your view.
Apparently, you are calling
/posts/vote_up
instead of
/posts/:id/vote_up
"vote_up" acts like a RESTful action, similar to "post/1/delete", "post/1/edit". So you need to add this custom RESTful action in route.
Change your route like this at first.
resources :posts do
member do
post 'vote_up'
end
end
Then, in your view, to use this path, add resource as arg
vote_up_post_path #post
Reference: http://guides.rubyonrails.org/routing.html#adding-more-restful-actions
Other people reading this notes should realise that post is not a singluar of his controller posts... but the post http verb
resources :contenders do
member do
post 'vote_up'
end
end
Not sure but in your view, instead of #post try giving #post.id to vote_up_post_path.
<%= link_to('vote for this post!', vote_up_post_path(#post.id) , :method => :post) %>

Rails - custom action in controller - how to reference in view?

I'm using a custom action to get the id of a project into the session, so that only relevant info for that project is shown in other areas. I've made a custom action in the projects controller, and am having trouble getting a link to work in the view to call that action. I just get an error saying "Couldn't find project without ID". I'm new to rails - I know it's probably an easy question, but help would be much appreciated, thanks!
View Code:
<%= link_to 'Select Project', :action => :select_project %>
Controller Code:
def select_project
#project = Project.find(params[:id])
session[:project_id] = #project.id
end
Routes:
resources :projects do
collection do
get :select_project
end
end
Alternative routes code:
resources :projects do
put 'select_project', on: :member
end
This is untested but I believe it is what you are looking for:
Routes:
resources :projects do
member do
post :set_current
end
end
this should create the following:
Endpoint: /projects/:id/set_current POST
Helper: set_current_project_path
Controller
def set_current
project = Project.find(params[:id])
session[:project_id] = project.id
redirect_to projects_path, :notice => "Current project set to #{project.name}"
end
Views
# index / erb tags excluded for simplicity
#projects.each do |project|
link_to 'Select Project', set_current_project_path(project), :method => :post
end
# show
<%= link_to 'Select Project', set_current_project_path(#project), :method => :post %>
See:
http://guides.rubyonrails.org/routing.html#adding-more-restful-actions
http://guides.rubyonrails.org/routing.html#crud-verbs-and-actions
Note also the use of 'post' instead of 'get', since we are changing the state of an object (session)
it is preferred to use a post not a get, otherwise users might pull up an old get request in the address bar
of their browser and set their session to a project unknowingly.
like varatis said - use rake routes or CONTROLLER=projects rake routes to help with determining what your route/path helpers look like and what http verbs they are expecting
And is there a reason why it's project not #project in the controller
The #project creates an instance variable; in a rails controller instance variables are made available to the views. This set_current action will never render a view, so no reason to make an instance variable out of it.
How come you have to set it to member and not collection in the routes
any action where you want to reference params[:id] should be a member route, an alternative would be to leave it as a collection route and pass params[:project_id] and pass that in all of your link_to calls, but in this case member makes more sense.
I believe resources :projects is a short cut for this break down
member do
get :show
get :edit
put :update
delete :destroy
end
collection do
get :index
get :new
post :create
end
hopefully that clarifies your questions some?
I think the route generated would be select_project_projects_path.
Link:
<%= link_to 'Select Project', select_project_projects_path %>
For future reference, run rake routes to see the automatic route helpers generated by Rails.

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

Resources