opal_orm 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f1cd945fd3b9484b0580826d90a4d9bcd537ca4b
4
+ data.tar.gz: 0ba5cb818f4320bfce0660722fec1cab525dc0d1
5
+ SHA512:
6
+ metadata.gz: c25f6c0b2496dc42e5d3429132290b191d587438b6ab77ba4747a3ce36b36bbe5fb9f6164d54958f7ed70e014e34fe581c511347956b63730f87037e0f515fa6
7
+ data.tar.gz: 11ef2d0c87d8a977877320b1e579f48ac15924b00207ab932c399dcabf2728ae0919264c429a8c2392d61f05dafe065fbc7dad06202134a4be038c5352eccc4b
data/.gitignore ADDED
@@ -0,0 +1,13 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ /db/
11
+ opal_orm-*.gem
12
+
13
+ notes
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1.2
4
+ before_install: gem install bundler -v 1.11.2
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in opal_orm.gemspec
4
+ gemspec
5
+ require 'pry'
6
+ gem 'thor'
7
+ gem 'rspec'
8
+ gem 'activesupport'
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Nathan Matteson
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,118 @@
1
+ # OpalOrm
2
+
3
+ Welcome to OpalORM! OpalORM is a lightweight object-relational mapper for Ruby. With it you
4
+ can define a schema for your models, and then set up relations between them for easy access in your project.
5
+
6
+ Note: this gem is in its early stages and should not be trusted with important data. If you want stronger validations,
7
+ security, and more features, look no further than the library that inspired OpalORM: [ActiveRecord](https://github.com/rails/rails/tree/master/activerecord).
8
+
9
+ ## Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ ```ruby
14
+ gem 'opal_orm'
15
+ ```
16
+
17
+ And then execute:
18
+
19
+ $ bundle
20
+
21
+ Or install it yourself as:
22
+
23
+ $ gem install opal_orm
24
+
25
+ In the root folder of your project, create a file named `Rakefile` if you don't have one already.
26
+
27
+ Paste the following into your Rakefile:
28
+
29
+ ```ruby
30
+ spec = Gem::Specification.find_by_name 'opal_orm'
31
+ load "#{spec.gem_dir}/lib/tasks/opal_db.rake"
32
+ ```
33
+
34
+ ## Usage
35
+
36
+ ### Database setup
37
+
38
+ To start, run:
39
+
40
+ $ opal_orm create DATABASE_NAME
41
+
42
+ which will create an empty Sqlite database in `./db/DATABASE_NAME.db`.
43
+
44
+ Then, run:
45
+
46
+ $ opal_orm generate SCHEMA_NAME TABLE1 TABLE2 ...
47
+
48
+ Where `SCHEMA_NAME` is the name of the new schema, `TABLE1`, `TABLE2` etc. are the names
49
+ of the tables you'd like to generate. You can define more tables in the schema file if you
50
+ need to.
51
+
52
+ The schema file will be placed in `./db/SCHEMA_NAME.rb`.
53
+
54
+ Inside your schema file, define each table in a `create_table` block.
55
+
56
+ For example,
57
+
58
+ ```ruby
59
+ create_table("cats") do |t|
60
+ t.string :name
61
+ t.integer :toy_count
62
+ end
63
+ ```
64
+
65
+ corresponds to
66
+
67
+ ```sql
68
+ CREATE TABLE cats (
69
+ id INTEGER PRIMARY KEY,
70
+ name VARCHAR(255),
71
+ toy_count INTEGER
72
+ );
73
+ ```
74
+
75
+ (The primary key column is generated automatically.)
76
+
77
+ Currently, the only supported column types are string and integer. More to come!
78
+
79
+ Once your schema file is ready, run the following rake task to convert it to SQL
80
+ and add it to the database:
81
+
82
+ $ rake opal_db:setup schema=SCHEMA_FILE
83
+
84
+ ### Using OpalORM::SQLObject
85
+
86
+ To use OpalORM's core features, inherit your models from `OpalORM::SQLObject`:
87
+
88
+ ```ruby
89
+ class Cat < OpalORM::SQLObject
90
+ end
91
+ ```
92
+
93
+ Instantiate a class like normal, then access data using `all`, `find`, and `where`:
94
+
95
+ ```ruby
96
+ c = Cat.new
97
+ c.name = "Mr. Bojangles"
98
+ c.save
99
+
100
+ puts Cat.find(1).name
101
+ puts Cat.all
102
+ puts Cat.where(name: "Mr. Bojangles")
103
+ ```
104
+
105
+ <!-- ## Development
106
+
107
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
108
+
109
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org). -->
110
+
111
+ ## Contributing
112
+
113
+ Bug reports and pull requests are welcome on GitHub at https://github.com/nmatte/OpalORM.
114
+
115
+
116
+ ## License
117
+
118
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+ require "./lib/opal_orm"
4
+ require_relative "lib/opal_orm/schema_manager"
5
+ import "./lib/tasks/opal_db.rake"
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "opal_orm"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "pry"
14
+ Pry.start
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/exe/opal_orm ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby -wU
2
+
3
+ require 'opal_orm'
4
+
5
+ OpalORM::DatabaseManager.start(ARGV)
data/lib/opal_orm.rb ADDED
@@ -0,0 +1,14 @@
1
+ require "opal_orm/version"
2
+ require_relative "opal_orm/cli"
3
+ require_relative 'opal_orm/db_connection'
4
+ require_relative 'opal_orm/sql_object'
5
+ require_relative 'opal_orm/schema_manager'
6
+ require_relative 'opal_orm/searchable'
7
+ require_relative 'opal_orm/associatable'
8
+
9
+ module OpalORM
10
+ CURRENT_PATH = Dir.pwd
11
+ CONFIG_PATH = File.join(CURRENT_PATH, 'db/opal_config.json')
12
+ DB_PATH = File.join(CURRENT_PATH, 'db')
13
+ # Your code goes here...
14
+ end
@@ -0,0 +1,76 @@
1
+ require_relative 'searchable'
2
+ require 'active_support/inflector'
3
+
4
+ class AssocOptions
5
+ attr_accessor(
6
+ :foreign_key,
7
+ :class_name,
8
+ :primary_key
9
+ )
10
+
11
+ def model_class
12
+ class_name.constantize
13
+ end
14
+
15
+ def table_name
16
+ class_name.underscore + "s"
17
+ end
18
+ end
19
+
20
+ class BelongsToOptions < AssocOptions
21
+ def initialize(name, options = {})
22
+ @foreign_key = options[:foreign_key] || "#{name}_id".to_sym
23
+ @class_name = options[:class_name] || name.to_s.camelcase
24
+ @primary_key = options[:primary_key] || :id
25
+ end
26
+ end
27
+
28
+ class HasManyOptions < AssocOptions
29
+ def initialize(name, self_class_name, options = {})
30
+ @foreign_key = options[:foreign_key] || "#{self_class_name.downcase}_id".to_sym
31
+ @class_name = options[:class_name] || name.to_s.camelcase.singularize
32
+ @primary_key = options[:primary_key] || :id
33
+ end
34
+ end
35
+
36
+ module Associatable
37
+ def belongs_to(name, options = {})
38
+ assoc_options[name] = BelongsToOptions.new(name,options)
39
+ define_method(name) do
40
+ # p "within class"
41
+ # p @assoc_options = BelongsToOptions.new(name,options)
42
+ opts = self.class.assoc_options[name]
43
+ opts.model_class.find(self.send("#{opts.foreign_key}"))
44
+ end
45
+ end
46
+
47
+
48
+ def has_many(name, options = {})
49
+ define_method(name) do
50
+ @options = HasManyOptions.new(name,self.class.to_s,options)
51
+ cats = @options.model_class.where(@options.foreign_key => id)
52
+ end
53
+ end
54
+
55
+ def assoc_options
56
+ @assoc_options ||= {}
57
+ end
58
+
59
+ def has_one_through(name, through_name, source_name)
60
+ define_method(name) do
61
+ through_options = self.class.assoc_options[through_name]
62
+ source_options = through_options.model_class.assoc_options[source_name]
63
+ pk = 1
64
+ through =
65
+ through_options.model_class
66
+ .where(through_options.primary_key => id)
67
+ .first
68
+
69
+ source_options.model_class.find(through.id)
70
+ end
71
+ end
72
+ end
73
+
74
+ class SQLObject
75
+ extend Associatable
76
+ end
@@ -0,0 +1,48 @@
1
+ require 'thor'
2
+ require_relative 'query_builder'
3
+ require_relative 'db_connection'
4
+ require_relative 'schema_manager'
5
+ require_relative 'util'
6
+
7
+ module OpalORM
8
+ class DatabaseManager < Thor
9
+ desc "new DATABASE_NAME", "Create the database to be used by OpalORM"
10
+ long_desc <<-CREATE
11
+ Create an empty SQLite database in /db/DATABASE_NAME.db.
12
+ CREATE
13
+
14
+ def new(db_name)
15
+ Util.ensure_db_dir
16
+ name_with_ext = "#{db_name}.db"
17
+ db_file_path = File.join(Util.db_path, name_with_ext)
18
+ puts "Creating db/#{name_with_ext} ..."
19
+ DBConnection.open(db_file_path)
20
+ if File.exist?(db_file_path)
21
+ Util.ensure_db_dir
22
+ puts Util.db_path
23
+ Util.save_config({db_name: name_with_ext})
24
+ puts "#{name_with_ext} successfully created."
25
+ end
26
+ end
27
+ # TODO define next command
28
+ desc "generate SCHEMA_NAME TABLE1 TABLE2 ... ", "Create a blank schema file to be edited"
29
+ long_desc <<-GENERATE
30
+ Create a blank schema file called schema.rb. In it you can use the OpalORM
31
+ DSL to create tables with different datatypes.
32
+ Then create the schema with ``.
33
+ You may optionally pass the table names that you want to create. Otherwise you
34
+ will have to add them yourself.
35
+ GENERATE
36
+
37
+ def generate(file_name, *table_names)
38
+ OpalORM::SchemaManager.generate(file_name, *table_names)
39
+ rescue FileExistsError => e
40
+ puts e.message
41
+ puts "Aborting."
42
+ rescue ForeignKeyMissingError => e
43
+ puts e.message
44
+ puts "Aborting."
45
+ end
46
+ end
47
+
48
+ end
@@ -0,0 +1,65 @@
1
+ require 'sqlite3'
2
+ require 'json'
3
+ require_relative 'util'
4
+ PRINT_QUERIES = ENV['PRINT_QUERIES'] == 'true'
5
+ # https://tomafro.net/2010/01/tip-relative-paths-with-file-expand-path
6
+ # ROOT_FOLDER = File.join(File.dirname(__FILE__), '..')
7
+ # CATS_SQL_FILE = File.join(ROOT_FOLDER, 'cats.sql')
8
+ # CATS_DB_FILE = File.join(ROOT_FOLDER, 'cats.db')
9
+
10
+
11
+ module OpalORM
12
+ class DBConnection
13
+ def self.open(db_file_name)
14
+ @db = SQLite3::Database.new(db_file_name)
15
+ @db.results_as_hash = true
16
+ @db.type_translation = true
17
+ @db
18
+ end
19
+
20
+ # def self.reset
21
+ # commands = [
22
+ # "rm '#{CATS_DB_FILE}'",
23
+ # "cat '#{CATS_SQL_FILE}' | sqlite3 '#{CATS_DB_FILE}'"
24
+ # ]
25
+ #
26
+ # commands.each { |command| `#{command}` }
27
+ # DBConnection.open(CATS_DB_FILE)
28
+ # end
29
+ #
30
+ def self.instance
31
+ if Util.get_database_path
32
+ @db = open(Util.get_database_path)
33
+ end
34
+
35
+ @db
36
+ end
37
+
38
+ def self.execute(*args)
39
+ print_query(*args)
40
+ instance.execute(*args)
41
+ end
42
+
43
+ def self.execute2(*args)
44
+ print_query(*args)
45
+ instance.execute2(*args)
46
+ end
47
+
48
+ def self.last_insert_row_id
49
+ instance.last_insert_row_id
50
+ end
51
+
52
+ private
53
+
54
+ def self.print_query(query, *interpolation_args)
55
+ return unless PRINT_QUERIES
56
+
57
+ puts '--------------------'
58
+ puts query
59
+ unless interpolation_args.empty?
60
+ puts "interpolate: #{interpolation_args.inspect}"
61
+ end
62
+ puts '--------------------'
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,75 @@
1
+ require 'active_support/inflector'
2
+
3
+ module OpalORM
4
+ class QueryBuilder
5
+ def self.create_table_query(name, &prc)
6
+ manager = new(name)
7
+ prc.call(manager)
8
+
9
+ manager.build!
10
+ end
11
+
12
+ attr_reader :query
13
+
14
+ def initialize(name)
15
+ @table_name = name
16
+ @columns = []
17
+ @foreign_keys = []
18
+ end
19
+
20
+ def string(name, *options)
21
+ @columns << {type: :string, name: name, options: options}
22
+ end
23
+
24
+ def integer(name, *options)
25
+ @columns << {type: :integer, name: name, options: options}
26
+ end
27
+
28
+ # def foreign_key(ref_name)
29
+ # @foreign_keys << ref_name
30
+ # end
31
+
32
+ def build!
33
+ query_start = "CREATE TABLE #{@table_name} ("
34
+ column_queries = @columns.map do |col_info|
35
+ result = []
36
+ case col_info[:type]
37
+ when :string
38
+ result = "#{col_info[:name]} VARCHAR(255) "
39
+ when :integer
40
+ result = "#{col_info[:name]} INTEGER "
41
+ end
42
+ unless col_info[:options].nil?
43
+ col_info[:options].each do |key|
44
+ case col_info[:options]
45
+ when :null
46
+ result += "NOT NULL" unless col_info[:options][:null]
47
+ end
48
+ end
49
+ end
50
+ result
51
+ end
52
+ column_queries.unshift("id INTEGER PRIMARY KEY")
53
+
54
+ foreign_keys = @foreign_keys.map do |ref_name|
55
+ if foreign_key_valid?(ref_name)
56
+ "FOREIGN KEY(#{ref_name}) REFERENCES #{@table_name.singularize}(id)"
57
+ else
58
+ raise ForeignKeyMissingError, "Error adding foreign key contsraint for #{ref_name}: couldn't find column named #{ref_name}."
59
+ end
60
+ end
61
+
62
+ query_end = ");"
63
+
64
+ @query = query_start + column_queries.concat(foreign_keys).join(",\n") + query_end
65
+ @query
66
+ end
67
+
68
+ def foreign_key_valid?(key)
69
+ @columns.any? {|col| key == col[:name]}
70
+ end
71
+ end
72
+
73
+ class ForeignKeyMissingError < StandardError
74
+ end
75
+ end
@@ -0,0 +1,63 @@
1
+ require_relative 'util'
2
+ require_relative 'query_builder'
3
+ require_relative 'db_connection'
4
+ module OpalORM
5
+ class SchemaManager
6
+ Util.ensure_db_dir
7
+
8
+ def self.generate(file_name, *table_names)
9
+ schema_path = File.join(Util.db_path, "#{file_name}.rb")
10
+ if File.exist?(schema_path)
11
+ raise FileExistsError, "#{file_name}.rb already exists. Please choose a different filename."
12
+ else
13
+ puts "Creating file 'db/#{file_name}.rb' ..."
14
+ File.open(schema_path, "w+") do |f|
15
+ contents = []
16
+ if table_names.empty?
17
+ contents << <<-RB
18
+ create_table("table_name") do |t|
19
+ end
20
+ RB
21
+ else
22
+ contents += table_names.map do |table_name|
23
+ puts "adding table #{table_name} ..."
24
+ create_table_from_name(table_name)
25
+ end
26
+ contents.unshift(comment_string)
27
+ end
28
+ f.write(contents.join)
29
+ puts "Done."
30
+ end
31
+ end
32
+ end
33
+
34
+ def self.create_table_from_name(table_name)
35
+ <<-RB
36
+ create_table \'#{table_name}\' do |t|
37
+
38
+ end
39
+ RB
40
+ end
41
+
42
+ def comment_string
43
+ <<-RB
44
+ # Example usage:
45
+ # create_table 'table_name' do |t|
46
+ # t.string column_name
47
+ # end
48
+ #
49
+ # The primary key will be created automatically, with name 'id'.
50
+ RB
51
+ end
52
+
53
+ def create_table(table_name, &prc)
54
+ q = QueryBuilder.create_table_query(table_name, &prc)
55
+
56
+
57
+ DBConnection.execute(q)
58
+ end
59
+ end
60
+
61
+ class FileExistsError < StandardError
62
+ end
63
+ end
@@ -0,0 +1,24 @@
1
+ require_relative 'db_connection'
2
+ require_relative 'sql_object'
3
+ module OpalORM
4
+ module Searchable
5
+ def where(params)
6
+ where_clause = params.keys.map do |key|
7
+ "#{key.to_s} = ?"
8
+ end.join(" AND ")
9
+ results = DBConnection.execute(<<-SQL,params.values)
10
+ SELECT
11
+ *
12
+ FROM
13
+ #{table_name}
14
+ WHERE
15
+ #{where_clause}
16
+ SQL
17
+ results.map { |res| new(res)}
18
+ end
19
+ end
20
+ end
21
+
22
+ class OpalORM::SQLObject
23
+ extend OpalORM::Searchable
24
+ end
@@ -0,0 +1,147 @@
1
+ require_relative 'db_connection'
2
+ require 'active_support/inflector'
3
+
4
+ module OpalORM
5
+ class SQLObject
6
+ def initialize(params = {})
7
+ params.each do |attribute,val|
8
+ col_sym = attribute.to_sym
9
+ if self.class.columns.include?(col_sym)
10
+ self.send("#{col_sym}=",val)
11
+ else
12
+ raise "unknown attribute '#{attribute}'"
13
+ end
14
+ end
15
+ end
16
+
17
+ def self.columns
18
+ @cols ||= DBConnection.execute2(<<-SQL).first.map(&:to_sym)
19
+ SELECT
20
+ *
21
+ FROM
22
+ #{table_name}
23
+ SQL
24
+ end
25
+
26
+ def insert
27
+ columns = self.class.columns#.reject { |c| c.nil?}
28
+ cols = columns.join(", ")
29
+ placeholders = (["?"] * columns.length).join(", ")
30
+ DBConnection.execute(<<-SQL,*attribute_values)
31
+ INSERT INTO
32
+ #{self.class.table_name}(#{cols})
33
+ VALUES
34
+ (#{placeholders})
35
+ SQL
36
+ attributes[:id] = DBConnection.last_insert_row_id
37
+ end
38
+
39
+ def self.finalize!
40
+ columns.each do |col_sym|
41
+ define_getter(col_sym)
42
+ define_setter(col_sym)
43
+ end
44
+ end
45
+
46
+ def self.define_getter(attr_name)
47
+ define_method(attr_name) do
48
+ attributes[attr_name]
49
+ end
50
+ end
51
+
52
+ def self.define_setter(attr_name)
53
+ define_method("#{attr_name}=") do |new_val|
54
+ attributes[attr_name] = new_val
55
+ end
56
+ end
57
+
58
+ def self.table_name=(table_name)
59
+ @table_name = table_name
60
+ end
61
+
62
+ def self.table_name
63
+ @table_name ||= self.to_s.downcase.pluralize
64
+ end
65
+
66
+ def self.all
67
+ query = <<-SQL
68
+ SELECT
69
+ *
70
+ FROM
71
+ #{self.table_name}
72
+ SQL
73
+ objs = DBConnection.execute(query)
74
+ parse_all(objs)
75
+ end
76
+
77
+ def self.parse_all(results)
78
+ objs = []
79
+ results.each do |obj|
80
+ objs << new(obj)
81
+ end
82
+ objs
83
+ end
84
+
85
+ def self.find(id)
86
+ result = DBConnection.execute(<<-SQL,id)
87
+ SELECT
88
+ *
89
+ FROM
90
+ #{table_name}
91
+ WHERE
92
+ id = ?
93
+ SQL
94
+ return nil if result.empty?
95
+ new(result.first)
96
+ end
97
+
98
+ def attributes
99
+ @attributes ||= {}
100
+ end
101
+
102
+ def attribute_values
103
+ self.class.columns.map do |col|
104
+ attributes[col]
105
+ end
106
+ end
107
+
108
+ def update
109
+ cols = self.class
110
+ .columns
111
+ .map { |col_name| "#{col_name} = ?"}
112
+ .join(", ")
113
+ DBConnection.execute(<<-SQL,*attribute_values - [:id], id)
114
+ UPDATE
115
+ #{self.class.table_name}
116
+ SET
117
+ #{cols}
118
+ WHERE
119
+ id = ?
120
+ SQL
121
+ end
122
+
123
+ def save
124
+ id.nil? ? insert : update
125
+ end
126
+
127
+ def self.is_column?(col_sym)
128
+ self.columns.include?(col_sym)
129
+ end
130
+
131
+ def method_missing(method_sym, *args)
132
+ if self.class.is_column?(method_sym)
133
+ self.class.define_getter(method_sym)
134
+ return send(method_sym)
135
+ end
136
+
137
+ setter_name = /(.*)=/.match(method_sym)
138
+ if setter_name && self.class.is_column?(setter_name[1].to_sym)
139
+ self.class.define_setter(setter_name[1].to_sym)
140
+ p method_sym
141
+ send(method_sym, args[0])
142
+ else
143
+ super(method_sym, args)
144
+ end
145
+ end
146
+ end
147
+ end
@@ -0,0 +1,49 @@
1
+ module OpalORM
2
+ class Util
3
+ def self.ensure_db_dir
4
+ unless Dir.exist?(self.db_path)
5
+ Dir.mkdir('db')
6
+ end
7
+ end
8
+
9
+ def self.current_path
10
+ Dir.pwd
11
+ end
12
+
13
+ def self.db_path
14
+ File.join(self.current_path, 'db')
15
+ end
16
+
17
+ def self.config_path
18
+ File.join(self.db_path, 'opal_config.json')
19
+ end
20
+
21
+ def self.get_config
22
+ if File.exists?(Util.config_path)
23
+ JSON.parse(File.read(Util.config_path))|| {}
24
+ end
25
+ end
26
+
27
+ def self.get_database_path
28
+ db_name = get_config["db_name"]
29
+ if db_name
30
+ File.join(db_path, db_name)
31
+ end
32
+ end
33
+
34
+ def self.make_config
35
+ Util.ensure_db_dir
36
+
37
+ unless File.exists?(Util.config_path)
38
+ File.new(Util.config_path, 'w')
39
+ end
40
+ end
41
+
42
+ def self.save_config(new_config)
43
+ File.open(Util.config_path, "w+") do |f|
44
+ f.write(new_config.to_json)
45
+ end
46
+ end
47
+ end
48
+
49
+ end
@@ -0,0 +1,3 @@
1
+ module OpalOrm
2
+ VERSION = "0.2.0"
3
+ end
@@ -0,0 +1,9 @@
1
+ require_relative "../opal_orm/schema_manager.rb"
2
+
3
+ namespace :opal_db do
4
+ desc "Resets the database with the given schema file."
5
+ task :setup do
6
+
7
+ OpalORM::SchemaManager.new.instance_eval File.read("./db/#{ENV["schema"]}")
8
+ end
9
+ end
data/opal_orm.gemspec ADDED
@@ -0,0 +1,40 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'opal_orm/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "opal_orm"
8
+ spec.version = OpalOrm::VERSION
9
+ spec.authors = ["Nathan Matteson"]
10
+ spec.email = ["nwmatteson@gmail.com"]
11
+
12
+ spec.summary = %q{OpalORM is a small object-relational mapper for Ruby.}
13
+ spec.description = %q{OpalORM is a lightweight object-relational mapper for Ruby. With it you
14
+ can define a schema for your models, and then set up relations between them for easy access in your project.}
15
+ spec.homepage = "http://github.com/nmatte/OpalORM"
16
+ spec.license = "MIT"
17
+
18
+ # Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
19
+ # delete this section to allow pushing this gem to any host.
20
+ if spec.respond_to?(:metadata)
21
+ spec.metadata['allowed_push_host'] = "https://rubygems.org"
22
+ else
23
+ raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
24
+ end
25
+
26
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
27
+
28
+ spec.bindir = "exe"
29
+ # spec.executables = ["./bin/opal_orm"]
30
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
31
+ # spec.executables << "opal_orm"
32
+ spec.require_paths = ["lib"]
33
+
34
+ spec.add_runtime_dependency 'sqlite3', '1.3.11'
35
+ spec.add_dependency 'thor','0.19.1'
36
+ spec.add_dependency 'activesupport', '4.2.5'
37
+ spec.add_development_dependency "bundler", "~> 1.11"
38
+ spec.add_development_dependency "rake", "~> 10.0"
39
+ spec.add_development_dependency "rspec", "~> 3.0"
40
+ end
metadata ADDED
@@ -0,0 +1,154 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: opal_orm
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - Nathan Matteson
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2016-03-17 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: sqlite3
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '='
18
+ - !ruby/object:Gem::Version
19
+ version: 1.3.11
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '='
25
+ - !ruby/object:Gem::Version
26
+ version: 1.3.11
27
+ - !ruby/object:Gem::Dependency
28
+ name: thor
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '='
32
+ - !ruby/object:Gem::Version
33
+ version: 0.19.1
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '='
39
+ - !ruby/object:Gem::Version
40
+ version: 0.19.1
41
+ - !ruby/object:Gem::Dependency
42
+ name: activesupport
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '='
46
+ - !ruby/object:Gem::Version
47
+ version: 4.2.5
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '='
53
+ - !ruby/object:Gem::Version
54
+ version: 4.2.5
55
+ - !ruby/object:Gem::Dependency
56
+ name: bundler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.11'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.11'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '10.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '10.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '3.0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '3.0'
97
+ description: |-
98
+ OpalORM is a lightweight object-relational mapper for Ruby. With it you
99
+ can define a schema for your models, and then set up relations between them for easy access in your project.
100
+ email:
101
+ - nwmatteson@gmail.com
102
+ executables:
103
+ - opal_orm
104
+ extensions: []
105
+ extra_rdoc_files: []
106
+ files:
107
+ - ".gitignore"
108
+ - ".rspec"
109
+ - ".travis.yml"
110
+ - Gemfile
111
+ - LICENSE.txt
112
+ - README.md
113
+ - Rakefile
114
+ - bin/console
115
+ - bin/setup
116
+ - exe/opal_orm
117
+ - lib/opal_orm.rb
118
+ - lib/opal_orm/associatable.rb
119
+ - lib/opal_orm/cli.rb
120
+ - lib/opal_orm/db_connection.rb
121
+ - lib/opal_orm/query_builder.rb
122
+ - lib/opal_orm/schema_manager.rb
123
+ - lib/opal_orm/searchable.rb
124
+ - lib/opal_orm/sql_object.rb
125
+ - lib/opal_orm/util.rb
126
+ - lib/opal_orm/version.rb
127
+ - lib/tasks/opal_db.rake
128
+ - opal_orm.gemspec
129
+ homepage: http://github.com/nmatte/OpalORM
130
+ licenses:
131
+ - MIT
132
+ metadata:
133
+ allowed_push_host: https://rubygems.org
134
+ post_install_message:
135
+ rdoc_options: []
136
+ require_paths:
137
+ - lib
138
+ required_ruby_version: !ruby/object:Gem::Requirement
139
+ requirements:
140
+ - - ">="
141
+ - !ruby/object:Gem::Version
142
+ version: '0'
143
+ required_rubygems_version: !ruby/object:Gem::Requirement
144
+ requirements:
145
+ - - ">="
146
+ - !ruby/object:Gem::Version
147
+ version: '0'
148
+ requirements: []
149
+ rubyforge_project:
150
+ rubygems_version: 2.2.2
151
+ signing_key:
152
+ specification_version: 4
153
+ summary: OpalORM is a small object-relational mapper for Ruby.
154
+ test_files: []