coaster 0.4.7 → 0.5.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.
- checksums.yaml +4 -4
- data/lib/coaster/core_ext/array.rb +11 -0
- data/lib/coaster/core_ext/date.rb +5 -0
- data/lib/coaster/core_ext/month.rb +108 -0
- data/lib/coaster/core_ext.rb +3 -0
- data/lib/coaster/serialized_properties.rb +193 -0
- data/lib/coaster/version.rb +1 -1
- metadata +20 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 3f3443395e8b26f474e4d170c1dd1e3edea41cf9
         | 
| 4 | 
            +
              data.tar.gz: 482a7957080674361a16c29a6284e7f819c8248e
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 27ff86f49682b3bfc97c2e9f335fb1a01921b524541b7d7c5f11c283f5bd6afb50a798bcfa4748d4bbf4c457707705e2826f2c5fd4d4c431017c7f4e02bb5eb3
         | 
| 7 | 
            +
              data.tar.gz: a109aefbd31130b58d721a92a365f3b726b4afe0854ef7a4b94872545f20332fe6f589629eb6d1952f474f30891b79d93c894204a5df503977e1b29fafac3bf7
         | 
| @@ -0,0 +1,108 @@ | |
| 1 | 
            +
            require 'attr_extras'  # gem
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            class Month
         | 
| 4 | 
            +
              vattr_initialize :year, :month
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              class << self
         | 
| 7 | 
            +
                def from(object)
         | 
| 8 | 
            +
                  case object
         | 
| 9 | 
            +
                    when Month then object
         | 
| 10 | 
            +
                    when String then Month.parse(object)
         | 
| 11 | 
            +
                    when Array then Month.new(object[0], object[1])
         | 
| 12 | 
            +
                    else new(object.year, object.month)
         | 
| 13 | 
            +
                  end
         | 
| 14 | 
            +
                end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                # Month.parse('201601')
         | 
| 17 | 
            +
                # Month.parse('2016-01')
         | 
| 18 | 
            +
                def parse(str)
         | 
| 19 | 
            +
                  date = Date.parse(str)
         | 
| 20 | 
            +
                  from(date)
         | 
| 21 | 
            +
                rescue ArgumentError => e
         | 
| 22 | 
            +
                  if str.instance_variable_get(:@_gsub_)
         | 
| 23 | 
            +
                    raise e, str: str.instance_variable_get(:@_gsub_)
         | 
| 24 | 
            +
                  elsif e.message != 'invalid date'
         | 
| 25 | 
            +
                    raise e, str: str
         | 
| 26 | 
            +
                  end
         | 
| 27 | 
            +
                  str_gsub = str.gsub(/[^\d]/, '')
         | 
| 28 | 
            +
                  str_gsub.insert(4, '0') if str_gsub.length == 5
         | 
| 29 | 
            +
                  str_gsub += '01'
         | 
| 30 | 
            +
                  str_gsub.instance_variable_set(:@_gsub_, str_gsub)
         | 
| 31 | 
            +
                  parse(str_gsub)
         | 
| 32 | 
            +
                end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                def current
         | 
| 35 | 
            +
                  from(Date.current)
         | 
| 36 | 
            +
                end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                def now
         | 
| 39 | 
            +
                  from(Time.zone.now)
         | 
| 40 | 
            +
                end
         | 
| 41 | 
            +
              end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
              def year
         | 
| 44 | 
            +
                Integer(@year)
         | 
| 45 | 
            +
              end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
              def month
         | 
| 48 | 
            +
                Integer(@month)
         | 
| 49 | 
            +
              end
         | 
| 50 | 
            +
             | 
| 51 | 
            +
              def first_date
         | 
| 52 | 
            +
                Date.new(year, month, 1)
         | 
| 53 | 
            +
              end
         | 
| 54 | 
            +
             | 
| 55 | 
            +
              def last_date
         | 
| 56 | 
            +
                Date.new(year, month, -1)
         | 
| 57 | 
            +
              end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
              def first_day
         | 
| 60 | 
            +
                first_date.day
         | 
| 61 | 
            +
              end
         | 
| 62 | 
            +
             | 
| 63 | 
            +
              def last_day
         | 
| 64 | 
            +
                last_date.day
         | 
| 65 | 
            +
              end
         | 
| 66 | 
            +
             | 
| 67 | 
            +
              def beginning_of_month
         | 
| 68 | 
            +
                first_date.beginning_of_day
         | 
