Reputation: 398
In my app, coins may or may not belong to networks. Hence I have the following in my routes.rb
:
resources :coins
resources :networks do
resources :coins
end
You can follow coins
via coins#follow and unfollow them via coins#unfollow
This is working just fine for coins which belong to networks via:
match 'networks/:network_id/coins/:id/follow', to: 'coins#follow', via: 'get', :as => :follow_coin
match 'networks/:network_id/coins/:id/unfollow', to: 'coins#unfollow', via: 'get', :as => :unfollow_coin
I'd like to do this as well:
match 'coins/:id/follow', to: 'coins#follow', via: 'get', :as => :follow_coin
match '/coins/:id/unfollow', to: 'coins#unfollow', via: 'get', :as => :unfollow_coin
But I am getting this error when visiting coins/coinname
, for example:
Invalid route name, already in use: 'follow_coin' You may have defined two routes with the same name using the `:as` option, or you may be overriding a route already defined by a resource with the same naming.
I am unclear on what the proper solution is. I'd like to map both networks/:network_id/coins/:id/follow
and coins/:id/follow
to the coins#follow
action, which is already prepared to handle coins that belong to networks and coins that don't.
I suspect that even with:
match 'networks/:network_id/coins/:id/follow', to: 'coins#follow', via: 'get', :as => :follow_coin
I could be doing this better with networks
resources
Upvotes: 0
Views: 2751
Reputation: 20263
In addition to what seaify said (great advice!), you could just do:
resource :coins do
member do
put :follow
put :unfollow
end
end
Then, when you want to use the network_id
, do something like (assuming you have a @coin
variable defined):
follow_coin_path(network_id: network_id)
Which will give you something like:
/coins/2/follow?network_id=1
And your params will be something like:
{..., id: 2, network_id: 1, ...}
Since it sounds like you already have the logic to determine whether the network_id
parameter is present.
If you're trying to use coinname
as the identifying variable (instead of id
), then do something like:
resources :coins, param: :coinname do
member do
put :follow
put :unfollow
end
end
When you do rake routes
, you should see something like:
follow_coin PUT /coins/:coinname/follow(.:format) coins#follow
unfollow_coin PUT /coins/:coinname/unfollow(.:format) coins#unfollow
coins GET /coins(.:format) coins#index
POST /coins(.:format) coins#create
new_coin GET /coins/new(.:format) coins#new
edit_coin GET /coins/:coinname/edit(.:format) coins#edit
coin GET /coins/:coinname(.:format) coins#show
PATCH /coins/:coinname(.:format) coins#update
PUT /coins/:coinname(.:format) coins#update
DELETE /coins/:coinname(.:format) coins#destroy
And your params will contain something like:
{..., coinname: 'bitcoin', ...}
Also, when you're using link_to
, remember to do:
link_to("Follow #{@coin.name}", follow_coin_path(@coin), method: :put)
If you don't use method: :put
, then link_to
generates a get
. And you'll end up with the No route matches [GET] "/coins/coinname/follow"
error.
Upvotes: 1
Reputation: 748
It's ok to set same controller#action
for different url.
But they should have different route helper
, so in rails view or controller, we can generate corresponding url for them.
Change code to this
match 'networks/:network_id/coins/:id/follow', to: 'coins#follow', via: 'get', :as => :network_follow_coin
match 'coins/:id/follow', to: 'coins#follow', via: 'get', :as => :follow_coin
So when use network_follow_coin(network_id, coin_id)
, it generate url /networks/1/coins/2/follow
.
When use follow_coin_path(coin_id)
, it generate url /coins/2/follow
.
As to simplify code, you should use resource
for better wrap and understand, reduce the use of match
(actually i think never). Change to this way
resource :networks do
resource :coins do
member do
put :follow
put :unfollow
end
end
end
And another thing is that if you change something in your database, you shouldn't set http method
as get
. If it's get
method, it suppose to just fetch data, no modify. It's also dangerous, because some spiders keep visit every link in your websites, it might activate some bad things.
Upvotes: 1