В моем приложении монеты могут принадлежать или не принадлежать сетям. Следовательно, в моем routes.rb
есть следующее:
resources :coins
resources :networks do
resources :coins
end
Вы можете подписаться на coins
с помощью монет # подписаться и отписаться от них с помощью монет # отписаться
Это работает очень хорошо для монет, которые принадлежат сетям через:
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
Я хотел бы сделать это также:
match 'coins/:id/follow', to: 'coins#follow', via: 'get', :as => :follow_coin
match '/coins/:id/unfollow', to: 'coins#unfollow', via: 'get', :as => :unfollow_coin
Но я получаю эту ошибку при посещении coins/coinname
, например:
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.
Мне неясно, что является правильным решением. Я хотел бы отобразить networks/:network_id/coins/:id/follow
и coins/:id/follow
на действие coins#follow
, которое уже подготовлено для обработки монет, принадлежащих сетям, и монет, которые этого не делают.
Я подозреваю, что даже с:
match 'networks/:network_id/coins/:id/follow', to: 'coins#follow', via: 'get', :as => :follow_coin
Я мог бы сделать это лучше с networks
ресурсами
2 ответа
В дополнение к тому, что сказал seaify (отличный совет!), Вы можете просто сделать:
resource :coins do
member do
put :follow
put :unfollow
end
end
Затем, когда вы хотите использовать network_id
, сделайте что-то вроде (при условии, что у вас определена переменная @coin
):
follow_coin_path(network_id: network_id)
Что даст вам что-то вроде:
/coins/2/follow?network_id=1
И ваши параметры будут примерно такими:
{..., id: 2, network_id: 1, ...}
Поскольку, похоже, у вас уже есть логика для определения наличия параметра network_id
.
Если вы пытаетесь использовать coinname
в качестве идентифицирующей переменной (вместо id
), то сделайте что-то вроде:
resources :coins, param: :coinname do
member do
put :follow
put :unfollow
end
end
Когда вы делаете rake routes
, вы должны увидеть что-то вроде:
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
И ваши параметры будут содержать что-то вроде:
{..., coinname: 'bitcoin', ...}
Кроме того, когда вы используете link_to
, не забудьте сделать:
link_to("Follow #{@coin.name}", follow_coin_path(@coin), method: :put)
Если вы не используете method: :put
, то link_to
генерирует get
. И вы получите ошибку No route matches [GET] "/coins/coinname/follow"
.
Можно установить один и тот же controller#action
для другого URL.
Но они должны иметь разные route helper
, поэтому в представлении rails или контроллере мы можем сгенерировать соответствующий URL для них.
Изменить код на это
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
Поэтому при использовании network_follow_coin(network_id, coin_id)
генерируется url /networks/1/coins/2/follow
.
При использовании follow_coin_path(coin_id)
он генерирует URL /coins/2/follow
.
Что касается упрощения кода, вы должны использовать resource
для лучшего переноса и понимания, сократить использование match
(на самом деле я думаю, что никогда). Изменить на этот путь
resource :networks do
resource :coins do
member do
put :follow
put :unfollow
end
end
end
И еще одна вещь: если вы что-то измените в своей базе данных, вы не должны устанавливать http method
как get
. Если это метод get
, он предполагает просто выборку данных, без изменений. Это также опасно, потому что некоторые пауки продолжают посещать каждую ссылку на ваших сайтах, это может активировать некоторые плохие вещи.
Похожие вопросы
Новые вопросы
ruby-on-rails
Ruby on Rails - это полнофункциональная платформа веб-приложений с открытым исходным кодом, написанная на Ruby. Он следует популярной модели фреймворка MVC и известен своим подходом «соглашение поверх конфигурации» при разработке приложений.