bitrix_on_rails 0.1.8 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Gemfile +4 -1
- data/Gemfile.lock +9 -4
- data/Guardfile +1 -0
- data/README.rdoc +8 -2
- data/VERSION +1 -1
- data/app/models/iblock.rb +1 -42
- data/app/models/iblock_element.rb +21 -45
- data/bitrix_on_rails.gemspec +19 -13
- data/lib/bitrix_on_rails.rb +12 -6
- data/lib/bitrix_on_rails/active_record.rb +19 -11
- data/lib/bitrix_on_rails/configuration.rb +26 -0
- data/lib/bitrix_on_rails/engine.rb +0 -3
- data/lib/bitrix_on_rails/iblock_element.rb +112 -0
- data/lib/bitrix_on_rails/iblock_element_prop_m.rb +1 -27
- data/lib/bitrix_on_rails/iblock_element_prop_s.rb +111 -102
- data/test/factories.rb +105 -0
- data/test/helper.rb +23 -30
- data/test/schema.rb +5 -1158
- data/test/test_active_record.rb +36 -0
- data/test/test_bitrix_on_rails.rb +14 -9
- data/test/test_iblock_element.rb +77 -0
- data/test/test_iblock_element_prop_s.rb +111 -0
- metadata +45 -41
| @@ -0,0 +1,112 @@ | |
| 1 | 
            +
            module BitrixOnRails
         | 
| 2 | 
            +
             | 
| 3 | 
            +
              # Хранит список созданных классов в виде хеша: iblock_id -> class_name
         | 
| 4 | 
            +
              @@infoblocks = {}
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              def self.infoblocks
         | 
| 7 | 
            +
                @@infoblocks
         | 
| 8 | 
            +
              end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
              def self.define_iblock_class(iblock_id, options = {})
         | 
| 11 | 
            +
                iblock_element_class = create_iblock_class(iblock_id, options[:extended_class], options[:extended_by])
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                unless options[:extended_class]
         | 
| 14 | 
            +
                  # Определяем имя класса, который нужно создать, а также namespace, в котором
         | 
| 15 | 
            +
                  # его нужно создать.
         | 
| 16 | 
            +
                  if class_name = options[:class_name]
         | 
| 17 | 
            +
                    a = class_name.split('::')
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                    class_name = a.last
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                    namespace = a[0..-2].join('::')
         | 
| 22 | 
            +
                    namespace = namespace.empty? ? Object : Object.const_get(namespace)
         | 
| 23 | 
            +
                  else
         | 
| 24 | 
            +
                    class_name = "IblockElement#{iblock_id}"
         | 
| 25 | 
            +
                    namespace  = Object
         | 
| 26 | 
            +
                  end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                  namespace.const_set(class_name, iblock_element_class)
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                create_prop_classes(iblock_id, iblock_element_class)
         | 
| 32 | 
            +
              end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
              protected
         | 
| 35 | 
            +
             | 
| 36 | 
            +
              def self.create_iblock_class(iblock_id, extended_class = nil, extended_by = nil)
         | 
| 37 | 
            +
                iblock_element_class = extended_class || Class.new(::IblockElement) {}
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                iblock_element_class.instance_eval do
         | 
| 40 | 
            +
                  @iblock_id = iblock_id
         | 
| 41 | 
            +
                  @iblock_properties = Iblock.get_properties(iblock_id).inject({}){ |a,e| a[e[1].code] = {:id => e[1].id, :multiple => e[1].multiple == 'Y'}; a}
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                  has_one :property_set, :class_name => "IblockElementPropS#{iblock_id}", :foreign_key => 'iblock_element_id', :autosave => true
         | 
| 44 | 
            +
                  has_many :m_props, :class_name => "IblockElementPropM#{iblock_id}", :foreign_key => 'iblock_element_id', :readonly => true
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                  default_scope where(:iblock_id => iblock_id)
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                  @iblock_properties.each { |m, property|
         | 
| 49 | 
            +
                    delegate m, :to => :property_set
         | 
| 50 | 
            +
                    delegate "#{m}=", :to => :property_set unless property[:multiple]
         | 
| 51 | 
            +
                  }
         | 
| 52 | 
            +
                end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                iblock_element_class.extend Object.const_get(extended_by) if extended_by
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                @@infoblocks[iblock_id] = iblock_element_class
         | 
| 57 | 
            +
             | 
| 58 | 
            +
                iblock_element_class
         | 
| 59 | 
            +
              end
         | 
| 60 | 
            +
             | 
| 61 | 
            +
              def self.create_prop_classes(iblock_id, iblock_element_class)
         | 
| 62 | 
            +
                const_name = "IblockElementPropS#{iblock_id}"
         | 
| 63 | 
            +
                unless Object.const_defined? const_name
         | 
| 64 | 
            +
                  c = Class.new(::ActiveRecord::Base) do
         | 
| 65 | 
            +
                    extend BitrixOnRails::IblockElementPropS
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                    class << self
         | 
| 68 | 
            +
                      # Имя класса, хранящего значения для множественных свойств
         | 
| 69 | 
            +
                      @m_prop_class = nil
         | 
| 70 | 
            +
             | 
| 71 | 
            +
                      # Список множественных свойств
         | 
| 72 | 
            +
                      @m_props = nil
         | 
| 73 | 
            +
             | 
| 74 | 
            +
                      # Список одиночных свойств
         | 
| 75 | 
            +
                      @s_props = nil
         | 
| 76 | 
            +
             | 
| 77 | 
            +
                      def m_prop_class
         | 
| 78 | 
            +
                        Object.const_get(@m_prop_class)
         | 
| 79 | 
            +
                      end
         | 
| 80 | 
            +
             | 
| 81 | 
            +
                      def m_props
         | 
| 82 | 
            +
                        @m_props
         | 
| 83 | 
            +
                      end
         | 
| 84 | 
            +
             | 
| 85 | 
            +
                      def s_props
         | 
| 86 | 
            +
                        @s_props
         | 
| 87 | 
            +
                      end
         | 
| 88 | 
            +
                    end
         | 
| 89 | 
            +
             | 
| 90 | 
            +
                    acts_as_iblock_element_prop_s(iblock_id, iblock_element_class)
         | 
| 91 | 
            +
                  end
         | 
| 92 | 
            +
                  Object.const_set const_name, c
         | 
| 93 | 
            +
                end
         | 
| 94 | 
            +
             | 
| 95 | 
            +
                const_name = "IblockElementPropM#{iblock_id}"
         | 
| 96 | 
            +
                unless Object.const_defined? const_name
         | 
| 97 | 
            +
                  c = Class.new(::ActiveRecord::Base) do
         | 
| 98 | 
            +
                    extend BitrixOnRails::IblockElementPropM
         | 
| 99 | 
            +
                    acts_as_iblock_element_prop_m(iblock_id)
         | 
| 100 | 
            +
                  end
         | 
| 101 | 
            +
                  Object.const_set "IblockElementPropM#{iblock_id}", c
         | 
| 102 | 
            +
                end
         | 
| 103 | 
            +
             | 
| 104 | 
            +
                # Вставляем связи с i_block_element_prop_* на уровень IblockElement. Это может быть полезно
         | 
| 105 | 
            +
                # в том случае, если пользователь получил объект класса IblockElement, а не создаваемого.
         | 
| 106 | 
            +
                # Использование этих связей полностью в компетенции пользователя объекта.
         | 
| 107 | 
            +
                IblockElement.instance_eval do
         | 
| 108 | 
            +
                  has_one  "iblock_element_prop_s#{iblock_id}".to_sym
         | 
| 109 | 
            +
                  has_many "iblock_element_prop_m#{iblock_id}".to_sym
         | 
| 110 | 
            +
                end
         | 
| 111 | 
            +
              end
         | 
| 112 | 
            +
            end
         | 
| @@ -1,56 +1,30 @@ | |
| 1 1 | 
             
            # -*- coding: utf-8 -*-
         | 
| 2 | 
            -
            # -*- coding: utf-8 -*-
         | 
| 3 2 | 
             
            module BitrixOnRails::IblockElementPropM
         | 