| 69 | 
            +
              end
         | 
| 70 | 
            +
             | 
| 71 | 
            +
              def end_of_month
         | 
| 72 | 
            +
                last_date.end_of_day
         | 
| 73 | 
            +
              end
         | 
| 74 | 
            +
             | 
| 75 | 
            +
              def date_for_day(number)
         | 
| 76 | 
            +
                Date.new(year, month, number)
         | 
| 77 | 
            +
              end
         | 
| 78 | 
            +
             | 
| 79 | 
            +
              def to_time_range
         | 
| 80 | 
            +
                beginning_of_month...(later.beginning_of_month)
         | 
| 81 | 
            +
              end
         | 
| 82 | 
            +
             | 
| 83 | 
            +
              def previous
         | 
| 84 | 
            +
                self.class.from(first_date - 1)
         | 
| 85 | 
            +
              end
         | 
| 86 | 
            +
             | 
| 87 | 
            +
              def later
         | 
| 88 | 
            +
                self.class.from(last_date + 1)
         | 
| 89 | 
            +
              end
         | 
| 90 | 
            +
             | 
| 91 | 
            +
              def to_s
         | 
| 92 | 
            +
                "#{year}-#{month}"
         | 
| 93 | 
            +
              end
         | 
| 94 | 
            +
              alias_method :inspect, :to_s
         | 
| 95 | 
            +
             | 
| 96 | 
            +
              def -(time)
         | 
| 97 | 
            +
                first_date - time
         | 
| 98 | 
            +
              end
         | 
| 99 | 
            +
             | 
| 100 | 
            +
              def +(time)
         | 
| 101 | 
            +
                first_date + time
         | 
| 102 | 
            +
              end
         | 
| 103 | 
            +
             | 
| 104 | 
            +
              include Comparable
         | 
| 105 | 
            +
              def <=>(other)
         | 
| 106 | 
            +
                first_date <=> Month.from(other).first_date
         | 
| 107 | 
            +
              end
         | 
| 108 | 
            +
            end
         | 
    
        data/lib/coaster/core_ext.rb
    CHANGED
    
    
| @@ -0,0 +1,193 @@ | |
| 1 | 
            +
            module Coaster
         | 
| 2 | 
            +
              module SerializedProperties
         | 
| 3 | 
            +
                class DuplicatedProperty < StandardError; end
         | 
| 4 | 
            +
                class InvalidProperty < StandardError; end
         | 
| 5 | 
            +
             | 
| 6 | 
            +
                def serialized_property_settings
         | 
| 7 | 
            +
                  @serialized_property_settings ||= {}
         | 
| 8 | 
            +
                end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                def serialized_property_setting(key)
         | 
| 11 | 
            +
                  serialized_property_settings[key.to_sym]
         | 
| 12 | 
            +
                end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                def serialized_column(serialize_column)
         | 
| 15 | 
            +
                  define_method serialize_column.to_sym do
         | 
| 16 | 
            +
                    return read_attribute(serialize_column.to_sym) if read_attribute(serialize_column.to_sym)
         | 
| 17 | 
            +
                    write_attribute(serialize_column.to_sym, {})
         | 
| 18 | 
            +
                    read_attribute(serialize_column)
         | 
| 19 | 
            +
                  end
         | 
| 20 | 
            +
                end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                def serialized_property_comment(key)
         | 
| 23 | 
            +
                  cm = serialized_property_settings[key.to_sym] &&
         | 
| 24 | 
            +
                       serialized_property_settings[key.to_sym][:comment]
         | 
| 25 | 
            +
                  cm || key.to_s
         | 
| 26 | 
            +
                end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                def serialized_property(serialize_column, key, type: nil, comment: nil, getter: nil, setter: nil, setter_callback: nil, default: nil)
         | 
| 29 | 
            +
                  raise DuplicatedProperty, "#{self.name}##{key} duplicated\n#{caller[0..5].join("\n")}" if serialized_property_settings[key.to_sym]
         | 
| 30 | 
            +
                  serialized_property_settings[key.to_sym] = {type: type, comment: comment, getter: getter, setter: setter, setter_callback: setter_callback, default: default}
         | 
| 31 | 
            +
                  _typed_serialized_property(serialize_column, key, type: type, getter: getter, setter: setter, setter_callback: setter_callback, default: default)
         | 
| 32 | 
            +
                end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                def serialized_properties(serialize_column, *keys, type: nil, getter: nil, setter: nil, setter_callback: nil, default: nil)
         | 
