Низ към сериализиран масив? (№ 2)

Опитвам се да добавя филтър преди, за да манипулирам въведеното от потребителя:

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 ми дава:

подобен на:

Низ към сериализиран масив?

Ruby on Rails 3 - Сериализиране на несъответстващи класове на масив

Дневник:

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")


person fluxsaas    schedule 20.03.2011    source източник


Отговори (2)


Хммм.. Просто се захващам с това, може би вашите field_options трябва да са от тип binary вместо string

t.binary :field_options, :null => true
person Shiv    schedule 20.03.2011
comment
mh, не, все още получавам: FormField.create!(:field_options =› 1,2,3) SPLIT #‹FormField id: nil, field_type: nil, name: nil, field_options: 1,2,3, стойност: нула, позиция: нула, formable_id: нула, formable_type: нула, account_form_field_id: нула, created_at: нула, updated_at: нула› ActiveRecord::SerializationTypeMismatch: field_options трябваше да да е масив, но е низ - person fluxsaas; 21.03.2011
comment
но грешката се появява, ако се опитам да осъществя достъп до *self.field_options в обратното извикване на before_validation с: puts self.field_options, така че може нещо да се случи по време на четене ..? - person fluxsaas; 21.03.2011
comment
да така мисля. опитайте FormField.create!(:field_options =› [1,2,3]) и вижте какво ще се случи? - person Shiv; 21.03.2011
comment
който работи според очакванията: =› #‹FormField id: 34, field_options: [1, 2, 3], .... › (трябваше да се добави, ако self.field_options.is_a?(String) към преди_валидиране - person fluxsaas; 21.03.2011
comment
все още не разбирам защо извежда грешката в напредъка на четенето. Предполагам, че трябва да го направя в контролера, като разделя низа на рубинен масив. - person fluxsaas; 22.03.2011

Вие декларирате, че 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 ще го десериализира до рубинен низ, позволявайки ви да го разделите и картографирате и да съхраните получения масив.

person whitehat101    schedule 30.01.2013