| 4 3 | 
             
              def acts_as_iblock_element_prop_m(id)
         | 
| 5 4 | 
             
                extend ClassMethods
         | 
| 6 5 | 
             
                include InstanceMethods
         | 
| 7 6 |  | 
| 8 | 
            -
                # Убираем лишнюю s вконце
         | 
| 9 | 
            -
                #set_table_name 'b_'+table_name.chop
         | 
| 10 7 | 
             
                set_table_name "b_iblock_element_prop_m#{id}"
         | 
| 11 8 |  | 
| 12 | 
            -
                # delegate :code, :to=>:property
         | 
| 13 | 
            -
             | 
| 14 9 | 
             
                belongs_to :iblock_element
         | 
| 15 10 | 
             
                belongs_to :iblock_property
         | 
| 16 11 | 
             
              end
         | 
| 17 12 |  | 
| 18 13 | 
             
              module ClassMethods
         | 
| 19 | 
            -
                def init
         | 
| 20 | 
            -
                  self.to_s=~/(\d+)/
         | 
| 21 | 
            -
                  iblock_id = $1.to_i
         | 
| 22 | 
            -
                  IblockElement.send :has_many, "iblock_element_prop_m#{iblock_id}".to_sym, :class_name=>"::IblockElementPropM#{iblock_id}"
         | 
| 23 | 
            -
                end
         | 
| 24 14 | 
             
              end
         | 
| 25 15 |  | 
| 26 16 | 
             
              module InstanceMethods
         | 
| 27 | 
            -
             | 
| 28 17 | 
             
                def property
         | 
| 29 18 | 
             
                  # Достаем кешированный вариант
         | 
| 30 19 | 
             
                  IblockProperty.find(iblock_property_id)
         | 
| 31 20 | 
             
                end
         | 
| 32 21 |  | 
| 33 22 | 
             
                def code
         | 
| 34 | 
            -
                  @code||=property.code
         | 
| 35 | 
            -
                end
         | 
| 36 | 
            -
             | 
| 37 | 
            -
                def get_value
         | 
| 38 | 
            -
                  case property.property_type
         | 
| 39 | 
            -
                  when 'S'     # String
         | 
| 40 | 
            -
                    self.value
         | 
| 41 | 
            -
                  when 'N'     # Numeric
         | 
| 42 | 
            -
                    self.value_num.to_i  # Когда BigDecimal - не приятно
         | 
| 43 | 
            -
                    # when 'E'     # Enum?
         | 
| 44 | 
            -
                    # self.value_enum
         | 
| 45 | 
            -
                    # when 'L'     # WTF?
         | 
| 46 | 
            -
                  else
         | 
| 47 | 
            -
                    raise "Не установленный тип (#{iblock_property.property_type}) свойства (#{self.class} #{id})"
         | 
| 48 | 
            -
                  end
         | 
| 23 | 
            +
                  @code ||= property.code
         | 
| 49 24 | 
             
                end
         | 
| 50 25 | 
             
              end
         | 
| 51 26 | 
             
            end
         | 
| 52 27 |  | 
| 53 | 
            -
             | 
| 54 28 | 
             
            # Table b_iblock_element_prop_m7
         | 
| 55 29 | 
             
            # ==============================
         | 
| 56 30 | 
             
            # ID, IBLOCK_ELEMENT_ID, IBLOCK_PROPERTY_ID, VALUE, VALUE_ENUM, VALUE_NUM, DESCRIPTION
         | 
| @@ -1,132 +1,141 @@ | |
| 1 1 | 
             
            # -*- coding: utf-8 -*-
         | 
| 2 2 | 
             
            module BitrixOnRails::IblockElementPropS
         | 
| 3 | 
            -
              def acts_as_iblock_element_prop_s(id)
         | 
| 4 | 
            -
                extend ClassMethods
         | 
| 5 | 
            -
                include InstanceMethods
         | 
| 6 | 
            -
             | 
| 7 | 
            -
                # Убираем лишнюю s вконце
         | 
| 8 | 
            -
                #set_table_name 'b_'+table_name.chop
         | 
| 9 | 
            -
                set_table_name "b_iblock_element_prop_s#{id}"
         | 
| 10 3 |  | 
| 11 | 
            -
             | 
| 4 | 
            +
              class MPropValuesWrapper
         | 
| 5 | 
            +
                attr_reader :iblock_element_id, :iblock_property_id
         | 
| 12 6 |  | 
| 13 | 
            -
                 | 
| 14 | 
            -
             | 
| 7 | 
            +
                def initialize(iblock_element_id, iblock_property_id, m_prop_class)
         | 
| 8 | 
            +
                  @iblock_element_id = iblock_element_id
         | 
| 9 | 
            +
                  @iblock_property_id = iblock_property_id
         | 
| 15 10 |  | 
| 16 | 
            -
             | 
| 17 | 
            -
                 | 
| 11 | 
            +
                  @m_prop_class = m_prop_class
         | 
| 12 | 
            +
                end
         | 
| 18 13 |  | 
| 19 | 
            -
                 | 
| 20 | 
            -
                   | 
| 14 | 
            +
                def values
         | 
| 15 | 
            +
                  @m_prop_class.where(
         | 
| 16 | 
            +
                    :iblock_element_id => @iblock_element_id,
         | 
| 17 | 
            +
                    :iblock_property_id => @iblock_property_id
         | 
| 18 | 
            +
                  ).collect { |e| e.value }
         | 
| 21 19 | 
             
                end
         | 
| 22 20 |  | 
| 23 | 
            -
                 | 
| 24 | 
            -
                   | 
| 25 | 
            -
                     | 
| 26 | 
            -
                     | 
| 27 | 
            -
             | 
| 21 | 
            +
                def add(value)
         | 
| 22 | 
            +
                  @m_prop_class.create(
         | 
| 23 | 
            +
                    :iblock_element_id => @iblock_element_id,
         | 
| 24 | 
            +
                    :iblock_property_id => @iblock_property_id,
         | 
| 25 | 
            +
                    :value => value)
         | 
| 28 26 | 
             
                end
         | 
| 29 27 |  | 
| 28 | 
            +
                def remove(value)
         | 
| 29 | 
            +
                  m_props = @m_prop_class.where(
         | 
| 30 | 
            +
                    :iblock_element_id => @iblock_element_id,
         | 
| 31 | 
            +
                    :iblock_property_id => @iblock_property_id,
         | 
| 32 | 
            +
                    :value => value)
         | 
| 33 | 
            +
                  m_props.each { |p| p.destroy } if m_props.any?
         | 
| 34 | 
            +
                end
         | 
| 30 35 | 
             
              end
         | 
| 31 36 |  | 
| 32 | 
            -
              def  | 
| 33 | 
            -
                 | 
| 34 | 
            -
             | 
| 37 | 
            +
              def acts_as_iblock_element_prop_s(iblock_id, iblock_element_class)
         | 
| 38 | 
            +
                extend ClassMethods
         | 
| 39 | 
            +
                include InstanceMethods
         | 
| 35 40 |  | 
| 36 | 
            -
             | 
| 41 | 
            +
                @m_prop_class = "IblockElementPropM#{iblock_id}"
         | 
| 42 | 
            +
                @m_props = {}
         | 
| 43 | 
            +
                @s_props = {}
         | 
| 37 44 |  | 
| 45 | 
            +
                Iblock.get_properties(iblock_id).select { |k,e|
         | 
| 46 | 
            +
                  if e.multiple == 'Y'
         | 
| 47 | 
            +
                    @m_props[e.code] = {:id => e.id, :type => e.property_type, :user_type => e.user_type}
         | 
| 48 | 
            +
                  else
         | 
| 49 | 
            +
                    @s_props[e.code] = {:id => e.id, :type => e.property_type, :user_type => e.user_type}
         | 
| 50 | 
            +
                  end
         | 
| 51 | 
            +
                }
         | 
| 38 52 |  | 
| 39 | 
            -
                 | 
| 40 | 
            -
                  # @m_prop_class = "IblockElementPropM#{id}"
         | 
| 41 | 
            -
                  # Название свойства сохраняется только для наглядности, чтобы можно было через консоль понять
         | 
| 42 | 
            -
                  # что за свойство.
         | 
| 43 | 
            -
                  @m_props ||= Iblock.get_properties(iblock_id).select { |k,e| e.multiple == 'Y' }
         | 
| 44 | 
            -
                end
         | 
| 53 | 
            +
                set_table_name "b_iblock_element_prop_s#{iblock_id}"
         | 
| 45 54 |  | 
| 46 | 
            -
                 | 
| 47 | 
            -
                # name - русское описание
         | 
| 48 | 
            -
             | 
| 49 | 
            -
                # Дальше идут пары:
         | 
| 50 | 
            -
                # property_120
         | 
| 51 | 
            -
                # description_120
         | 
| 52 | 
            -
                # ..
         | 
| 53 | 
            -
                # определяются они в iblock.iblock_properties
         | 
| 54 | 
            -
             | 
| 55 | 
            -
                # Берем список свойств из таблицы iblock_properties
         | 
| 56 | 
            -
                # и создаем такие же методы для опроса и установки, чтобы можно было использовать
         | 
| 57 | 
            -
                # их напрямую:
         | 
| 58 | 
            -
                #
         | 
| 59 | 
            -
                #   self.кодовое_имя_свойства
         | 
| 60 | 
            -
                #
         | 
| 61 | 
            -
                #   Например:
         | 
| 62 | 
            -
                #
         | 
| 63 | 
            -
                #   self.post_id вместо self.property_120
         | 
| 64 | 
            -
                #
         | 
| 65 | 
            -
             | 
| 66 | 
            -
                def iblock_id
         | 
| 67 | 
            -
                  self.name=~/(\d+)/
         | 
| 68 | 
            -
                  $1.to_i
         | 
| 69 | 
            -
                end
         | 
| 55 | 
            +
                belongs_to :iblock_element, :class_name => iblock_element_class.name
         | 
| 70 56 |  | 
| 71 | 
            -
                 | 
| 72 | 
            -
             | 
| 73 | 
            -
             | 
| 74 | 
            -
             | 
| 75 | 
            -
                  IblockElement.send :has_one, "iblock_element_prop_s#{iblock_id}".to_sym, :class_name=>Iblock.s_props_class(iblock_id).name, :autosave => true
         | 
| 76 | 
            -
             | 
| 77 | 
            -
                  self.properties = {}
         | 
| 78 | 
            -
                  attribute_names.select {|a| a[0,4]=='prop' }.each do |name|
         | 
| 79 | 
            -
                    prop_id = name.slice(9,5).to_i
         | 
| 80 | 
            -
                    iblock_property = IblockProperty.find(prop_id)
         | 
| 81 | 
            -
                    code = iblock_property.code.downcase.to_sym
         | 
| 82 | 
            -
                    self.properties[code] = name
         | 
| 83 | 
            -
                    define_method code do
         | 
| 84 | 
            -
                      val = send name
         | 
| 85 | 
            -
                      return val.to_i if val.is_a?(BigDecimal)
         | 
| 86 | 
            -
             | 
| 87 | 
            -
                      # Вот так мы проверяем сериализацию
         | 
| 88 | 
            -
                      # Есть еще вариант что поле сериализовано если  iblock_property.user_type=='HTML'
         | 
| 89 | 
            -
                      #
         | 
| 90 | 
            -
                      if val.is_a? String and val.length>5 and val[0,3]=~/[a-z]:\d/
         | 
| 91 | 
            -
                        res = PHP.unserialize(val)
         | 
| 92 | 
            -
                        # res = PhpSerialization.load(val)
         | 
| 93 | 
            -
                        return iblock_property.property_type=='S' && res.is_a?(Hash) && res.include?('TEXT') ? res['TEXT'] : res
         | 
| 94 | 
            -
                      end
         | 
| 95 | 
            -
                      val
         | 
| 96 | 
            -
                    end
         | 
| 97 | 
            -
                    define_method "#{code}=" do |val|
         | 
| 98 | 
            -
                      send "#{name}=", val
         | 
| 99 | 
            -
                    end
         | 
