Last active
March 17, 2020 00:26
-
-
Save mhasbini/ace22d7a10b891b4d59ea403a9ec2d5f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require './ruby_on_lane.rb' | |
# Schema | |
Schema.define('hello_app_database') do | |
table :users do | |
column :string, :name | |
column :int, :age | |
end | |
end | |
# Models | |
class User < Model | |
def self.adult? | |
self.age > 18 | |
end | |
end | |
# Seed | |
User.create(name: "John Doe", age: 42) | |
User.create(name: "Tipsy Lala", age: 25) | |
user = User.create(name: "Lorem Ipsum", age: 19) | |
user.name == "Lorem Ipsum" | |
# Routes | |
get '/' do | |
'Hello :)' | |
end | |
get '/filter' do | |
filter_age = params['age'] || 20 | |
count = User.where('age', '>', filter_age).count | |
"Number of users who are older than #{filter_age}: #{count}" | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'sqlite3' | |
require 'linguistics' | |
require 'rack' | |
class Adapter | |
@@db = nil | |
def table(_name, &block) | |
@columns = [] | |
self.instance_eval(&block) | |
if table_exists?(_name) | |
@columns.each do |column| | |
unless column_exists?(_name, column[:name]) | |
add_column(table: _name, column: column[:name], type: column[:type]) | |
end | |
end | |
else | |
create_table(table: _name, columns: @columns) | |
end | |
end | |
def column(_type, _name) | |
@columns << { | |
:type => map_type[_type], | |
:name => _name.to_s | |
} | |
end | |
end | |
class SQLiteAdapter < Adapter | |
def initialize(db_name) | |
@@db = SQLite3::Database.new db_name | |
end | |
def self.insert(table, params) | |
@@db.execute("INSERT INTO #{table} (#{params.keys.join(', ')}) | |
VALUES (#{(['?'] * params.count).join(', ')})", params.values) | |
end | |
def self.search(table, field, op, value) | |
columns = self.get_columns(table) | |
results = [] | |
@@db | |
.execute("SELECT #{columns.join(', ')} FROM #{table} WHERE #{field} #{op} #{value}") | |
.map do |result| | |
record = {} | |
result.each_with_index do |val, idx| | |
record[columns[idx]] = val | |
end | |
results << record | |
end | |
return results | |
end | |
def table_exists?(_name) | |
table_exists = @@db.execute("SELECT 1 FROM sqlite_master WHERE type='table' AND name=?", _name.to_s) | |
return !table_exists.empty? | |
end | |
def self.get_columns(_table) | |
@@db | |
.execute( | |
"SELECT name FROM pragma_table_info(?)", | |
_table.to_s | |
) | |
.flatten | |
end | |
def column_exists?(_table, _name) | |
@@db | |
.execute( | |
"SELECT COUNT(*) FROM pragma_table_info(?) WHERE name=?", | |
_table.to_s, | |
_name.to_s | |
) | |
.flatten | |
.all? { |n| n == 1} | |
end | |
def add_column(table:, column:, type:) | |
@@db.execute("ALTER TABLE #{table} ADD COLUMN #{column} #{type}") | |
end | |
def create_table(table:, columns:) | |
@@db.execute("CREATE TABLE #{table} (#{inline(columns)})") | |
end | |
# convert [{ | |
# :type => "string" | |
# :name => "test" | |
# }, ...] | |
# into: name type, name type, name type, | |
def inline(columns) | |
columns | |
.map { |column| "#{column[:name]} #{column[:type]}" } | |
.join(", ") | |
end | |
def map_type | |
{ | |
:string => "TEXT", | |
:int => "INTEGER" | |
} | |
end | |
end | |
module Schema | |
def self.define(db_name, &block) | |
adapter = SQLiteAdapter.new(db_name) | |
adapter.instance_eval(&block) | |
end | |
end | |
# source https://stackoverflow.com/a/1509939 | |
class String | |
def to_underscore | |
self.gsub(/::/, '/'). | |
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2'). | |
gsub(/([a-z\d])([A-Z])/,'\1_\2'). | |
tr("-", "_"). | |
downcase | |
end | |
end | |
Linguistics.use :en | |
class Model | |
def self.table | |
@table ||= self.name.to_underscore.en.plural | |
end | |
def self.create(params) | |
SQLiteAdapter.insert(self.table, params) | |
self.create_attributes(params) | |
self | |
end | |
def self.create_attributes(params) | |
SQLiteAdapter.get_columns(self.table).each do |column| | |
self.class.send(:define_method, column.to_sym) do | |
params.fetch(column.to_sym, nil) | |
end | |
end | |
end | |
def self.where(field, op, value) | |
SQLiteAdapter.search(self.table, field, op, value) | |
end | |
end | |
class User < Model | |
def self.adult? | |
self.age > 18 | |
end | |
end | |
class Handler | |
def initialize(&block) | |
@block = block | |
end | |
def params | |
@request.params | |
end | |
def call(env) | |
@request = Rack::Request.new(env) | |
@body = self.instance_eval(&@block) | |
[200, {"Content-Type" => "text/plain"}, [@body]] | |
end | |
end | |
class RubyOnLane | |
def self.app | |
@app ||= begin | |
Rack::Builder.new do | |
map "/" do | |
run ->(env) {[200, {'Content-Type' => 'text/plain'}, ['Ruby on Lane']] } | |
end | |
end | |
end | |
end | |
end | |
def get(pattern, &block) | |
RubyOnLane.app.map(pattern) do | |
run Handler.new(&block) | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'rack/server' | |
if ARGV.length > 1 | |
puts "Usage: ruby runner.rb app_name" | |
end | |
if ARGV.length == 1 | |
app_name = ARGV[0] | |
unless app_name.end_with?('.rb') | |
app_name = app_name + '.rb' | |
end | |
end | |
require File.expand_path(app_name) | |
Rack::Server.start :app => RubyOnLane.app |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment