在rails控制台中创建实例时,Rails 4强参数失败

ran*_*its 15 ruby ruby-on-rails strong-parameters ruby-on-rails-4

可能在这里做一些愚蠢的事情,但这里是我的基本cookie切割器类:

class League < ActiveRecord::Base

    private
      def league_params
        params.require(:full_name).permit!
      end

end
Run Code Online (Sandbox Code Playgroud)

在创建联盟的新实例时:

2.0.0-p0 :001 > l = League.new(full_name: 'foo', short_name: 'bar')
WARNING: Can't mass-assign protected attributes for League: full_name, short_name
Run Code Online (Sandbox Code Playgroud)

我到底错在了什么?这是一个Rails 4.0.0.beta1 build + Ruby 2.0

**更新**

我现在意识到强大的参数现在在Controller中实施,而不是在模型中.最初的问题仍然存在.如果在控制器级别允许它们,如果我在Rails控制台中创建实例,如何正确地将属性列入白名单?我是否还需要attr_accessible在这种情况下也使用,从而完全复制哪些强参数试图"修复"?

小智 14

两件事情.该league_params定义云控制器,而不是模型.并且params.require()应该包含参数中需要存在的模型的名称,而不是属性.属性存在检查仍应在模型验证中.并且确保您确实希望在使用之前允许访问League模型中的所有属性permit!.所以,它应该是这样的:

class LeaguesController < ApplicationController

  private
    def league_params
      params.require(:league).permit!
    end

end
Run Code Online (Sandbox Code Playgroud)

更新:

是的,如果您希望在直接访问模型时限制属性,则需要切换回使用attr_accessible模型中的模型.该功能已移至此gem:https://github.com/rails/protected_attributes.

我认为如果您直接在控制台中使用模型,则不需要保护属性,因为您确切知道输入的内容.由于控制台可以完全访问您的应用程序,因此管理整个数据库与恶意分配属性一样容易.

  • 那么我还是需要回到attr_accessible? (3认同)

Ner*_*ian 7

存在强参数attr_accessible的基本安全原因是模型中存在某些不应允许更改的属性,除非它是您的代码的明确意图.

他们之间的细微差别是他们完成工作的透视形式.

StrongParameters专注于用例:可以对每个控制器的操作进行微调,以允许或禁止某些参数,同时考虑任何条件.灵活性.

attr_accessible采用不同的视角.它专注于角色,而不是专注于用例.因此,例如,取决于用户的角色,可以改变或不改变某些属性.


使用StrongParameters的方法是在param哈希上应用requirepermit关键字.

require声明密钥必须出现在params哈希上.require如果没有这样的钥匙,将提出异常.

permit声明允许一个字段.任何不允许的密钥都将从哈希中删除,因此不会通过批量分配传递给模型.

模型

class League
   attr_protected :final_price  # Nobody can mass-assign the final price
   attr_accessible :winner_name, :as => :jury
end
Run Code Online (Sandbox Code Playgroud)

和控制器

class LeaguesController < ApplicationController
Run Code Online (Sandbox Code Playgroud)

这两个动作使用StrongParameters

  # A common user can create a league
  def create
    league = League.new(league_params)
    league.final_price = 1000
    league.save
    redirect_to(league)
  end

  # But only the admin can publish a league
  def publish_league
     league = League.find(params[:id]
     league.update_attributes(league_params_as_admin)
  end
Run Code Online (Sandbox Code Playgroud)

这个使用attr_accessible

  def publish_the_winner
    league = League.find(params[:id]
    # We would expect the current_user.role to return :jury.
    league.assign_attributes(params[:league], :as => current_user.role)
  end

  private
    def league_params
      params.require(:league).permit(:name)
    end

    def league_params_as_admin
      params.require(:league).permit(:name, :status)
    end 

end
Run Code Online (Sandbox Code Playgroud)

在我的经验中:

使用强参数的灵活性来微调可以在每个控制器中批量分配的属性.

使用无处不在的attr_accesible来确保无论如何都无法对某些属性进行质量分配.例如,在Resque Task中,您可以将用户输入作为参数传递.您将检查是否使用attr_accesible对某些属性进行了大量分配.

更多信息:

http://api.rubyonrails.org/classes/ActiveModel/MassAssignmentSecurity/ClassMethods.html

https://github.com/rails/strong_parameters