| 35 | 
            +
                  keys.flatten.each do |key|
         | 
| 36 | 
            +
                    key_name = key
         | 
| 37 | 
            +
                    prop_hash = {type: type, getter: getter, setter: setter, setter_callback: setter_callback, default: default}
         | 
| 38 | 
            +
                    if key.is_a? Hash
         | 
| 39 | 
            +
                      key_name = key[:key]
         | 
| 40 | 
            +
                      prop_hash = {type: type, getter: getter, setter: setter, setter_callback: setter_callback, default: default}.merge(key)
         | 
| 41 | 
            +
                      prop_hash.delete(:key)
         | 
| 42 | 
            +
                    end
         | 
| 43 | 
            +
                    serialized_property(serialize_column, key_name, prop_hash)
         | 
| 44 | 
            +
                  end
         | 
| 45 | 
            +
                end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                private
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                def _typed_serialized_property(serialize_column, key, type: nil, getter: nil, setter: nil, setter_callback: nil, default: nil)
         | 
| 50 | 
            +
                  case type
         | 
| 51 | 
            +
                    when String then
         | 
| 52 | 
            +
                      # String은 나중에 eval해서 가져옴,
         | 
| 53 | 
            +
                      # type에서 다른 객체를 참조할 경우, 순환참조가 발생할 수 있기 때문에
         | 
| 54 | 
            +
                      Rails.configuration.after_initialize {
         | 
| 55 | 
            +
                        if type.is_a?(String)
         | 
| 56 | 
            +
                          begin
         | 
| 57 | 
            +
                            type = eval(type)
         | 
| 58 | 
            +
                            raise InvalidProperty, "#{self.name}##{key} type string is return string #{type}" if type.is_a?(String)
         | 
| 59 | 
            +
                          rescue InvalidProperty => e
         | 
| 60 | 
            +
                            raise
         | 
| 61 | 
            +
                          rescue => e
         | 
| 62 | 
            +
                            raise InvalidProperty, "#{self.name}##{key} eval failed: type:[#{type}] [#{e.class.name}] #{e.message}"
         | 
| 63 | 
            +
                          end
         | 
| 64 | 
            +
                          serialized_property_setting(key.to_sym)[:type] = type
         | 
| 65 | 
            +
                          _typed_serialized_property serialize_column, key, type: type, getter: getter, setter: setter, setter_callback: setter_callback, default: default
         | 
| 66 | 
            +
                        end
         | 
| 67 | 
            +
                      }
         | 
| 68 | 
            +
                    when Array then
         | 
| 69 | 
            +
                      _define_serialized_property serialize_column, key,
         | 
| 70 | 
            +
                        setter: proc { |val|
         | 
| 71 | 
            +
                          raise InvalidProperty, "#{self.name}##{key} must be one of #{type}" unless type.include?(val)
         | 
| 72 | 
            +
                          val
         | 
| 73 | 
            +
                        },
         | 
| 74 | 
            +
                        getter: proc { |val|
         | 
| 75 | 
            +
                          type.include?(val) ? val : nil
         | 
| 76 | 
            +
                        }
         | 
| 77 | 
            +
                    else
         | 
| 78 | 
            +
                      if type == Time
         | 
| 79 | 
            +
                        _define_serialized_property serialize_column, key,
         | 
| 80 | 
            +
                          getter: Proc.new { |val| val.nil? ? nil : Time.zone.parse(val) },
         | 
| 81 | 
            +
                          setter: Proc.new { |val| val.is_a?(Time) ? val.to_s(:default_tz) : nil}
         | 
| 82 | 
            +
                      elsif type == Integer
         | 
| 83 | 
            +
                        _define_serialized_property serialize_column, key,
         | 
| 84 | 
            +
                          setter: proc { |val|
         | 
| 85 | 
            +
                            val = val.blank? ? nil : Integer(val)
         | 
| 86 | 
            +
                            val = setter.call(val) if setter
         | 
| 87 | 
            +
                            val
         | 
| 88 | 
            +
                          }
         | 
| 89 | 
            +
                      elsif type == Array
         | 
| 90 | 
            +
                        _define_serialized_property(serialize_column, key, default: [])
         | 
| 91 | 
            +
                      elsif type && type < ActiveRecord::Base
         | 
| 92 | 
            +
                        _define_serialized_property serialize_column, "#{key}_id"
         | 