| 100 | 
            -
                    eval "def self.find_by_#{code}(val); find_by_#{name}(val); end"
         | 
| 57 | 
            +
                @s_props.each { |code, property|
         | 
| 58 | 
            +
                  define_method(code) do
         | 
| 59 | 
            +
                    value = send "property_#{property[:id]}"
         | 
| 60 | 
            +
                    unserialize value, property[:type], property[:user_type]
         | 
| 101 61 | 
             
                  end
         | 
| 102 | 
            -
                end
         | 
| 103 | 
            -
              end
         | 
| 104 62 |  | 
| 105 | 
            -
             | 
| 63 | 
            +
                  define_method("#{code}=") do |val|
         | 
| 64 | 
            +
                    send "property_#{property[:id]}=", serialize(val, property[:type], property[:user_type])
         | 
| 65 | 
            +
                  end
         | 
| 106 66 |  | 
| 107 | 
            -
             | 
| 108 | 
            -
             | 
| 109 | 
            -
                   | 
| 110 | 
            -
                 | 
| 67 | 
            +
                  define_method "find_by_#{code}" do |val|
         | 
| 68 | 
            +
                    send "find_by_property#{property[:id]}", serialize(val, property[:type], property[:user_type])
         | 
| 69 | 
            +
                  end
         | 
| 70 | 
            +
                }
         | 
| 111 71 |  | 
| 112 | 
            -
                 | 
| 113 | 
            -
             | 
| 114 | 
            -
             | 
| 115 | 
            -
             | 
| 116 | 
            -
                   | 
| 72 | 
            +
                @m_props.each { |code, property|
         | 
| 73 | 
            +
                  define_method(code) do
         | 
| 74 | 
            +
                    instance_variable_get("@m_prop_#{property[:id]}".to_sym) ||
         | 
| 75 | 
            +
                    instance_variable_set("@m_prop_#{property[:id]}".to_sym, MPropValuesWrapper.new(self.iblock_element_id, property[:id], m_prop_class))
         | 
| 76 | 
            +
                  end
         | 
| 77 | 
            +
                }
         | 
| 78 | 
            +
             | 
| 79 | 
            +
                before_save do
         | 
| 80 | 
            +
                  self.class.m_props.each { |code, p|
         | 
| 81 | 
            +
                    values = send(code).values
         | 
| 82 | 
            +
                    self.send("property_#{p[:id]}=", ::PHP.serialize({'VALUE' => values, 'DESCRIPTION' => Array.new(values.size, nil)}))
         | 
| 83 | 
            +
                  }
         | 
| 117 84 | 
             
                end
         | 
| 85 | 
            +
              end
         | 
| 118 86 |  | 
| 119 | 
            -
             | 
| 120 | 
            -
             | 
| 87 | 
            +
              module ClassMethods
         | 
| 88 | 
            +
              end
         | 
| 89 | 
            +
             | 
| 90 | 
            +
              module InstanceMethods
         | 
| 91 | 
            +
                def m_prop_class
         | 
| 92 | 
            +
                  self.class.m_prop_class
         | 
| 121 93 | 
             
                end
         | 
| 122 94 |  | 
| 123 | 
            -
                 | 
| 124 | 
            -
             | 
| 95 | 
            +
                # Возможные значения для типов свойств:
         | 
| 96 | 
            +
                # * S - строка
         | 
| 97 | 
            +
                # * N - число
         | 
| 98 | 
            +
                # * F - файл
         | 
| 99 | 
            +
                # * L - список
         | 
| 100 | 
            +
                # * E - привязка к элементам
         | 
| 101 | 
            +
                # * G - привязка к группам.
         | 
| 102 | 
            +
                def unserialize(value, type, user_type = nil)
         | 
| 103 | 
            +
                  return nil unless value
         | 
| 104 | 
            +
             | 
| 105 | 
            +
                  case type
         | 
| 106 | 
            +
                    when 'N'
         | 
| 107 | 
            +
                      value.is_a?(BigDecimal) ? value.to_i : value
         | 
| 108 | 
            +
                    when 'S'
         | 
