【问题标题】:String to Serialized Array? (nr. 2)字符串到序列化数组? (编号 2)
【发布时间】:2011-07-19 04:55:36
【问题描述】:

我正在尝试添加一个前置过滤器来操作用户输入:

class FormField < ActiveRecord::Base
  attr_accessible :field_type, :name, :field_options
  serialize :field_options, Array
  before_validation :update_field_options

  def update_field_options
    begin
        self.field_options = self.field_options.split(/\,/).map(&:strip)
      rescue ActiveRecord::SerializationTypeMismatch
        errors.add_to_base("Die Optionen bitte mit Kommata trennen)")
        false
    end
  end
end

当我尝试使用“1,2,3”创建记录时,它不起作用(ActiveRecord::SerializationTypeMismatch)。

迁移是:

t.string :field_options, :null => true

不知道我在这里做错了什么。如果我将之前的过滤器更改为:

self.field_options = [1,2,3]

它有效,似乎我无法访问 self.field_options,但我可以设置它们.....

logger.warn { "field_options #{ self.field_options }" }

不输出任何东西,甚至没有“field_options”,self给我:

类似于:

String to Serialized Array?

Ruby on Rails 3 - Serialize Array Mismatched Class Bafflement

日志:

Started POST "/global/form_fields?format=" for 127.0.0.1 at Sun Mar 20 17:50:00 +0100 2011
  SQL (3.8ms)  describe `shift_categories_users`
  SQL (3.9ms)  describe `roles_users`
  Processing by Global::FormFieldsController#create as 
  Parameters: {"form_field"=>{"name"=>"rails verion", "field_options"=>"1,2,3", "field_type"=>"select"}, "commit"=>"Create Form field", "authenticity_token"=>"nTmPr1H3Ilp6eRqLq/9Gd0JZx7wAw0lHqGlMBEq74HU=", "utf8"=>"✓"}
  User Load (5.0ms)  SELECT `users`.* FROM `users` WHERE `users`.`id` = 261 LIMIT 1
  SQL (0.9ms)  BEGIN
  SQL (0.4ms)  ROLLBACK
  Account Load (1.6ms)  SELECT `accounts`.* FROM `accounts` WHERE `accounts`.`subdomain` = 'expertcloud' LIMIT 1
  ConfigOption Load (1.8ms)  SELECT `config_options`.* FROM `config_options` WHERE `config_options`.`name` = 'headline' AND (`config_options`.account_id = 82) LIMIT 1
DEPRIATION WARNING - make sure you use it in the correct context. user.admin? use user.role?(:admin) insted
DEPRIATION WARNING - make sure you use it in the correct context. user.admin? use user.role?(:admin) insted
  SQL (3.1ms)  describe `roles_users`
  Role Load (2.0ms)  SELECT `roles`.* FROM `roles`
  Role Load (2.0ms)  SELECT * FROM `roles` INNER JOIN `roles_users` ON `roles`.id = `roles_users`.role_id WHERE (`roles_users`.user_id = 261 ) LIMIT 1
Rendered shared/_options.html.haml (73.3ms)
  CACHE (0.0ms)  SELECT `config_options`.* FROM `config_options` WHERE `config_options`.`name` = 'headline' AND (`config_options`.account_id = 82) LIMIT 1
  Role Load (1.2ms)  SELECT `roles`.* FROM `roles` INNER JOIN `roles_users` ON `roles`.id = `roles_users`.role_id WHERE `roles`.`name` = 'admin' AND (`roles_users`.user_id = 261 ) LIMIT 1
  SQL (2.9ms)  describe `shift_categories_users`
  Plan Load (1.8ms)  SELECT `plans`.* FROM `plans` WHERE `plans`.`id` = 4 LIMIT 1
Rendered shared/_navigation.html.haml (179.3ms)
Rendered shared/_header.html.haml (269.9ms)
Rendered shared/_footer.html.haml (1.1ms)
Rendered global/form_fields/new.html.haml within layouts/application (1141.4ms)
Completed 200 OK in 1354ms (Views: 1231.8ms | ActiveRecord: 33.0ms)

编辑 在控制台中:

 FormField.create!(:field_options => "1,2,3")

如果我尝试在模型中调试它:

puts "SPLIT #{ self.field_options }"
puts "SPLIT #{ self.inspect }"

读取self.field_options(即“1,2,3”)时出现错误

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3 serialization activerecord


    【解决方案1】:

    嗯.. 只是尝试一下,也许你的 field_options 应该是二进制类型而不是字符串

    t.binary :field_options, :null => true
    

    【讨论】:

    • mh,不,我仍然得到:FormField.create!(:field_options => "1,2,3") SPLIT # ActiveRecord::SerializationTypeMismatch: field_options 应该是一个数组,但是是一个字符串
    • 但是如果我尝试在 before_validation 回调中访问 *self.field_options" 会抛出错误:puts self.field_options 所以它可能在阅读过程中发生......?
    • 是的,我想是的。试试 FormField.create!(:field_options => [1,2,3]) 看看会发生什么?
    • 按预期工作:=> #(必须添加“如果self.field_options.is_a?(String)" 到 before_validation
    • 仍然不明白为什么它会在读取进度中引发错误。我想我必须在控制器中执行此操作,将字符串拆分为 ruby​​ 数组。
    【解决方案2】:

    您声明 field_options 必须从数组继承。

    serialize :field_options, Array
    

    当您将数组分配给 field_options 时,它会为您序列化数据(在 yaml 中,但这对您来说应该是透明的。)

    你不能:

    self.field_options = "any string"
    

    因为字符串不是数组。如果您必须预处理用户输入的字符串,则需要

    attr_accessible :field_options_str # Rails mass-assign
    attr_accessor   :field_options_str # Ruby
    
    def update_field_options
      self.field_options = self.field_options_str.split(/\,/).map(&:strip)
      # I had to…
      # field_options = field_options_str.split(',').map &:strip
    end
    

    你也可以,

    serialize :field_options # remove Array
    

    然后,rails 会将您的字符串序列化为 yaml 字符串,而 self.field_options 会将其反序列化为 ruby​​ 字符串,允许您对其进行拆分和映射,并存储结果数组。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-20
      • 2017-03-03
      • 1970-01-01
      • 1970-01-01
      • 2016-09-08
      相关资源
      最近更新 更多