| 93 | 
            +
             | 
| 94 | 
            +
                        define_method key.to_sym do
         | 
| 95 | 
            +
                          instance_val = instance_variable_get("@#{key}".to_sym)
         | 
| 96 | 
            +
                          return instance_val if instance_val
         | 
| 97 | 
            +
                          key_id = send("#{key}_id".to_sym)
         | 
| 98 | 
            +
                          if key_id.nil?
         | 
| 99 | 
            +
                            instance_val = nil
         | 
| 100 | 
            +
                          else
         | 
| 101 | 
            +
                            instance_val = type.find(key_id) rescue nil
         | 
| 102 | 
            +
                            instance_variable_set("@#{key}".to_sym, instance_val)
         | 
| 103 | 
            +
                          end
         | 
| 104 | 
            +
                          instance_val = getter.call(instance_val) if getter
         | 
| 105 | 
            +
                          instance_val
         | 
| 106 | 
            +
                        end
         | 
| 107 | 
            +
             | 
| 108 | 
            +
                        define_method "#{key}=".to_sym do |val|
         | 
| 109 | 
            +
                          val = setter.call(val) if setter
         | 
| 110 | 
            +
             | 
| 111 | 
            +
                          if val.nil?
         | 
| 112 | 
            +
                            instance_variable_set("@#{key}".to_sym, nil)
         | 
| 113 | 
            +
                            send("#{key}_id=".to_sym, nil)
         | 
| 114 | 
            +
                          else
         | 
| 115 | 
            +
                            unless val.is_a?(type)
         | 
| 116 | 
            +
                              raise ActiveRecord::AssociationTypeMismatch, "#{type}(##{type.object_id}) expected, got #{val.class.name}(#{val.class.object_id})"
         | 
| 117 | 
            +
                            end
         | 
| 118 | 
            +
                            instance_variable_set("@#{key}".to_sym, val)
         | 
| 119 | 
            +
                            send("#{key}_id=".to_sym, (Integer(val.id) rescue val.id))
         | 
| 120 | 
            +
                          end
         | 
| 121 | 
            +
             | 
| 122 | 
            +
                          if setter_callback
         | 
| 123 | 
            +
                            setter_callback.call(val)
         | 
| 124 | 
            +
                          else
         | 
| 125 | 
            +
                            val
         | 
| 126 | 
            +
                          end
         | 
| 127 | 
            +
                        end
         | 
| 128 | 
            +
                      else
         | 
| 129 | 
            +
                        _define_serialized_property serialize_column, key, getter: getter, setter: setter, setter_callback: setter_callback, default: default
         | 
| 130 | 
            +
                      end
         | 
| 131 | 
            +
                  end
         | 
| 132 | 
            +
                end
         | 
| 133 | 
            +
             | 
| 134 | 
            +
                def _define_serialized_property(serialize_column, key, getter: nil, setter: nil, setter_callback: nil, default: nil)
         | 
| 135 | 
            +
                  if default
         | 
| 136 | 
            +
                    if getter
         | 
| 137 | 
            +
                      define_method key.to_sym do
         | 
| 138 | 
            +
                        hsh = send(serialize_column.to_sym)
         | 
| 139 | 
            +
                        hsh[key.to_s] ||= default.dup
         | 
| 140 | 
            +
                        getter.call(hsh[key.to_s])
         | 
| 141 | 
            +
                      end
         | 
| 142 | 
            +
                    else
         | 
| 143 | 
            +
                      define_method key.to_sym do
         | 
| 144 | 
            +
                        hsh = send(serialize_column.to_sym)
         | 
| 145 | 
            +
                        hsh[key.to_s] ||= default.dup
         | 
| 146 | 
            +
                      end
         | 
| 147 | 
            +
                    end
         | 
| 148 | 
            +
                  else
         | 
| 149 | 
            +
                    if getter
         | 
| 150 | 
            +
                      define_method key.to_sym do
         | 
| 151 | 
            +
                        hsh = send(serialize_column.to_sym)
         | 
| 152 | 
            +
                        getter.call(hsh[key.to_s])
         | 
| 153 | 
            +
                      end
         | 
| 154 | 
            +
                    else
         | 
| 155 | 
            +
                      define_method key.to_sym do
         | 
| 156 | 
            +
                        hsh = send(serialize_column.to_sym)
         | 
| 157 | 
            +
                        hsh[key.to_s]
         | 
| 158 | 
            +
                      end
         | 