| 109 | 
            +
                      if value.length > 5 && value[0..3] =~ /[a-z]:\d/
         | 
| 110 | 
            +
                        v = ::PHP.unserialize(value)
         | 
| 111 | 
            +
                        v.is_a?(Hash) && v.include?('TEXT') ? v['TEXT'] : value
         | 
| 112 | 
            +
                      elsif user_type == 'DateTime'
         | 
| 113 | 
            +
                        Time.parse(value).in_time_zone
         | 
| 114 | 
            +
                      else
         | 
| 115 | 
            +
                        value
         | 
| 116 | 
            +
                      end
         | 
| 117 | 
            +
                      when 'L' # id из таблицы b_iblock_property_enum
         | 
| 118 | 
            +
                        value
         | 
| 119 | 
            +
                    else
         | 
| 120 | 
            +
                      value
         | 
| 121 | 
            +
                  end
         | 
| 125 122 | 
             
                end
         | 
| 126 123 |  | 
| 127 | 
            -
                def  | 
| 128 | 
            -
                   | 
| 129 | 
            -
                   | 
| 124 | 
            +
                def serialize(value, type, user_type = nil)
         | 
| 125 | 
            +
                  case type
         | 
| 126 | 
            +
                  when 'S'
         | 
| 127 | 
            +
                    if user_type == 'HTML'
         | 
| 128 | 
            +
                      ::PHP.serialize({'TEXT' => value, 'TYPE' => 'html'})
         | 
| 129 | 
            +
                    elsif user_type == 'DateTime'
         | 
| 130 | 
            +
                      value.strftime('%Y-%m-%d %H:%M:%S')
         | 
| 131 | 
            +
                    else
         | 
| 132 | 
            +
                      # Это делается потому, что пользователь может хранить в строках не только
         | 
| 133 | 
            +
                      # строковые значения.
         | 
| 134 | 
            +
                      value.to_s
         | 
| 135 | 
            +
                    end
         | 
| 136 | 
            +
                  else
         | 
| 137 | 
            +
                    value
         | 
| 138 | 
            +
                  end
         | 
| 130 139 | 
             
                end
         | 
| 131 140 | 
             
              end
         | 
| 132 141 | 
             
            end
         | 
    
        data/test/factories.rb
    ADDED
    
    | @@ -0,0 +1,105 @@ | |
| 1 | 
            +
            # -*- coding: utf-8 -*-
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            FactoryGirl.define do
         | 
| 4 | 
            +
              factory :iblock_type
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              factory :iblock do
         | 
| 7 | 
            +
                version 2
         | 
| 8 | 
            +
                timestamp_x Time.now
         | 
| 9 | 
            +
                name 'имя инфоблока'
         | 
| 10 | 
            +
                lid 'lid'
         | 
| 11 | 
            +
                association :iblock_type
         | 
| 12 | 
            +
              end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
              factory :iblock_property do
         | 
| 15 | 
            +
                timestamp_x Time.now
         | 
| 16 | 
            +
              end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
              factory :iblock_element do
         | 
| 19 | 
            +
              end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
              #
         | 
| 22 | 
            +
              # Инфоблок 3
         | 
| 23 | 
            +
              #
         | 
| 24 | 
            +
             | 
| 25 | 
            +
              factory :iblock3, :parent=>:iblock do
         | 
