rails_to_swift 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.
Files changed (55) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/Rakefile +37 -0
  4. data/bin/rails_to_swift +23 -0
  5. data/lib/rails_to_swift.rb +89 -0
  6. data/lib/rails_to_swift/active_record_patch.rb +9 -0
  7. data/lib/rails_to_swift/column.rb +9 -0
  8. data/lib/rails_to_swift/engine.rb +5 -0
  9. data/lib/rails_to_swift/swift_column.rb +23 -0
  10. data/lib/rails_to_swift/swift_models.rb +160 -0
  11. data/lib/rails_to_swift/tasks.rb +6 -0
  12. data/lib/rails_to_swift/templates/Constants.swift +23 -0
  13. data/lib/rails_to_swift/templates/NSDate+Rails.swift +21 -0
  14. data/lib/rails_to_swift/templates/model.swift +67 -0
  15. data/lib/rails_to_swift/templates/slimmodel.swift +62 -0
  16. data/lib/rails_to_swift/version.rb +3 -0
  17. data/lib/tasks/rails_to_swift_tasks.rake +8 -0
  18. data/test/dummy/README.rdoc +28 -0
  19. data/test/dummy/Rakefile +6 -0
  20. data/test/dummy/app/assets/javascripts/application.js +13 -0
  21. data/test/dummy/app/assets/stylesheets/application.css +15 -0
  22. data/test/dummy/app/controllers/application_controller.rb +5 -0
  23. data/test/dummy/app/helpers/application_helper.rb +2 -0
  24. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  25. data/test/dummy/bin/bundle +3 -0
  26. data/test/dummy/bin/rails +4 -0
  27. data/test/dummy/bin/rake +4 -0
  28. data/test/dummy/bin/setup +29 -0
  29. data/test/dummy/config.ru +4 -0
  30. data/test/dummy/config/application.rb +26 -0
  31. data/test/dummy/config/boot.rb +5 -0
  32. data/test/dummy/config/database.yml +25 -0
  33. data/test/dummy/config/environment.rb +5 -0
  34. data/test/dummy/config/environments/development.rb +41 -0
  35. data/test/dummy/config/environments/production.rb +79 -0
  36. data/test/dummy/config/environments/test.rb +42 -0
  37. data/test/dummy/config/initializers/assets.rb +11 -0
  38. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  39. data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
  40. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  41. data/test/dummy/config/initializers/inflections.rb +16 -0
  42. data/test/dummy/config/initializers/mime_types.rb +4 -0
  43. data/test/dummy/config/initializers/session_store.rb +3 -0
  44. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  45. data/test/dummy/config/locales/en.yml +23 -0
  46. data/test/dummy/config/routes.rb +4 -0
  47. data/test/dummy/config/secrets.yml +22 -0
  48. data/test/dummy/public/404.html +67 -0
  49. data/test/dummy/public/422.html +67 -0
  50. data/test/dummy/public/500.html +66 -0
  51. data/test/dummy/public/favicon.ico +0 -0
  52. data/test/integration/navigation_test.rb +8 -0
  53. data/test/rails_to_swift_test.rb +7 -0
  54. data/test/test_helper.rb +21 -0
  55. metadata +185 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 4c918d6a4e23af7df5a422e8d690b1746d6dd1de
4
+ data.tar.gz: 3869b0514acc8e6afb9b181ae73da18e9c7138ab
5
+ SHA512:
6
+ metadata.gz: 2540b6e4c15e80b204d56107745dde9a49cd4c0d3fe6f6cb71b0e332d3cf7891b32aeda7e44a0f97fb40a486cbf75345e6cef31f8299feea70e6933cdbf006f2
7
+ data.tar.gz: c54f3ed681d7a47d87e976009344b475c88c8a77e9b52b189a6b6f80b46768cd7baa542ce5995bddb2cab11bf22d852df6066acce866acf224c3f2db5d05b05f
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2015 Josh Juncker
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,37 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'RailsToSwift'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.rdoc')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
18
+ load 'rails/tasks/engine.rake'
19
+
20
+
21
+ load 'rails/tasks/statistics.rake'
22
+
23
+
24
+
25
+ Bundler::GemHelper.install_tasks
26
+
27
+ require 'rake/testtask'
28
+
29
+ Rake::TestTask.new(:test) do |t|
30
+ t.libs << 'lib'
31
+ t.libs << 'test'
32
+ t.pattern = 'test/**/*_test.rb'
33
+ t.verbose = false
34
+ end
35
+
36
+
37
+ task default: :test
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ unless File.exists?('./Rakefile') || File.exists?('./Gemfile')
4
+ abort "Please run annotate from the root of the project."
5
+ end
6
+
7
+ require 'rubygems'
8
+ begin
9
+ require 'bundler'
10
+ Bundler.setup
11
+ rescue Exception => e
12
+ end
13
+
14
+ here = File.expand_path(File.dirname __FILE__)
15
+ $:<< "#{here}/../lib"
16
+
17
+ require 'optparse'
18
+ require 'rails_to_swift'
19
+ RailsToSwift.bootstrap_rake
20
+
21
+ RailsToSwift.eager_load()
22
+
23
+ SwiftModels.create_model_files
@@ -0,0 +1,89 @@
1
+ $:.unshift(File.dirname(__FILE__))
2
+ # require "rails_to_swift/engine"
3
+ require "rails_to_swift/column"
4
+ require "rails_to_swift/swift_column"
5
+ require "rails_to_swift/swift_models"
6
+
7
+ begin
8
+ # ActiveSupport 3.x...
9
+ require 'active_support/hash_with_indifferent_access'
10
+ require 'active_support/core_ext/object/blank'
11
+ rescue Exception => e
12
+ # ActiveSupport 2.x...
13
+ require 'active_support/core_ext/hash/indifferent_access'
14
+ require 'active_support/core_ext/blank'
15
+ end
16
+
17
+ module RailsToSwift
18
+ def self.loaded_tasks=(val); @loaded_tasks = val; end
19
+ def self.loaded_tasks; return @loaded_tasks; end
20
+
21
+ def self.load_tasks
22
+ return if(self.loaded_tasks)
23
+ self.loaded_tasks = true
24
+
25
+ Dir[File.join(File.dirname(__FILE__), 'tasks', '**/*.rake')].each { |rake| load rake }
26
+ end
27
+
28
+ def self.load_requires(options)
29
+ options[:require].each { |path| require path } if options[:require] && options[:require].count > 0
30
+ end
31
+
32
+ def self.eager_load(options = {})
33
+ self.load_requires(options)
34
+ require "annotate/active_record_patch"
35
+
36
+ if(defined?(Rails))
37
+ if(Rails.version.split('.').first.to_i < 3)
38
+ Rails.configuration.eager_load_paths.each do |load_path|
39
+ matcher = /\A#{Regexp.escape(load_path)}(.*)\.rb\Z/
40
+ Dir.glob("#{load_path}/**/*.rb").sort.each do |file|
41
+ require_dependency file.sub(matcher, '\1')
42
+ end
43
+ end
44
+ else
45
+ klass = Rails::Application.send(:subclasses).first
46
+ klass.eager_load!
47
+ end
48
+ else
49
+ options[:model_dir].each do |dir|
50
+ FileList["#{dir}/**/*.rb"].each do |fname|
51
+ require File.expand_path(fname)
52
+ end
53
+ end
54
+ end
55
+ end
56
+
57
+ def self.bootstrap_rake
58
+ begin
59
+ require 'rake/dsl_definition'
60
+ rescue Exception => e
61
+ # We might just be on an old version of Rake...
62
+ end
63
+ require 'rake'
64
+
65
+ if File.exists?('./Rakefile')
66
+ load './Rakefile'
67
+ end
68
+ Rake::Task[:environment].invoke rescue nil
69
+ if(!defined?(Rails))
70
+ # Not in a Rails project, so time to load up the parts of
71
+ # ActiveSupport we need.
72
+ require 'active_support'
73
+ require 'active_support/core_ext/class/subclasses'
74
+ require 'active_support/core_ext/string/inflections'
75
+ end
76
+ self.load_tasks
77
+ end
78
+
79
+ def self.fallback(*args)
80
+ return args.detect { |arg| !arg.blank? }
81
+ end
82
+
83
+ def self.true?(val)
84
+ return false if(val.blank?)
85
+ return false unless(val =~ TRUE_RE)
86
+ return true
87
+ end
88
+
89
+ end
@@ -0,0 +1,9 @@
1
+ # monkey patches
2
+
3
+ module ::ActiveRecord
4
+ class Base
5
+ def self.method_missing(name, *args)
6
+ # ignore this, so unknown/unloaded macros won't cause parsing to fail
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ class Column
2
+ attr_accessor :name, :type, :not_null
3
+ def formatted_name
4
+ return name
5
+ end
6
+ def formatted_type
7
+ return type
8
+ end
9
+ end
@@ -0,0 +1,5 @@
1
+ module RailsToSwift
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace RailsToSwift
4
+ end
5
+ end
@@ -0,0 +1,23 @@
1
+ class SwiftColumn < Column
2
+ def formatted_name
3
+ return name.camelize(:lower)
4
+ end
5
+ def formatted_type
6
+ case self.type
7
+ when "integer"
8
+ return "Int"
9
+ when "float"
10
+ return "Float"
11
+ when "string"
12
+ return "String"
13
+ when "array"
14
+ return "Array"
15
+ when "text"
16
+ return "String"
17
+ when "datetime"
18
+ return "NSDate"
19
+ else
20
+ return ""
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,160 @@
1
+ require 'erb'
2
+ require 'fileutils'
3
+
4
+ module SwiftModels
5
+
6
+ class << self
7
+
8
+ def model_dir
9
+ @model_dir.is_a?(Array) ? @model_dir : [@model_dir || "app/models"]
10
+ end
11
+
12
+ def model_dir=(dir)
13
+ @model_dir = dir
14
+ end
15
+
16
+ def schema_default(klass, column)
17
+ quote(klass.column_defaults[column.name])
18
+ end
19
+
20
+ def create_model_files(options = {})
21
+ FileUtils::mkdir_p(Rails.root.join('rails_to_swift', 'models'))
22
+ constants_file = File.read(File.expand_path('../templates/Constants.swift', __FILE__))
23
+ nsdate_file = File.read(File.expand_path('../templates/NSDate+Rails.swift', __FILE__))
24
+ File.open(Rails.root.join('rails_to_swift', "Constants.swift"), 'w') {|f| f.write(constants_file) }
25
+ File.open(Rails.root.join('rails_to_swift', "NSDate+Rails.swift"), 'w') {|f| f.write(nsdate_file) }
26
+ get_model_files(options).each do |file|
27
+ create_model_file(File.join(file), options)
28
+ end
29
+ end
30
+
31
+ def create_model_file(file, options)
32
+ begin
33
+ # return false if (/# -\*- SkipSchemaAnnotations.*/ =~ (File.exist?(file) ? File.read(file) : '') )
34
+ klass = get_model_class(file)
35
+ if klass && klass < ActiveRecord::Base && !klass.abstract_class? && klass.table_exists?
36
+
37
+ @class_name = klass.to_s
38
+ cols = klass.columns
39
+ cols = cols.sort_by(&:name) if(options[:sort])
40
+ cols = classified_sort(cols) if(options[:classified_sort])
41
+ @columns = []
42
+ cols.each do |col|
43
+ col_info = SwiftColumn.new
44
+ col_info.not_null = col.null ? false : true
45
+ col_info.type = (col.type || col.sql_type).to_s
46
+ col_info.name = col.name
47
+ @columns.push(col_info)
48
+ end
49
+ template = File.read(File.expand_path('../templates/model.swift', __FILE__))
50
+ File.open(Rails.root.join('rails_to_swift', 'models', "#{@class_name}.swift"), "w") do |file|
51
+ file.write ERB.new(template, nil, '>').result(binding)
52
+ end
53
+ # File.open(Rails.root.join('rails_to_swift', 'models', "#{@class_name}.swift"), "w") do |file|
54
+ # file.write Slim::Template.new({default_tag: "", use_html_safe: false, disable_escape: true}) {template}.render(binding)
55
+ # end
56
+
57
+ end
58
+ rescue Exception => e
59
+ puts "Unable to create #{file}: #{e.message}"
60
+ puts "\t" + e.backtrace.join("\n\t") if options[:trace]
61
+ end
62
+ end
63
+
64
+ # Return a list of the model files to annotate.
65
+ # If we have command line arguments, they're assumed to the path
66
+ # of model files from root dir. Otherwise we take all the model files
67
+ # in the model_dir directory.
68
+ def get_model_files(options)
69
+ models = []
70
+ if(!options[:is_rake])
71
+ models = ARGV.dup.reject{|m| m.match(/^(.*)=/)}
72
+ end
73
+
74
+ if models.empty?
75
+ begin
76
+ model_dir.each do |dir|
77
+ Dir.chdir(dir) do
78
+ lst =
79
+ if options[:ignore_model_sub_dir]
80
+ Dir["*.rb"].map{ |f| [dir, f] }
81
+ else
82
+ Dir["**/*.rb"].reject{ |f| f["concerns/"] }.map{ |f| [dir, f] }
83
+ end
84
+ models.concat(lst)
85
+ end
86
+ end
87
+ rescue SystemCallError
88
+ puts "No models found in directory '#{model_dir.join("', '")}'."
89
+ puts "Either specify models on the command line, or use the --model-dir option."
90
+ puts "Call 'annotate --help' for more info."
91
+ exit 1
92
+ end
93
+ end
94
+
95
+ models
96
+ end
97
+
98
+ # Retrieve the classes belonging to the model names we're asked to process
99
+ # Check for namespaced models in subdirectories as well as models
100
+ # in subdirectories without namespacing.
101
+ def get_model_class(file)
102
+ model_path = file.gsub(/\.rb$/, '')
103
+ model_dir.each { |dir| model_path = model_path.gsub(/^#{dir}/, '').gsub(/^\//, '') }
104
+ begin
105
+ get_loaded_model(model_path) or raise LoadError.new("cannot load a model from #{file}")
106
+ rescue LoadError
107
+ # this is for non-rails projects, which don't get Rails auto-require magic
108
+ file_path = File.expand_path(file)
109
+ if File.file?(file_path) && Kernel.require(file_path)
110
+ retry
111
+ elsif model_path.match(/\//)
112
+ model_path = model_path.split('/')[1..-1].join('/').to_s
113
+ retry
114
+ else
115
+ raise
116
+ end
117
+ end
118
+ end
119
+
120
+ # Retrieve loaded model class by path to the file where it's supposed to be defined.
121
+ def get_loaded_model(model_path)
122
+ begin
123
+ ActiveSupport::Inflector.constantize(ActiveSupport::Inflector.camelize(model_path))
124
+ rescue
125
+ # Revert to the old way but it is not really robust
126
+ ObjectSpace.each_object(::Class).
127
+ select do |c|
128
+ Class === c and # note: we use === to avoid a bug in activesupport 2.3.14 OptionMerger vs. is_a?
129
+ c.ancestors.respond_to?(:include?) and # to fix FactoryGirl bug, see https://github.com/ctran/annotate_models/pull/82
130
+ c.ancestors.include?(ActiveRecord::Base)
131
+ end.
132
+ detect { |c| ActiveSupport::Inflector.underscore(c.to_s) == model_path }
133
+ end
134
+ end
135
+
136
+
137
+ def classified_sort(cols)
138
+ rest_cols = []
139
+ timestamps = []
140
+ associations = []
141
+ id = nil
142
+
143
+ cols = cols.each do |c|
144
+ if c.name.eql?("id")
145
+ id = c
146
+ elsif (c.name.eql?("created_at") || c.name.eql?("updated_at"))
147
+ timestamps << c
148
+ elsif c.name[-3,3].eql?("_id")
149
+ associations << c
150
+ else
151
+ rest_cols << c
152
+ end
153
+ end
154
+ [rest_cols, timestamps, associations].each {|a| a.sort_by!(&:name) }
155
+
156
+ return ([id] << rest_cols << timestamps << associations).flatten
157
+ end
158
+
159
+ end
160
+ end
@@ -0,0 +1,6 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ # Make tasks visible for Rails also when used as gem.
5
+ Dir[File.join(File.dirname(__FILE__), '..', 'tasks', '**/*.rake')].each { |rake| load rake }
6
+ Dir[File.join(File.dirname(__FILE__), '..', '..', 'tasks', '**/*.rake')].each { |rake| load rake }
@@ -0,0 +1,23 @@
1
+ //
2
+ // Constants.swift
3
+ //
4
+
5
+ func removeNilValuedKeys<T>(dict:[T:AnyObject?])->[T:AnyObject] {
6
+ var result:[T:AnyObject] = [:]
7
+ for (key, value) in dict {
8
+ if let value: AnyObject = value {
9
+ result.updateValue(value, forKey: key)
10
+ }
11
+ }
12
+ return result
13
+ }
14
+
15
+ func removeNilValuedKeys(dict:NSDictionary)->[String:AnyObject] {
16
+ var result:[String:AnyObject] = [:]
17
+ for (key, value) in dict {
18
+ if let value: AnyObject = value where !(value is NSNull) {
19
+ result.updateValue(value, forKey: key as! String)
20
+ }
21
+ }
22
+ return result
23
+ }
@@ -0,0 +1,21 @@
1
+ //
2
+ // NSDate+Rails.swift
3
+ //
4
+
5
+ import Foundation
6
+
7
+ extension NSDate {
8
+
9
+ func railsFriendly() -> String {
10
+ let format:NSDateFormatter = NSDateFormatter()
11
+ format.dateFormat = "yyyy-MM-dd HH:mm:ss zzz"
12
+ return format.stringFromDate(self)
13
+ }
14
+
15
+ class func fromRails(date:String) -> NSDate? {
16
+ let dateFormatter = NSDateFormatter()
17
+ // dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss Z" // expected date format: 2015-09-30 19:19:26 +0000
18
+ dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ" // expected date format: 2015-10-12T17:46:00.386Z
19
+ return dateFormatter.dateFromString(date)
20
+ }
21
+ }