| 159 | 
            +
                    end
         | 
| 160 | 
            +
                  end
         | 
| 161 | 
            +
             | 
| 162 | 
            +
                  if setter
         | 
| 163 | 
            +
                    define_method "#{key}_without_callback=".to_sym do |val|
         | 
| 164 | 
            +
                      if val.nil?
         | 
| 165 | 
            +
                        send(serialize_column.to_sym).delete(key.to_s)
         | 
| 166 | 
            +
                      else
         | 
| 167 | 
            +
                        val = setter.call(val) if setter
         | 
| 168 | 
            +
                        send(serialize_column.to_sym)[key.to_s] = val
         | 
| 169 | 
            +
                      end
         | 
| 170 | 
            +
                    end
         | 
| 171 | 
            +
                  else
         | 
| 172 | 
            +
                    define_method "#{key}_without_callback=".to_sym do |val|
         | 
| 173 | 
            +
                      if val.nil?
         | 
| 174 | 
            +
                        send(serialize_column.to_sym).delete(key.to_s)
         | 
| 175 | 
            +
                      else
         | 
| 176 | 
            +
                        send(serialize_column.to_sym)[key.to_s] = val
         | 
| 177 | 
            +
                      end
         | 
| 178 | 
            +
                    end
         | 
| 179 | 
            +
                  end
         | 
| 180 | 
            +
             | 
| 181 | 
            +
                  if setter_callback
         | 
| 182 | 
            +
                    define_method "#{key}=".to_sym do |val|
         | 
| 183 | 
            +
                      send("#{key}_without_callback=".to_sym, val)
         | 
| 184 | 
            +
                      setter_callback.call(val)
         | 
| 185 | 
            +
                    end
         | 
| 186 | 
            +
                  else
         | 
| 187 | 
            +
                    define_method "#{key}=".to_sym do |val|
         | 
| 188 | 
            +
                      send("#{key}_without_callback=".to_sym, val)
         | 
| 189 | 
            +
                    end
         | 
| 190 | 
            +
                  end
         | 
| 191 | 
            +
                end
         | 
| 192 | 
            +
              end
         | 
| 193 | 
            +
            end
         | 
    
        data/lib/coaster/version.rb
    CHANGED
    
    
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: coaster
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0. | 
| 4 | 
            +
              version: 0.5.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - buzz jung
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2017- | 
| 11 | 
            +
            date: 2017-12-05 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: i18n
         | 
| @@ -64,6 +64,20 @@ dependencies: | |
| 64 64 | 
             
                - - "<"
         | 
| 65 65 | 
             
                  - !ruby/object:Gem::Version
         | 
| 66 66 | 
             
                    version: '8.0'
         | 
| 67 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 68 | 
            +
              name: attr_extras
         | 
| 69 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 70 | 
            +
                requirements:
         | 
| 71 | 
            +
                - - ">="
         | 
| 72 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 73 | 
            +
                    version: '0'
         | 
| 74 | 
            +
              type: :runtime
         | 
| 75 | 
            +
              prerelease: false
         | 
| 76 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 77 | 
            +
                requirements:
         | 
| 78 | 
            +
                - - ">="
         | 
| 79 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 80 | 
            +
                    version: '0'
         | 
| 67 81 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 68 82 | 
             
              name: bundler
         | 
| 69 83 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -188,9 +202,13 @@ files: | |
| 188 202 | 
             
            - lib/coaster.rb
         | 
| 189 203 | 
             
            - lib/coaster/backtrace_cleaner.rb
         | 
| 190 204 | 
             
            - lib/coaster/core_ext.rb
         | 
| 205 | 
            +
            - lib/coaster/core_ext/array.rb
         | 
| 206 | 
            +
            - lib/coaster/core_ext/date.rb
         | 
| 207 | 
            +
            - lib/coaster/core_ext/month.rb
         | 
| 191 208 | 
             
            - lib/coaster/core_ext/object_translation.rb
         | 
| 192 209 | 
             
            - lib/coaster/core_ext/standard_error.rb
         | 
| 193 210 | 
             
            - lib/coaster/core_ext/standard_error/raven.rb
         | 
| 211 | 
            +
            - lib/coaster/serialized_properties.rb
         | 
| 194 212 | 
             
            - lib/coaster/version.rb
         | 
| 195 213 | 
             
            - test/locales/en.yml
         | 
| 196 214 | 
             
            - test/test_helper.rb
         |