rails_to_swift 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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
+ }