1

Rails 4 поставляется с сильными параметрами, что отличное дополнение, но я столкнулся с проблемой. У меня есть полиморфная модель Comment, и я не могу на всю жизнь получить контроллер, чтобы принять параметры, которые ему нужны. Вот мой код (укороченный для ясности):ForbiddenAttributesError для полиморфной модели в Rails 4

Маршруты:

resources :articles do 
    resources :comments 
end 

Модели:

class Article < ActiveRecord::Base 
    has_many :comments, :as => :commentable 
end 

class Comment < ActiveRecord::Base 
    belongs_to :commentable, :polymorphic => true 
end 

Контроллер:

class CommentsController < ApplicationController 
    before_action :get_commentable 

    def create 
    @comment = @commentable.comments.new(comment_params) 
    if @comment.save 
     redirect_to @commentable, :notice => "Thank you!" 
    else 
     render :new 
    end 
    end 

private 

    def get_commentable 
    resource, id = request.path.split("/")[1,2] 
    @commentable = resource.singularize.classify.constantize.find(id) 
    redirect_to :home unless defined?(@commentable) 
    end 

    def comment_params 
    params.require(:comment).permit(:title, :message) 
    end 
end 

Опубликовано PARAMS (из формы на статьи #show):

{"authenticity_token"=>"v70nN8aFpofNw9vbVjhpsm9SwLOwKlOpNOEOTozUwCk=", 
"comment"=>{"title"=>"Test","message"=>"Testing"}, 
"article_id"=>"1"} 

кажется мне, как она должна работать, но все, что я пытаюсь я получаю ActiveModel::ForbiddenAttributesError in CommentsController#create - даже когда я пытаюсь

def comment_params 
    params.permit! 
    end 

в контроллере. У меня нет таких проблем с другими (не полиморфными) моделями, поэтому я подозреваю, что это имеет какое-то отношение к полиморфизму. Есть идеи?

+0

На самом деле, кажется, что это ошибка, вызванная канкан, который я использую, чтобы сделать авторизацию на основе ролей - его отключение позволяет создавать комментарии. Хммм. –

ответ

2

Поскольку отсутствие ответов, казалось, указывало на то, что я лаял неправильное дерево здесь. Проблема заключается не в сильных параметрах, а в использовании камня CanCan, который я использую для выполнения авторизации на основе роли и действия. По-видимому, это связано с тем, как CanCan присваивает параметры объектам (CanCan использует методы ActionController по умолчанию) - см. Подробности в this bug report, в частности the reply from "rewritten". Короче говоря, положить это в мой контроллер приложений решает эту проблему:

before_filter do 
    resource = controller_name.singularize.to_sym 
    method = "#{resource}_params" 
    params[resource] &&= send(method) if respond_to?(method, true) 
end 

Update:

Как отметил @scaryguy, если выше метод вызывается из контроллера, который не имеет связанный с ним модель будет падать. Решение просто назвать метод и назвать его как before_filter, в то же время явно исключая его в тех контроллерах, у которых нет моделей (и, следовательно, в любом случае не будет использовать автоматическое назначение CanCan). Я считаю, что-то вроде этого:

before_filter :can_can_can 

def can_can_can 
    resource = controller_name.singularize.to_sym 
    method = "#{resource}_params" 
    params[resource] &&= send(method) if respond_to?(method, true) 
end 

, а затем в модели менее контроллера:

skip_before_filter :can_can_can 
+0

Это была та же проблема, что и у меня, и это решение работало отлично. Бьюсь об заклад, многие люди сталкиваются с этой проблемой с течением времени. – Ecnalyr

+0

Спасибо @Ecnalyr, рад услышать, что это помогло кому-то! –

+0

Да, это работает, но только тогда, когда существуют контроллеры и модели, и оба они правильно названы. Это ломает ситуацию, когда вы хотите использовать контроллер без модели. – scaryguy

Смежные вопросы