mongify-mongoid 1.0.0

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