| 26 | 
            +
                name 'Свойства поста'
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                after_build { |iblock|
         | 
| 29 | 
            +
                  iblock.iblock_properties.build  Factory.build(:iblock3_s_prop_post_id).attributes
         | 
| 30 | 
            +
                  iblock.iblock_properties.build  Factory.build(:iblock3_s_prop_preview_mpage).attributes
         | 
| 31 | 
            +
                  iblock.iblock_properties.build  Factory.build(:iblock3_s_prop_publication_date).attributes
         | 
| 32 | 
            +
                  iblock.iblock_properties.build  Factory.build(:iblock3_m_prop_glob_clas).attributes
         | 
| 33 | 
            +
                }
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                after_create { |iblock|
         | 
| 36 | 
            +
                  connection = ActiveRecord::Base.connection
         | 
| 37 | 
            +
                  connection.create_table "b_iblock_element_prop_s#{iblock.id}".to_sym, :id => false do |t|
         | 
| 38 | 
            +
                    t.integer :iblock_element_id
         | 
| 39 | 
            +
                    iblock.iblock_properties.each { |property|
         | 
| 40 | 
            +
                      type = case property.property_type
         | 
| 41 | 
            +
                             when 'N' then :integer
         | 
| 42 | 
            +
                             when 'S' then :string
         | 
| 43 | 
            +
                             when 'L' then :integer
         | 
| 44 | 
            +
                             end
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                      t.send type, "property_#{property.id}".to_sym
         | 
| 47 | 
            +
                      t.string "description_#{property.id}"
         | 
| 48 | 
            +
                    }
         | 
| 49 | 
            +
                  end
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                  connection.create_table "b_iblock_element_prop_m#{iblock.id}".to_sym do |t|
         | 
| 52 | 
            +
                    t.integer :iblock_element_id
         | 
| 53 | 
            +
                    t.integer :iblock_property_id
         | 
| 54 | 
            +
                    t.integer :value
         | 
| 55 | 
            +
                    t.string :description
         | 
| 56 | 
            +
                  end
         | 
| 57 | 
            +
                }
         | 
| 58 | 
            +
              end
         | 
| 59 | 
            +
             | 
| 60 | 
            +
              factory :iblock3_s_prop_post_id, :parent => :iblock_property do
         | 
| 61 | 
            +
                name 'ID поста'
         | 
| 62 | 
            +
                code 'POST_ID'
         | 
| 63 | 
            +
                property_type 'N'
         | 
| 64 | 
            +
                multiple 'N'
         | 
| 65 | 
            +
              end
         | 
| 66 | 
            +
             | 
| 67 | 
            +
              factory :iblock3_s_prop_preview_mpage, :parent => :iblock_property do
         | 
| 68 | 
            +
                name 'Анонс для главной'
         | 
| 69 | 
            +
                code 'PREVIEW_MPAGE'
         | 
| 70 | 
            +
                property_type 'S'
         | 
| 71 | 
            +
                multiple 'N'
         | 
| 72 | 
            +
                user_type 'HTML'
         | 
| 73 | 
            +
              end
         | 
| 74 | 
            +
             | 
| 75 | 
            +
              factory :iblock3_s_prop_publication_date, :parent => :iblock_property do
         | 
| 76 | 
            +
                name 'Дата публикации'
         | 
| 77 | 
            +
                code 'PUBLICATION_DATE'
         | 
| 78 | 
            +
                property_type 'S'
         | 
| 79 | 
            +
                multiple 'N'
         | 
| 80 | 
            +
                user_type 'DateTime'
         | 
| 81 | 
            +
              end
         | 
| 82 | 
            +
             | 
| 83 | 
            +
              factory :iblock3_m_prop_glob_clas, :parent => :iblock_property do
         | 
| 84 | 
            +
                name 'Глобальный классификатор'
         | 
| 85 | 
            +
                code 'GLOB_CLASS'
         | 
| 86 | 
            +
                property_type 'S'
         | 
| 87 | 
            +
                multiple 'Y'
         | 
| 88 | 
            +
              end
         | 
| 89 | 
            +
             | 
| 90 | 
            +
              factory :iblock_element3, :parent => :iblock_element do
         | 
| 91 | 
            +
                name ''
         | 
| 92 | 
            +
              end
         | 
| 93 | 
            +
             | 
| 94 | 
            +
              #
         | 
| 95 | 
            +
              # Инфоблок 7
         | 
| 96 | 
            +
              #
         | 
| 97 | 
            +
             | 
| 98 | 
            +
              factory :iblock7, :parent=>:iblock do
         | 
| 99 | 
            +
                id 7
         | 
| 100 | 
            +
              end
         | 
| 101 | 
            +
             | 
| 102 | 
            +
              factory :iblock_element7, :parent => :iblock_element do
         | 
| 103 | 
            +
                association :iblock, :factory=>:iblock7
         | 
| 104 | 
            +
              end
         | 
| 105 | 
            +
            end
         |