使用强参数和设计更新OpenStruct字段

时间:2015-08-03 20:12:44

标签: ruby-on-rails ruby-on-rails-4 devise

尝试添加:首选项以设计强参数

from sqlalchemy.sql import text
cmd = "SELECT * FROM information_schema.columns WHERE table_schema = :db ORDER BY table_name,ordinal_position"
result = session.execute(
            text(cmd),
            {"db": "classicmodels"}
        )
result.fetchall()

生成错误

preferences: [:gender, :location, :website, :aim, :interests]) 

添加:首选项只是

Attribute was supposed to be a OpenStruct, but was a ActionController::Parameters. -- {"gender"=>"No", "location"=>"", "website"=>"", "aim"=>"", "interests"=>""}

不会抛出任何错误,但在提交表单时不会更新任何键值对。以下字段:首选项,例如:email和:password,可以正确更新。

我已完成谷歌搜索,但无法找出在强参数消毒剂中指示嵌套OpenStruct的格式。

记录器输出确认:首选项未被允许。

控制器/ application_controller

:preferences

模型/用户

class ApplicationController < ActionController::Base
  before_action :configure_permitted_parameters, if: :devise_controller?

  [snip]

  def configure_permitted_parameters
    devise_parameter_sanitizer.for(:sign_up) { 
        [snip]
    }
    devise_parameter_sanitizer.for(:account_update) { 
        |u| u.permit(:name, :email,
                     :password, :password_confirmation, :current_password,
                     preferences: [:gender, :location, :website, :aim, :interests]) 
    }
  end

视图/设计/注册/ _form

class User < ActiveRecord::Base
  serialize :preferences, OpenStruct
  after_create :default_preferences

  def default_preferences
    self.preferences.gender = ''
    self.preferences.location = ''
    self.preferences.website = ''
    [snip etc.]
  end

1 个答案:

答案 0 :(得分:1)

您应该能够覆盖要转换为预期类型的​​偏好分配:

class User < ActiveRecord::Base
  …
  def preferences=(val)
    return super if val.is_a? OpenStruct
    super OpenStruct.new val.to_h if val
  end
end

如果该值已经是OpenStruct,则此代码将调用原始settor方法,否则将尝试在将该哈希值转换为OpenStruct之前将值转换为哈希值。请注意,如果无法将值转换为哈希值,则会引发错误。

我认为这是最好的解决方案,因为将serialize类型指定为OpenStruct意味着指定的值应始终OpenStruct的实例,并且这段代码将确保。