motion_record 0.0.1
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 +15 -0
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +246 -0
- data/Rakefile +1 -0
- data/lib/motion_record/base.rb +54 -0
- data/lib/motion_record/connection_adapters/sqlite_adapter.rb +160 -0
- data/lib/motion_record/persistence.rb +99 -0
- data/lib/motion_record/schema/column_definition.rb +111 -0
- data/lib/motion_record/schema/index_definition.rb +35 -0
- data/lib/motion_record/schema/migration.rb +25 -0
- data/lib/motion_record/schema/migration_definition.rb +32 -0
- data/lib/motion_record/schema/migrator.rb +39 -0
- data/lib/motion_record/schema/migrator_definition.rb +18 -0
- data/lib/motion_record/schema/table_definition.rb +46 -0
- data/lib/motion_record/schema.rb +35 -0
- data/lib/motion_record/scope.rb +129 -0
- data/lib/motion_record/scope_helpers.rb +89 -0
- data/lib/motion_record/serialization/base_serializer.rb +20 -0
- data/lib/motion_record/serialization/boolean_serializer.rb +26 -0
- data/lib/motion_record/serialization/default_serializer.rb +14 -0
- data/lib/motion_record/serialization/json_serializer.rb +38 -0
- data/lib/motion_record/serialization/time_serializer.rb +84 -0
- data/lib/motion_record/serialization.rb +68 -0
- data/lib/motion_record/version.rb +3 -0
- data/lib/motion_record.rb +37 -0
- data/motion_record.gemspec +23 -0
- metadata +99 -0
@@ -0,0 +1,84 @@
|
|
1
|
+
module MotionRecord
|
2
|
+
module Serialization
|
3
|
+
class TimeSerializer < BaseSerializer
|
4
|
+
|
5
|
+
# Pattern stolen from Ruby Time's xmlschema method
|
6
|
+
ISO8601_PATTERN = /\A\s*
|
7
|
+
(-?\d+)-(\d\d)-(\d\d)
|
8
|
+
T
|
9
|
+
(\d\d):(\d\d):(\d\d)
|
10
|
+
(\.\d+)?
|
11
|
+
(Z|[+-]\d\d:\d\d)?
|
12
|
+
\s*\z/ix
|
13
|
+
|
14
|
+
def serialize(value)
|
15
|
+
case @column.type
|
16
|
+
when :integer, :float
|
17
|
+
value.to_i
|
18
|
+
when :text
|
19
|
+
self.class.time_to_iso8601(value)
|
20
|
+
else
|
21
|
+
raise "Can't serialize #{value.inspect} to #{@column.type.inspect}"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def deserialize(value)
|
26
|
+
case @column.type
|
27
|
+
when :integer, :float
|
28
|
+
Time.at(value)
|
29
|
+
when :text
|
30
|
+
self.class.time_from_iso8601(value)
|
31
|
+
else
|
32
|
+
raise "Can't deserialize #{value.inspect} from #{@column.type.inspect}"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Convert a Time object to an ISO8601 format time string
|
37
|
+
#
|
38
|
+
# time - the Time to convert
|
39
|
+
#
|
40
|
+
# Returns the String representation
|
41
|
+
def self.time_to_iso8601(time)
|
42
|
+
if time.utc_offset == 0
|
43
|
+
zone = "Z"
|
44
|
+
else
|
45
|
+
offset_hours = time.utc_offset / 3600
|
46
|
+
offset_minutes = (time.utc_offset - (offset_hours * 3600)) / 60
|
47
|
+
zone = "%+03d:%02d" % [offset_hours, offset_minutes]
|
48
|
+
end
|
49
|
+
|
50
|
+
if time.usec != 0
|
51
|
+
"%04d-%02d-%02dT%02d:%02d:%02d.%03d%s" % [time.year, time.month, time.day, time.hour, time.min, time.sec, time.usec, zone]
|
52
|
+
else
|
53
|
+
"%04d-%02d-%02dT%02d:%02d:%02d:%s" % [time.year, time.month, time.day, time.hour, time.min, time.sec, zone]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# Parse an ISO8601 format time string
|
58
|
+
#
|
59
|
+
# time_str - the String time representation in ISO8601 format
|
60
|
+
#
|
61
|
+
# Returns a Time object
|
62
|
+
def self.time_from_iso8601(time_str)
|
63
|
+
# Logic stolen from Ruby Time's xmlschema method
|
64
|
+
if (match = ISO8601_PATTERN.match(time_str))
|
65
|
+
year = match[1].to_i
|
66
|
+
mon = match[2].to_i
|
67
|
+
day = match[3].to_i
|
68
|
+
hour = match[4].to_i
|
69
|
+
min = match[5].to_i
|
70
|
+
sec = match[6].to_i
|
71
|
+
# usec = (match[7] || 0).to_i # microsecond values are discarded
|
72
|
+
zone = match[8]
|
73
|
+
if zone == "Z"
|
74
|
+
Time.utc(year, mon, day, hour, min, sec)
|
75
|
+
elsif zone
|
76
|
+
Time.new(year, mon, day, hour, min, sec, zone)
|
77
|
+
end
|
78
|
+
else
|
79
|
+
raise ArgumentError.new("invalid date: #{time_str.inspect}")
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module MotionRecord
|
2
|
+
module Serialization
|
3
|
+
module ClassMethods
|
4
|
+
# Register a new attribute serializer
|
5
|
+
#
|
6
|
+
# attribute - Symbol name of the attribute
|
7
|
+
# serializer_class_or_sym - One of :time, :boolean, :json or a custom
|
8
|
+
# subclass of Serialization::BaseSerializer
|
9
|
+
def serialize(attribute, serializer_class_or_sym)
|
10
|
+
if serializer_class_or_sym.is_a?(Symbol)
|
11
|
+
self.serializer_classes[attribute] = case serializer_class_or_sym
|
12
|
+
when :time
|
13
|
+
Serialization::TimeSerializer
|
14
|
+
when :boolean
|
15
|
+
Serialization::BooleanSerializer
|
16
|
+
when :json
|
17
|
+
Serialization::JSONSerializer
|
18
|
+
else
|
19
|
+
raise "Unknown serializer #{serializer_class_or_sym.inspect}"
|
20
|
+
end
|
21
|
+
else
|
22
|
+
self.serializer_classes[attribute] = serializer_class_or_sym
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# Build a new object from the Hash result of a SQL query
|
27
|
+
def from_table_params(params)
|
28
|
+
attributes = {}
|
29
|
+
params.each do |name, value|
|
30
|
+
attributes[name.to_sym] = serializer(name.to_sym).deserialize(value)
|
31
|
+
end
|
32
|
+
record = self.new(attributes)
|
33
|
+
record.mark_persisted!
|
34
|
+
record
|
35
|
+
end
|
36
|
+
|
37
|
+
# Serialize a Hash of attributes to their database representation
|
38
|
+
def to_table_params(hash)
|
39
|
+
hash.each_with_object({}) do |attribute_and_value, params|
|
40
|
+
attribute, value = attribute_and_value
|
41
|
+
params[attribute] = serializer(attribute).serialize(value)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
protected
|
46
|
+
|
47
|
+
# Internal: Get the serializer object for an attribute
|
48
|
+
#
|
49
|
+
# attribute - Symbol name of the attribute
|
50
|
+
def serializer(attribute)
|
51
|
+
@serializers ||= {}
|
52
|
+
unless @serializers[attribute]
|
53
|
+
@serializers[attribute] = build_serializer(attribute)
|
54
|
+
end
|
55
|
+
@serializers[attribute]
|
56
|
+
end
|
57
|
+
|
58
|
+
# Internal: Registry of serializer classes
|
59
|
+
def serializer_classes
|
60
|
+
@serializer_classes ||= Hash.new(Serialization::DefaultSerializer)
|
61
|
+
end
|
62
|
+
|
63
|
+
def build_serializer(attribute)
|
64
|
+
serializer_classes[attribute].new(table_columns[attribute])
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
unless defined?(Motion::Project::Config)
|
2
|
+
raise "This file must be required within a RubyMotion project Rakefile."
|
3
|
+
end
|
4
|
+
|
5
|
+
Motion::Project::App.setup do |app|
|
6
|
+
# if Motion::Project.constants.include? :IOSConfig
|
7
|
+
# # config for iOS app
|
8
|
+
# end
|
9
|
+
|
10
|
+
# if Motion::Project.constants.include? :AndroidConfig
|
11
|
+
# # config for Android app
|
12
|
+
# end
|
13
|
+
|
14
|
+
dirname = File.dirname(__FILE__)
|
15
|
+
|
16
|
+
serial_files = Dir.glob(File.join(dirname, 'motion_record/serialization/*.rb'))
|
17
|
+
conn_files = Dir.glob(File.join(dirname, 'motion_record/connection_adapters/*.rb'))
|
18
|
+
schema_files = Dir.glob(File.join(dirname, 'motion_record/schema/*.rb'))
|
19
|
+
base_files = Dir.glob(File.join(dirname, 'motion_record/*.rb'))
|
20
|
+
|
21
|
+
# RubyMotion for Android can't infer file dependencies so we must explicitly
|
22
|
+
# declare their compilation order
|
23
|
+
(base_files + schema_files + conn_files + serial_files).reverse.each do |file|
|
24
|
+
app.files.unshift(file)
|
25
|
+
end
|
26
|
+
|
27
|
+
# Some files don't have the same dependency order and alphabetic order
|
28
|
+
{
|
29
|
+
"motion_record/persistence.rb" => "motion_record/scope_helpers.rb"
|
30
|
+
}.each do |file, dependency|
|
31
|
+
app.files_dependencies File.join(dirname, file) => File.join(dirname, dependency)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
module MotionRecord
|
36
|
+
# Your code goes here...
|
37
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'motion_record/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "motion_record"
|
8
|
+
spec.version = MotionRecord::VERSION
|
9
|
+
spec.authors = ["Zach Millman"]
|
10
|
+
spec.email = ["zach.millman@gmail.com"]
|
11
|
+
spec.description = %q{Mini ActiveRecord for RubyMotion}
|
12
|
+
spec.summary = %q{Miniature ActiveRecord for RubyMotion to use SQLite for storing your objects}
|
13
|
+
spec.homepage = "https://github.com/magoosh/motion_record"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
end
|
metadata
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: motion_record
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Zach Millman
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-03-13 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.3'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ! '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ! '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
description: Mini ActiveRecord for RubyMotion
|
42
|
+
email:
|
43
|
+
- zach.millman@gmail.com
|
44
|
+
executables: []
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- .gitignore
|
49
|
+
- Gemfile
|
50
|
+
- LICENSE.txt
|
51
|
+
- README.md
|
52
|
+
- Rakefile
|
53
|
+
- lib/motion_record.rb
|
54
|
+
- lib/motion_record/base.rb
|
55
|
+
- lib/motion_record/connection_adapters/sqlite_adapter.rb
|
56
|
+
- lib/motion_record/persistence.rb
|
57
|
+
- lib/motion_record/schema.rb
|
58
|
+
- lib/motion_record/schema/column_definition.rb
|
59
|
+
- lib/motion_record/schema/index_definition.rb
|
60
|
+
- lib/motion_record/schema/migration.rb
|
61
|
+
- lib/motion_record/schema/migration_definition.rb
|
62
|
+
- lib/motion_record/schema/migrator.rb
|
63
|
+
- lib/motion_record/schema/migrator_definition.rb
|
64
|
+
- lib/motion_record/schema/table_definition.rb
|
65
|
+
- lib/motion_record/scope.rb
|
66
|
+
- lib/motion_record/scope_helpers.rb
|
67
|
+
- lib/motion_record/serialization.rb
|
68
|
+
- lib/motion_record/serialization/base_serializer.rb
|
69
|
+
- lib/motion_record/serialization/boolean_serializer.rb
|
70
|
+
- lib/motion_record/serialization/default_serializer.rb
|
71
|
+
- lib/motion_record/serialization/json_serializer.rb
|
72
|
+
- lib/motion_record/serialization/time_serializer.rb
|
73
|
+
- lib/motion_record/version.rb
|
74
|
+
- motion_record.gemspec
|
75
|
+
homepage: https://github.com/magoosh/motion_record
|
76
|
+
licenses:
|
77
|
+
- MIT
|
78
|
+
metadata: {}
|
79
|
+
post_install_message:
|
80
|
+
rdoc_options: []
|
81
|
+
require_paths:
|
82
|
+
- lib
|
83
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - ! '>='
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
88
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
89
|
+
requirements:
|
90
|
+
- - ! '>='
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: '0'
|
93
|
+
requirements: []
|
94
|
+
rubyforge_project:
|
95
|
+
rubygems_version: 2.1.11
|
96
|
+
signing_key:
|
97
|
+
specification_version: 4
|
98
|
+
summary: Miniature ActiveRecord for RubyMotion to use SQLite for storing your objects
|
99
|
+
test_files: []
|