В моем приложении монеты могут принадлежать или не принадлежать сетям. Следовательно, в моем 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 ресурсами

0
libovness 24 Апр 2017 в 17:05

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".

1
jvillian 24 Апр 2017 в 16:40

Можно установить один и тот же 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, он предполагает просто выборку данных, без изменений. Это также опасно, потому что некоторые пауки продолжают посещать каждую ссылку на ваших сайтах, это может активировать некоторые плохие вещи.

1
seaify - Freelancer 24 Апр 2017 в 15:18
43590277