Метод действия: :id с link_to?

Когда я пытаюсь подписаться на продукт, нажав на ссылку:

<%= link_to "Subscribe", :controller => "products", :action => "subscribe_product", :id => product.id, :method => :post %>

Я получаю эту ошибку и замечаю, что параметры неверны.

ActiveRecord::RecordNotFound in ProductsController#show

Couldn't find Product with id=subscribe_product

{"id"=>"subscribe_product", "method"=>"post"}

Мой метод subscribe_product в моем ProductsController:

def subscribe_product
  @product = Product.find(params[:id])
  @product.subscriptions.create(:subscriber_id => current_user.id)
end

Мой маршрут:

resources :products do
  post :subscribe_product, :on => :collection
end

Это ассоциации:

class User
  has_many :products
  has_many :subscriptions, :foreign_key => :subscriber_id

class Product
  belongs_to :user
  has_many :subscriptions, :as => :subscribable

class Subscriptions
  belongs_to :subscriber, :class_name => "User"
  belongs_to :subscribable, :polymorphic => true

Пользователи подписываются в другом контроллере:

PagesController
  def index
   @product_history = current_user.products
  end
end

pages/index.html.erb

<% for product in @product_history %>
  <%= product.name %>
  <%= product.price %>
  <%= link_to "Subscribe", :controller => "products", :action => "subscribe_product", :id => product.id, :method => :post %>
<% end %>

Так почему же вместо этого мой метод действия рассматривается как идентификатор?


person LearningRoR    schedule 06.04.2012    source источник


Ответы (3)


Поскольку вы проезжаете id, маршрут subscribe_product должен быть маршрутом member. Попробуйте это и дайте мне знать, что вы получите:

resources :products do
  member do
    post 'subscribe_product'
  end
end

В контроллере (чтобы обойти атрибуты, не назначаемые массово):

def subscribe_product
  @product = Product.find(params[:id])
  subscription = Subscription.new
  subscription.subscriber_id = current_user.id
  @product.subscriptions << subscription
end
person tsherif    schedule 06.04.2012
comment
При использовании моего первого link_to: <%= link_to "Subscribe", :controller => "products", :action => "subscribe_product", :id => product.id, :method => :post %> выдает ошибку - No route matches [GET] "/products/5/subscribe_product" - person LearningRoR; 06.04.2012
comment
Я думаю, ваша ссылка должна выглядеть так (отдельный хэш для пути): <%= link_to "Subscribe", {:controller => "products", :action => "subscribe_product", :id => product.id}, :method => :post %>. Если это не сработает, можете запустить rake routes | grep subscribe_product и сообщить мне, что получилось. - person tsherif; 06.04.2012
comment
Я думаю, что это работает, но я заметил, что у меня есть Can't mass-assign protected attributes: subscriber_id, subscribable_type, поэтому я не был бы в этом уверен. Я не хочу, чтобы они были доступны как массово назначаемые. Прямо сейчас я получаю Template Missing, но я могу просто эффективно перенаправить. - person LearningRoR; 06.04.2012
comment
Это просто означает, что вы не можете создать их с помощью хэша в своем контроллере. Я обновлю свой ответ, чтобы показать вам, как это нужно сделать. - person tsherif; 06.04.2012

Пытаться :

resources :products do
  post :subscribe_product, :on => :member
end

Он будет генерировать такие маршруты, как:

subscribe_product_product POST     /product/:id/subscribe_product(.:format)   {:action=>"subscribe_product", :controller=>"products"}

и используйте путь, как в представлении:

subscribe_products_path(product.id)
person Community    schedule 06.04.2012

Пожалуйста, попробуйте это. Измените маршрут на:

resources :products do
  post :subscribe
end

Затем измените ссылку, например:

<%= link_to "Subscribe", subscribe_products_path(:id => product.id), :method => :post %>
person Spyros    schedule 06.04.2012
comment
Это дает мне NoMethodError, потому что просматриваемые продукты находятся в другом контроллере. Не знаю, как с этим справиться. Я отредактирую свой ответ и покажу контроллер и представление. - person LearningRoR; 06.04.2012
comment
какая ошибка без метода? по какому методу? Попробуйте вместо этого subscribe_products_path, я ошибся в порядке названного маршрута: P - person Spyros; 06.04.2012
comment
Я должен был сделать это post :subscribe, :on => :collection, но затем я получаю сообщение об ошибке Couldn't find Product without an ID. - person LearningRoR; 06.04.2012
comment
Template missing, это новинка! Он считает, что метод subscribe теперь является представлением. - person LearningRoR; 06.04.2012
comment
Это потому, что вы не перенаправляете куда-либо в своем методе контроллера подписки. Если вы добавите «redirect_to products_path», он будет перенаправлен на эту страницу. Я настоятельно рекомендую прочитать книгу о Rails, чтобы лучше понять, как с ним работать. - person Spyros; 06.04.2012