簡體   English   中英

Rails中的動態attr_accessible

[英]Dynamic attr_accessible in rails

根據Rails-cast#237 ,動態屬性應易於實現。 盡管在Rails控制台中嘗試創建對象時遇到了一些錯誤。 請指教。

我得到的錯誤如下:

ruby-1.9.3-p0 :005 > User.new :username => "johnsmith", :email => "johnsmith@gmail.com", :password => "changethis"
ArgumentError: wrong number of arguments (1 for 0)
    from /Volumes/Terra-Nova/jwaldrip/Sites/theirksome/config/initializers/accessible_attributes.rb:6:in `mass_assignment_authorizer'
    from /Volumes/Terra-Nova/jwaldrip/.rvm/gems/ruby-1.9.3-p0/gems/activemodel-3.1.3/lib/active_model/mass_assignment_security.rb:209:in `sanitize_for_mass_assignment'
    from /Volumes/Terra-Nova/jwaldrip/.rvm/gems/ruby-1.9.3-p0/gems/activerecord-3.1.3/lib/active_record/base.rb:1744:in `assign_attributes'
    from /Volumes/Terra-Nova/jwaldrip/.rvm/gems/ruby-1.9.3-p0/gems/activerecord-3.1.3/lib/active_record/base.rb:1567:in `initialize'
    from (irb):5:in `new'
    from (irb):5
    from /Volumes/Terra-Nova/jwaldrip/.rvm/gems/ruby-1.9.3-p0/gems/railties-3.1.3/lib/rails/commands/console.rb:45:in `start'
    from /Volumes/Terra-Nova/jwaldrip/.rvm/gems/ruby-1.9.3-p0/gems/railties-3.1.3/lib/rails/commands/console.rb:8:in `start'
    from /Volumes/Terra-Nova/jwaldrip/.rvm/gems/ruby-1.9.3-p0/gems/railties-3.1.3/lib/rails/commands.rb:40:in `<top (required)>'
    from script/rails:6:in `require'
    from script/rails:6:in `<main>'

/models/user.rb:

class User < ActiveRecord::Base

    # Attributes
    attr_accessible :username, :email, :password, :password_confirmation, :is_admin
    attr_accessor :password

    # Callbacks
    before_save :encrypt_password

    # Relationships
    has_many :irks

    # Validation
    validates_confirmation_of :password
    validates_presence_of :password, on: :create
    validates :password, presence: true, length: { in: 3..20 }

    validates :username, presence: true, uniqueness: true, length: { in: 3..20 }
    validates :email, presence: true, email: true, uniqueness: true

    # User Authentication
    def self.authenticate(email, password)
        user = find_by_email(email)
        if user && user.password_hash == BCrypt::Engine.hash_secret(password, user.password_salt)
            user
        else
            nil
        end
    end

    # Password Encryption
    def encrypt_password
        if password.present?
            self.password_salt = BCrypt::Engine.generate_salt
            self.password_hash = BCrypt::Engine.hash_secret(password, password_salt)
        end
    end
end

/config/initializers/accessible_attributes.rb:

class ActiveRecord::Base
    attr_accessible
    attr_accessor :accessible

    private

    def mass_assignment_authorizer
        if accessible == :all
            self.class.protected_attributes
        else
            super + (accessible || [])
        end
    end
end

不能完全確定您要執行的操作或此mass_assignment_authorizer的用途是什么。 似乎有更簡單的方法可以防止大規模分配。 話雖如此,我閱讀了railscast的最后幾段 ,似乎您有了這個初始化程序后,創建對象時就無法將任何參數傳遞給初始化程序。 即使可以,也不會設置屬性...

在控制器中,我們還需要將可訪問選項應用於create動作。 如果我們只是像這樣應用它,它將無法正常工作。

@article = Article.new(params[:article])
@article.accessible = :all if admin?

之所以不起作用,是因為新呼叫中發生了批量分配,因此在我們設置可訪問性時為時已晚。 我們需要將創建新文章與分配其屬性分開,並將調用滑動到兩者之間。

因此,在我看來,為了現在為您的一個模型設置屬性,您首先需要創建它,然后在類上將accessibility設置為:all ,然后手動分配所需的屬性,例如:

u = User.create
u.accessible = :all if current_user.is_admin? # or whatever the conditional is for the admin user
u.update_attributes(:username => "johnsmith", :email => "johnsmith@gmail.com", :password => "changethis")

根據需要基於權限需要訪問的屬性數量,最好跳過此模塊,因為它需要執行一些額外的工作。 如果在一個或兩個模型上只有幾個屬性,那么最好使用自己的方法和attr_accessible手動實現此功能。 嘗試閱讀有關紅寶石訪問器的文章 ,看看是否可以在沒有此插件的情況下獲得所需的結果?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM