mongify-mongoid 1.0.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.
@@ -0,0 +1,33 @@
1
+ class <%= class_name %>
2
+ include Mongoid::Document
3
+ <%- if has_timestamps? -%>
4
+ include Mongoid::Timestamps<%= "::#{has_created_at_timestamp? ? "Created" : "Updated"}" unless has_both_timestamps?-%>
5
+ <%- end %>
6
+
7
+ <%- fields.each do |key, field| -%>
8
+ <%- unless key == "id" -%>
9
+ field :<%= field.name %>, type: <%= field.type %>
10
+ <%- end -%>
11
+ <%- end -%>
12
+
13
+ <%- if polymorphic? -%>
14
+ ### POLYMORPHIC RELATIONS ###
15
+ #
16
+ # This model is polymorphic, please uncomment one of the following options:
17
+ #
18
+ # belongs_to :<%= polymorphic_as %>, polymorphic: true
19
+ # embedded_in :<%= polymorphic_as %>, polymorphic: true
20
+ #
21
+ # ALSO: Make sure to add the otherside of the polymorphic relationship into your other models,
22
+ # below are some examples:
23
+ # has_many :address, as: :<%= polymorphic_as %>
24
+ # embeds_many :notes, as: :<%= polymorphic_as %>
25
+ #
26
+ ###
27
+
28
+ <%- end -%>
29
+ <%- relations.sort{|a,b | a.name <=> b.name}.each do |relation| -%>
30
+ <%= relation.name %> :<%= relation.association %>
31
+ <%- end -%>
32
+
33
+ end
@@ -0,0 +1,64 @@
1
+ module Mongify
2
+ module Mongoid
3
+ #
4
+ # Used to output messages to the UI
5
+ #
6
+ class UI
7
+ class << self
8
+ # Outputs to stream using puts method
9
+ def puts(msg)
10
+ out_stream.puts(msg) if out_stream
11
+ end
12
+
13
+ # Outputs to stream using print method
14
+ def print(msg)
15
+ out_stream.print(msg) if out_stream
16
+ end
17
+
18
+ # Gets input from user
19
+ def gets
20
+ in_stream ? in_stream.gets : ''
21
+ end
22
+
23
+ # Outputs a question and gets input
24
+ def request(msg)
25
+ print(msg)
26
+ gets.chomp
27
+ end
28
+
29
+ # Asks a yes or no question and waits for reply
30
+ def ask(msg)
31
+ request("#{msg} [yn] ") == 'y'
32
+ end
33
+
34
+ # Outputs a Warning (using puts command)
35
+ def warn(msg)
36
+ puts "WARNING: #{msg}"
37
+ end
38
+
39
+ # Outputs a message and aborts execution of app
40
+ def abort(message)
41
+ UI.puts "PROGRAM HALT: #{message}"
42
+ Kernel.abort message
43
+ end
44
+
45
+ # Incoming stream
46
+ def in_stream
47
+ $stdin
48
+ end
49
+ # Output stream
50
+ def out_stream
51
+ $stdout
52
+ end
53
+
54
+ # Creates an instance of HighLine
55
+ # which lets us figure out width of console
56
+ # plus a whole lot more
57
+ # @return [HighLine] instance
58
+ def terminal_helper
59
+ @terminal_helper ||= HighLine.new
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,6 @@
1
+ module Mongify
2
+ module Mongoid
3
+ #Version number for Mongify-Mongoid
4
+ VERSION = "1.0.0"
5
+ end
6
+ end
@@ -0,0 +1,34 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'mongify/mongoid/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "mongify-mongoid"
8
+ spec.version = Mongify::Mongoid::VERSION
9
+ spec.authors = ["Andrew Kalek", "Afolabi Badmos"]
10
+ spec.email = ["andrew.kalek@anlek.com", "afolabi@badmos.com"]
11
+ spec.description = %q{Generates Mongoid Models from the Mongify translation file}
12
+ spec.summary = %q{Generates Mongoid Models from the Mongify translation file}
13
+ spec.homepage = "https://github.com/anlek/mongify-mongoid"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
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.extra_rdoc_files = [
22
+ "CHANGELOG.md",
23
+ "README.md"
24
+ ]
25
+
26
+ spec.add_dependency "mongify"
27
+
28
+ spec.add_development_dependency "bundler", "~> 1.3"
29
+ spec.add_development_dependency "rspec"
30
+ spec.add_development_dependency "rake"
31
+ spec.add_development_dependency "guard-rspec"
32
+ spec.add_development_dependency 'yard'
33
+ spec.add_development_dependency 'redcarpet'
34
+ end
@@ -0,0 +1,44 @@
1
+ table "users" do
2
+ column "id", :key
3
+ column "first_name", :string
4
+ column "last_name", :string
5
+ column "created_at", :datetime
6
+ column "updated_at", :datetime
7
+ end
8
+
9
+ table "posts" do
10
+ column "id", :key
11
+ column "title", :string
12
+ column "owner_id", :integer, :references => "users", :rename_to => 'user_id'
13
+ column "body", :text
14
+ column "published_at", :datetime
15
+ column "created_at", :datetime
16
+ column "updated_at", :datetime
17
+ end
18
+
19
+ table "comments", :embed_in => 'posts', :on => 'post_id' do
20
+ column "id", :key
21
+ column "body", :text
22
+ column "post_id", :integer, :references => "posts"
23
+ column "user_id", :integer, :references => "users"
24
+ column "created_at", :datetime
25
+ column "updated_at", :datetime
26
+ end
27
+
28
+ table "preferences", :embed_in => 'users', :as => 'object' do
29
+ column "id", :key
30
+ column "user_id", :integer, :references => "users"
31
+ column "notify_by_email", :boolean
32
+ column "created_at", :datetime, :ignore => true
33
+ column "updated_at", :datetime, :ignore => true
34
+ end
35
+
36
+ table "notes", :polymorphic => 'notable', :embed_in => true do
37
+ column "id", :key
38
+ column "user_id", :integer, :references => "users"
39
+ column "notable_id", :integer, :references => "notables"
40
+ column "notable_type", :string
41
+ column "body", :text
42
+ column "created_at", :datetime
43
+ column "updated_at", :datetime
44
+ end
@@ -0,0 +1,45 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mongify::Mongoid::CLI::Command::Worker do
4
+ let(:translation_file){ "spec/files/translation.rb" }
5
+ let(:output_folder) { "spec/files/tmp" }
6
+ subject(:worker) { Mongify::Mongoid::CLI::Command::Worker.new(translation_file) }
7
+
8
+ before(:each) do
9
+ Mongify::Mongoid::Printer.any_instance.stub(:write)
10
+ end
11
+
12
+ let(:view) do
13
+ view = stub("View")
14
+ view.stub(:output)
15
+ view.stub(:report_success)
16
+ view
17
+ end
18
+
19
+ context "default output file" do
20
+ it "should be called path + models" do
21
+ FileUtils.stub(:mkdir_p)
22
+ Mongify::Mongoid::Generator.any_instance.stub(:process)
23
+ worker.output_folder.should == File.join(Dir.pwd, "models")
24
+ end
25
+ end
26
+
27
+ context "translation file" do
28
+ it "raises an error if not passed" do
29
+ lambda { Mongify::Mongoid::CLI::Command::Worker.new().execute(view) }.should raise_error(Mongify::Mongoid::TranslationFileNotFound)
30
+ end
31
+ it "raises an error if file doesn't exist" do
32
+ lambda { Mongify::Mongoid::CLI::Command::Worker.new("missing/translation.rb").execute(view) }.should raise_error(Mongify::Mongoid::TranslationFileNotFound)
33
+ end
34
+ end
35
+
36
+ context "output folder" do
37
+ it "raises an error if folder exist" do
38
+ lambda { Mongify::Mongoid::CLI::Command::Worker.new(translation_file, output_folder).execute(view) }.should raise_error(Mongify::Mongoid::OverwritingFolder)
39
+ end
40
+ it "doesn't raise error if overwrite is true" do
41
+ lambda { Mongify::Mongoid::CLI::Command::Worker.new(translation_file, output_folder, :overwrite => true).execute(view) }.should_not raise_error(Mongify::Mongoid::OverwritingFolder)
42
+ end
43
+ end
44
+
45
+ end
@@ -0,0 +1,123 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mongify::Mongoid::Generator do
4
+ context "Instance Methods" do
5
+ context "process" do
6
+
7
+ let(:translation_file) { "spec/files/translation.rb" }
8
+ let(:output_dir){File.expand_path('../../../files/tmp', File.dirname(__FILE__))}
9
+ subject(:generator) { Mongify::Mongoid::Generator.new(translation_file, output_dir) }
10
+
11
+ it "is successful" do
12
+ subject.should_receive(:generate_models)
13
+ subject.should_receive(:process_fields)
14
+ subject.should_receive(:generate_embedded_relations)
15
+ subject.should_receive(:write_models_to_file)
16
+
17
+ subject.process
18
+ end
19
+
20
+ context "file doesnt exists" do
21
+ subject { Mongify::Mongoid::Generator.new("/my/awesome/file.ext", output_dir) }
22
+
23
+ it "should raise FileNotFound exception" do
24
+ expect { subject.process }.to raise_error(Mongify::Mongoid::FileNotFound)
25
+ end
26
+ end
27
+
28
+ context "generate_models" do
29
+ let(:table) { stub(name: 'users', columns: [], polymorphic?: false) }
30
+ it "should build model" do
31
+ subject.models.should be_empty
32
+ subject.send("build_model", table)
33
+ subject.should have(1).model
34
+ model = subject.models[table.name.to_sym]
35
+ model.table_name.should == table.name
36
+ end
37
+ end
38
+ context "process_fields" do
39
+ let(:table) { stub(name: 'users', columns: [], ignored?: false, polymorphic?: false) }
40
+ before(:each) do
41
+ table.stub(:columns).and_return([stub(name: "first_name", type: "string", options: {}), stub(name: "last_name", type: "string", options:{})])
42
+ subject.translation.stub(:all_tables).and_return([table])
43
+ subject.generate_models
44
+ end
45
+ it "works" do
46
+ subject.send(:translation).should_receive(:find).with(table.name).and_return(table)
47
+ subject.process_fields
48
+ model = subject.find_model(table.name)
49
+ model.should have(2).fields
50
+ end
51
+ end
52
+
53
+ context "embedded_relations" do
54
+ let(:table) { stub(name: 'preferences', columns: [stub(name: "Email", type:"string")], polymorphic?: false) }
55
+ let(:parent_model){ Mongify::Mongoid::Model.new(:table_name => "users", :class_name => "User")}
56
+ before(:each) do
57
+ table.stub(:embed_in).and_return('users')
58
+ table.stub(:embedded_as_object?).and_return(true)
59
+ subject.generate_models
60
+ generator.models[parent_model.table_name.to_sym] = parent_model
61
+ @model = subject.send("extract_embedded_relations", table)
62
+ end
63
+
64
+ context "model relations" do
65
+ it "should add embedded_in relations" do
66
+ @model.should have_relation(Mongify::Mongoid::Model::Relation::EMBEDDED_IN).for_association(parent_model.table_name)
67
+ end
68
+ end
69
+ context "parent model relations" do
70
+ it "should add embeds_one " do
71
+ parent_model.should have_relation(Mongify::Mongoid::Model::Relation::EMBEDS_ONE).for_association(@model.table_name)
72
+ end
73
+ end
74
+ end
75
+
76
+ context "polymorphic tables" do
77
+ let(:table) { stub(name: 'users', columns: [], ignored?: false, polymorphic?: false) }
78
+ let(:polymorphic_table){ stub(name: 'notes', columns: [], ignored?: false, polymorphic?: true, polymorphic_as: "notable") }
79
+ before(:each) do
80
+ table.stub(:columns).and_return([stub(name: "first_name", type: "string", options: {}), stub(name: "last_name", type: "string", options:{})])
81
+ tables = [table, polymorphic_table]
82
+ tables.each do |_table|
83
+ subject.translation.stub(:find).with(_table.name).and_return(_table)
84
+ end
85
+
86
+ subject.translation.stub(:all_tables).and_return(tables)
87
+ subject.generate_models
88
+ end
89
+ it "should have model" do
90
+ model = subject.find_model(polymorphic_table.name)
91
+ model.should_not be_nil
92
+ model.should be_polymorphic
93
+ end
94
+
95
+ it "should not add polymorphic fields" do
96
+ subject.process_fields
97
+ model = subject.find_model(polymorphic_table.name)
98
+ model.should_not have_relation(:belongs_to)
99
+ end
100
+ end
101
+
102
+ context "generate_fields_for" do
103
+ let(:model) {generator.send(:build_model, stub(name: "users", polymorphic?: false))}
104
+ let(:parent_model) {generator.send(:build_model, stub(name: "accounts", polymorphic?: false))}
105
+ let(:table) {stub(name: "users", columns: [stub(name: "account_id", type: "id", options: {'references' => "accounts"})], polymorphic?: false)}
106
+ before(:each) do
107
+ model #generate via rspec
108
+ parent_model #generate via rspec
109
+ generator.translation.stub(:find).with(model.table_name).and_return(table)
110
+ end
111
+ it "adds correctly" do
112
+ generator.send(:generate_fields_for, model, table)
113
+ model.should have_relation(Mongify::Mongoid::Model::Relation::BELONGS_TO).for_association("account")
114
+ parent_model.should have_relation(Mongify::Mongoid::Model::Relation::HAS_MANY).for_association("users")
115
+ end
116
+ end
117
+
118
+ after(:all) do
119
+ FileUtils.rm Dir["#{output_dir}/*.rb"]
120
+ end
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,31 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mongify::Mongoid::Model::Field do
4
+ subject(:field){ Mongify::Mongoid::Model::Field.new("first_name", "String") }
5
+ context "types" do
6
+ context "validation" do
7
+ it "doesn't raise error when valid value" do
8
+ expect { Mongify::Mongoid::Model::Field.new("first_name", "String") }.to_not raise_error
9
+ end
10
+ it "does raise error on invalid value" do
11
+ expect { Mongify::Mongoid::Model::Field.new("first_name", "Limb") }.to raise_error(Mongify::Mongoid::InvalidField)
12
+ end
13
+ end
14
+
15
+ context "translation" do
16
+ [:array, :bigdecimal, :boolean, :date, :datetime, :float, :hash, :integer, :objectid, :binary, :range, :regexp, :string, :symbol, :time, :timewithzone].each do |type|
17
+ it "for #{type} works" do
18
+ field.send(:translate_type, type).should == Mongify::Mongoid::Model::Field::TRANSLATION_TYPES[type]
19
+ end
20
+ end
21
+ it "for Text is String" do
22
+ field.send(:translate_type, 'Text').should == "String"
23
+ end
24
+ it "uses original name if no translation was found" do
25
+ type = "Limb"
26
+ field.send(:translate_type, type).should == type
27
+ end
28
+ end
29
+
30
+ end
31
+ end
@@ -0,0 +1,42 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mongify::Mongoid::Model::Relation do
4
+ describe "VALID_RELATIONS" do
5
+ subject { Mongify::Mongoid::Model::Relation::VALID_RELATIONS }
6
+
7
+ it { should =~ %w(embeds_one embeds_many embedded_in has_one has_many has_and_belongs_to_many belongs_to) }
8
+ end
9
+
10
+ context "singularize" do
11
+ [Mongify::Mongoid::Model::Relation::BELONGS_TO,
12
+ Mongify::Mongoid::Model::Relation::EMBEDDED_IN,
13
+ Mongify::Mongoid::Model::Relation::EMBEDS_ONE].each do |relation|
14
+ it "#{relation}" do
15
+ r = Mongify::Mongoid::Model::Relation.new(relation, "posts")
16
+ r.association.should == "post"
17
+ end
18
+ end
19
+
20
+ end
21
+
22
+ describe "initialize" do
23
+ context "invalid relation name" do
24
+ it "should raise InvalidRelation error" do
25
+ expect {
26
+ @relation = Mongify::Mongoid::Model::Relation.new(:brother, "user", {})
27
+ }.to raise_error Mongify::Mongoid::InvalidRelation
28
+ end
29
+ end
30
+
31
+ context "valid relation name" do
32
+ before do
33
+ @relation = Mongify::Mongoid::Model::Relation.new(:embeds_one, "user", {})
34
+ end
35
+
36
+ subject { @relation }
37
+ its(:name) { should == "embeds_one" }
38
+ its(:association) { should == "user" }
39
+ its(:options) { should == {} }
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,146 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mongify::Mongoid::Model do
4
+ subject(:model) { Mongify::Mongoid::Model.new(:table_name => "users", :class_name => "User") }
5
+
6
+ describe "initialize" do
7
+ its(:class_name) { should == "User" }
8
+ its(:table_name) { should == "users" }
9
+ end
10
+
11
+ describe "add_field" do
12
+ before(:each) { model.add_field("name", "String") }
13
+ it { should have_field("name").of_type("String") }
14
+ it "doesn't add the id column" do
15
+ model.add_field("id", "integer")
16
+ model.should_not have_field("id")
17
+ end
18
+ it "doesn't add ignored columns" do
19
+ model.add_field("first_name", "String", {ignore: true})
20
+ model.should_not have_field("first_name")
21
+ end
22
+ it "renames fields" do
23
+ model.add_field("sur_name", "String", {rename_to: "last_name"})
24
+ model.should_not have_field("sur_name")
25
+ model.should have_field("last_name")
26
+ end
27
+ it "doesn't add a reference columns" do
28
+ model.add_field("user_id", "integer", {references: 'users'})
29
+ model.should_not have_field("user_id")
30
+ end
31
+ it "raises error if field is unkown" do
32
+ expect { model.add_field("user_id", 'limb') }.to raise_error(
33
+ Mongify::Mongoid::InvalidField,
34
+ "Unkown field type limb for user_id in #{model.class_name}")
35
+ end
36
+ end
37
+
38
+ it "should find relation" do
39
+ model.add_relation(Mongify::Mongoid::Model::Relation::BELONGS_TO, "accounts")
40
+ model.add_relation(Mongify::Mongoid::Model::Relation::HAS_MANY, "posts")
41
+ r = model.send(:find_relation_by, "accounts")
42
+ r.association.should == "account"
43
+ r.name.should == Mongify::Mongoid::Model::Relation::BELONGS_TO
44
+ end
45
+
46
+ it "should delete relation" do
47
+ model.add_relation(Mongify::Mongoid::Model::Relation::BELONGS_TO, "accounts")
48
+ model.add_relation(Mongify::Mongoid::Model::Relation::HAS_MANY, "posts")
49
+ model.send(:delete_relation_for, "accounts")
50
+ model.should have(1).relation
51
+ end
52
+
53
+ describe "Timestamps" do
54
+ it "doesn't at created_at field" do
55
+ model.add_field("created_at", "Datetime")
56
+ model.should have(0).fields
57
+ end
58
+ it "doesn't at updated_at field" do
59
+ model.add_field("updated_at", "Datetime")
60
+ model.should have(0).fields
61
+ end
62
+
63
+ it "has a created_at timestamp" do
64
+ model.should_not have_created_at_timestamp
65
+ model.add_field("created_at", "Datetime")
66
+ model.should have_created_at_timestamp
67
+ end
68
+
69
+ it "has a updated_at timestamp" do
70
+ model.should_not have_updated_at_timestamp
71
+ model.add_field("updated_at", "Datetime")
72
+ model.should have_updated_at_timestamp
73
+ end
74
+
75
+ it "has timestamps" do
76
+ model.should_not have_timestamps
77
+ model.add_field("updated_at", "Datetime")
78
+ model.should have_timestamps
79
+ end
80
+
81
+ it "has both timestamps" do
82
+ model.should_not have_both_timestamps
83
+ model.add_field("created_at", "Datetime")
84
+ model.add_field("updated_at", "Datetime")
85
+ model.should have_both_timestamps
86
+ end
87
+
88
+ it "doesn't add ignored timestamps" do
89
+ model.add_field("created_at", "Datetime", ignore: true)
90
+ model.should_not have_timestamps
91
+ end
92
+ end
93
+
94
+ context "polymorphic name" do
95
+ before(:each) do
96
+ model.polymorphic_as = "userable"
97
+ end
98
+ it "should match" do
99
+ model.send("polymorphic_field?", "userable_id").should be_true
100
+ model.send("polymorphic_field?", "userable_type").should be_true
101
+ end
102
+ it "doesn't match" do
103
+ model.send("polymorphic_field?", "user_name").should be_false
104
+ model.send("polymorphic_field?", "userable_other").should be_false
105
+ end
106
+
107
+ end
108
+
109
+ describe "add_relation" do
110
+ let(:associated) { "preferences" }
111
+ Mongify::Mongoid::Model::Relation::VALID_RELATIONS.each do |relation|
112
+ context relation do
113
+ before { model.add_relation(relation, associated) }
114
+ it { should have_relation(relation).for_association(associated) }
115
+ end
116
+ end
117
+
118
+ context "embedded relations overpower relational relations" do
119
+ let(:association){"comments"}
120
+ it "works" do
121
+ model.add_relation(Mongify::Mongoid::Model::Relation::HAS_MANY, association)
122
+ model.add_relation(Mongify::Mongoid::Model::Relation::EMBEDS_MANY, association)
123
+ model.relations.should have(1).relation
124
+ relation = model.relations.first
125
+ relation.name.should == Mongify::Mongoid::Model::Relation::EMBEDS_MANY
126
+ relation.association = association
127
+ end
128
+
129
+ it "works with belongs_to as well" do
130
+ model.add_relation(Mongify::Mongoid::Model::Relation::BELONGS_TO, association.singularize)
131
+ model.add_relation(Mongify::Mongoid::Model::Relation::EMBEDDED_IN, association)
132
+ model.relations.should have(1).relation
133
+ relation = model.relations.first
134
+ relation.name.should == Mongify::Mongoid::Model::Relation::EMBEDDED_IN
135
+ relation.association = association
136
+ end
137
+
138
+ it "doesn't delete embedded" do
139
+ model.add_relation(Mongify::Mongoid::Model::Relation::EMBEDS_MANY, association)
140
+ model.add_relation(Mongify::Mongoid::Model::Relation::HAS_MANY, association)
141
+ model.relations.should have(1).relation
142
+ end
143
+
144
+ end
145
+ end
146
+ end