I got these actions in users controller
class UsersController < ApplicationController
def index #default action
...
end
def new #default action
...
end
def another_new
...
end
def create
...
end
def another_create
...
end
end
I want to be able to
/users/another_new and call from some sort of link :method => :another_create
to make /users/another_new
I got the following config/routes.rb
get '/users/another_new' :to => 'users#another_new'
resources :users
my question is if this is the correct way to add the get and how I add the another_create method.
in your config/routes.rb file do this
resources :users do
collection do
get 'another_new'
post 'another_create'
end
end
Also have a look HERE for clear understanding of concepts.
Hope this helps you dude :)
try this in routes.rb
match "/users/another_new " => "users#another_new", :as => 'another_new'
then you can do
link_to "MyUrl", another_new_path
this should work. Good luck.
Also note that you shouldn't have :method => :another_new. Your options for :method are :get, :put, :post, and :delete, and the one you use should match how you defined the action in routes.
Related
The link in _applicant.html.erb looks like this in the browser: http://localhost:3000/needs/3/applicants.1
and when clicked on this shows up in the browser:
Routing Error
No route matches [PUT] "/needs/3/applicants.1"
I want it to update the acceptance column for this particular applicant row. Basically I want it to send data to the update method of the applicants controller. How can I modify the code to do this?
_applicant.html.erb
<%= link_to 'Accept Applicant', need_applicants_path(applicant.need_id, applicant.id), :method => :put, :action => "update", :applicant => {:acceptance => true} %>
got this from running rake routes:
PUT /needs/:need_id/applicants/:id(.:format) applicants#update
routes.rb:
resources :needs, except: [:new] do
resources :applicants
end
applicants_controller.rb
class ApplicantsController < ApplicationController
def update
#need = Need.find(params[:need_id])
#applicant = #need.applicants.find(params[:id])
if #applicant.update_attributes(params[:applicant])
flash[:success] = 'Your applicant has been accepted/rejected!'
redirect_to #need
else
#need = Need.find(params[:need_id])
render 'needs/show'
end
end
end
I think there are two possible fixes here:
First,
http://localhost:3000/needs/3/applicants.1
should probably read
http://localhost:3000/needs/3/applicants/1
The error is in this line:
<%= link_to 'Accept Applicant', need_applicants_path(applicant.need_id, applicant.id), :method => :put, :action => "update", :applicant => {:acceptance => true} %>
where...
need_applicants_path(applicant.need_id, applicant.id)
You can try passing in two instance objects like so:
need_applicants_path(Need.find(applicant.need_id), applicant)
Second, another possible solution is to explicitly set the PUT path in your routes.
In your config/routes.rb add the line
put 'need/:need_id/applicant/:id/update
then run
rake routes
and see what the PUT path is
Following attempt seems to be functional, but is not the 'clean' result that I am trying to archive.
Following route
get "/learn(/:category)", to: "users#index", as: "learn"
Should be useable for something like "/learn/technology" - Which works, if entered manually in the address bar.
If I tough try to achieve similar in my views, I get the following: "/learn?category=technology" - Which well, technically works, but is not what I want.
I'm using the following inside my view:
- Category.promoted.limit(7).each do |category|
%li.category-button
= link_to learn_path(category) do
= button_tag "", :class => "#{category.name}"
= content_tag(:span, category.to_s, :class => 'category-head')
And my Category Model looks the following:
class Category < ActiveRecord::Base
has_many :skills
validates_uniqueness_of :name
scope :promoted, lambda { where(:promoted => true) }
def to_s
read_attribute(:name).titleize
end
def to_param
name.parameterize
end
end
How would I achieve the 'cleaner' solution?
Edit:
Following works - but there must be a better solution than that?
get "/learn", to: "users#index", as: "learn"
get "/learn/:category", to: "users#index", as: "filter_learn"
Try changing your link to the following:
...
= link_to learn_path(category: category.name) do
...
You may use url_for to solve the problem.
Suppose I have UsersController with index action and this in routes.rb:
resources :users, only: [:index] do
collection do
get ':kind', :to => 'users#index'
end
end
Then when I'm on /users page I can use the url_for this way:
= link_to 'Kind1', url_for(kind: :students)
which will produce path:
/users/students
If I'm on some another page (another controller or another action), then I shoud provide more info. For example when I'm on another controller's page then I should provide both controller and action params if target action is not index (if target action is index then it is sufficient to provide only controller):
= link_to 'Kind1', url_for(controller: :users, action: :index, kind: :students)
it produces the same path:
/users/students
While using users_path(kind: :students) you'll get:
/users?kind=students
I want to add another action to my controller, and I can't figure out how.
I found this on RailsCasts, and on most StackOverflow topics:
# routes.rb
resources :items, :collection => {:schedule => :post, :save_scheduling => :put}
# items_controller.rb
...
def schedule
end
def save_scheduling
end
# items index view:
<%= link_to 'Schedule', schedule_item_path(item) %>
But it gives me the error:
undefined method `schedule_item_path' for #<#<Class:0x6287b50>:0x62730c0>
Not sure where I should go from here.
A nicer way to write
resources :items, :collection => {:schedule => :post, :save_scheduling => :put}
is
resources :items do
collection do
post :schedule
put :save_scheduling
end
end
This is going to create URLs like
/items/schedule
/items/save_scheduling
Because you're passing an item into your schedule_... route method, you likely want member routes instead of collection routes.
resources :items do
member do
post :schedule
put :save_scheduling
end
end
This is going to create URLs like
/items/:id/schedule
/items/:id/save_scheduling
Now a route method schedule_item_path accepting an Item instance will be available. The final issue is, your link_to as it stands is going to generate a GET request, not a POST request as your route requires. You need to specify this as a :method option.
link_to("Title here", schedule_item_path(item), method: :post, ...)
Recommended Reading: http://api.rubyonrails.org/classes/ActionView/Helpers/UrlHelper.html#method-i-link_to
Ref Rails Routing from the Outside In
Following should work
resources :items do
collection do
post 'schedule'
put 'save_scheduling'
end
end
You can write routes.rb like this:
match "items/schedule" => "items#schedule", :via => :post, :as => :schedule_item
match "items/save_scheduling" => "items#save_scheduling", :via => :put, :as => :save_scheduling_item
And the link_to helper can not send post verb in Rails 3.
You can see the Rails Routing from the Outside In
Currently I have a route that looks like this:
resources :posts
I want to override the 'show' action so that I can display a url like this:
posts/:id/:slug
I am currently able to do this by adding a custom match route:
resources :posts
match 'posts/:id/:slug' => 'posts#show'
However, when I use the link_to helper, it does not use my custom show route.
<%= link_to 'show', post %> # renders /posts/123
How can I define my show route so that I can still use the link_to helper?
Update: As you can read in the following answers, you can override the route to the 'show' action, but it's probably more work than it's worth. It's easier to just create a custom route:
# config/routes.rb
match 'posts/:id/:slug' => 'posts#show', as: 'post_seo'
# app/views/posts/index.html.erb
<%= link_to post.title, post_seo_path(post.id, post.slug) %>
You have two routes which point to posts#show (you should be able to confirm this by running rake routes), and your link is using the wrong one.
When you call link_to('show', post) the URL of the link is generated by calling url_for(post) which (eventually, after passing through several other methods on the way) calls post_path(post). Since the route to posts#show that was created by your call to resources(:posts) is named post, that is the route that post_path generates.
You also currently have inconsistent routes for the show, update and destroy actions which will probably cause you problems later on.
You can fix this by changing your routes to the following:
resources :posts, :except => ['show', 'update', 'destroy']
get 'posts/:id/:slug' => 'posts#show', :as => 'post'
put 'posts/:id/:slug' => 'posts#update'
delete 'posts/:id/:slug' => 'posts#destroy'
Unfortunately you still can't use link_to('show', post) just yet, because it relies on being able to use post.to_param as the single argument needed to build a path to a post. Your custom route requires two arguments, an id and a slug. So now your link code will need to look like this:
link_to 'show', post_path(post.id, post.slug)
You can get around that problem by defining your own post_path and post_url helpers in app/helpers/posts_helper.rb:
module PostsHelper
def post_path(post, options={})
post_url(post, options.merge(:only_path => true))
end
def post_url(post, options={})
url_for(options.merge(:controller => 'posts', :action => 'show',
:id => post.id, :slug => post.slug))
end
end
Which means we're finally able to use:
link_to 'show', post
If that all seems like too much work, a common alternative is to use URLs that look more like posts/:id-:slug, in which case you can stick with the standard RESTful routes and just override the to_param method in your Post class:
def to_param
"#{id}-#{slug}"
end
You'll also need to do a little bit of work splitting up params[:id] into an ID and a slug before you can look up the relevant instance in your show, edit, update and destroy controller actions.
resources :posts, except: :show do
get ":slug" => :show, as: "", on: :member
end
and define helper
def post_path post
"/posts/#{post.id}/#{post.slug}"
end
db/migrate/add_slug_to_articles.rb
add_column :articles, :slug, :string
add_index :articles, :slug
models/article.rb
class Article < ActiveRecord::Base
extend FriendlyId
friendly_id :name, use: :slugged
def should_generate_new_friendly_id?
new_record?
end
end
Or...
class Article < ActiveRecord::Base
extend FriendlyId
friendly_id :name, use: :history
end
http://railscasts.com/episodes/314-pretty-urls-with-friendlyid
https://github.com/norman/friendly_id
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