djoini 0.1.2 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +115 -0
- data/Rakefile +2 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/lib/djoini/base.rb +28 -0
- data/lib/djoini/composite.rb +47 -0
- data/lib/djoini/configuration.rb +27 -0
- data/lib/djoini/connection.rb +31 -0
- data/lib/djoini/crud.rb +53 -0
- data/lib/djoini/fields.rb +30 -0
- data/lib/djoini/files.rb +34 -0
- data/lib/djoini/loaders/ini_loader.rb +33 -0
- data/lib/djoini/loaders/json_loader.rb +33 -0
- data/lib/djoini/record.rb +33 -0
- data/lib/djoini/relation.rb +35 -0
- data/lib/djoini/table.rb +86 -0
- data/lib/djoini/version.rb +3 -0
- data/lib/djoini.rb +9 -0
- data/lib/tasks/load.rake +25 -0
- data/spec/database.yml +5 -0
- data/spec/djoini/model_spec.rb +57 -0
- data/spec/djoini/task_fixtures/users.ini +11 -0
- data/spec/djoini/task_fixtures/users.json +4 -0
- data/spec/djoini/task_spec.rb +59 -0
- data/spec/models/post.rb +3 -0
- data/spec/models/user.rb +3 -0
- data/spec/spec_helper.rb +22 -0
- metadata +38 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 34a71a0db65d4024e67e0803aa1cf65448863ed3
|
4
|
+
data.tar.gz: d58e772585d90145b09d2cc103276356522877fe
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4ee443c72bc06ea95cb86e1f5e0fc02a415b2bd865f625ccf3a228f9e0632c8eb85bd22f1928a80f2fa13b14daa4a2bb373c2aa11ea0665f36323139a11402b5
|
7
|
+
data.tar.gz: e48ccdc6d6e2415092ed3d783ea1c6a2604e4ff34e695b97ef82ae7ccd38171e6561afc2114275626f16b9b6ef27b31deeb14259d9bafe14c3903c5f93c852e9
|
data/README.md
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
# Djoini
|
2
|
+
|
3
|
+
DJsOnINI is a implimentation of ActiveModel pattern and a fixture loader for json and ini formats. It implement's only a little part of pattern, so isn't usable in serious applications.
|
4
|
+
|
5
|
+
Thing's that are implemented:
|
6
|
+
- Djoini::Base class to inherit from
|
7
|
+
- Basic crud operations like
|
8
|
+
- create
|
9
|
+
- update
|
10
|
+
- find
|
11
|
+
- where
|
12
|
+
- destroy
|
13
|
+
- all
|
14
|
+
- delete_all
|
15
|
+
- Connection to the postgres database, via pg driver
|
16
|
+
- Rake task to load fixtures
|
17
|
+
- Config files via `Djoini.config` and .yaml for database
|
18
|
+
|
19
|
+
|
20
|
+
## Installation
|
21
|
+
|
22
|
+
Add this line to your application's Gemfile:
|
23
|
+
|
24
|
+
```ruby
|
25
|
+
gem 'djoini'
|
26
|
+
```
|
27
|
+
|
28
|
+
And then execute:
|
29
|
+
|
30
|
+
$ bundle
|
31
|
+
|
32
|
+
Or install it yourself as:
|
33
|
+
|
34
|
+
$ gem install djoini
|
35
|
+
|
36
|
+
## Usage
|
37
|
+
|
38
|
+
**Important**
|
39
|
+
Make appropriate tables or use other gem to create migrations. This gem doesn't handle migrations only mapping and loading.
|
40
|
+
|
41
|
+
Also you need to create database.yml in your `PWD/config/` folder with atleast this content to use local db with specified credentials.
|
42
|
+
|
43
|
+
```yaml
|
44
|
+
postgres:
|
45
|
+
adapter: postgresql
|
46
|
+
db_name: djoini_test
|
47
|
+
username: ruby
|
48
|
+
password: noway
|
49
|
+
```
|
50
|
+
|
51
|
+
### Model usage:
|
52
|
+
|
53
|
+
```ruby
|
54
|
+
# Model that will produce Post's object
|
55
|
+
class Post < Djoini::Base # Inherit from Base class to use the power of ActiveRecord
|
56
|
+
table_name :posts # Explicitly specify table name to be mapped to, scheme
|
57
|
+
# counted as 'public'.
|
58
|
+
end
|
59
|
+
```
|
60
|
+
|
61
|
+
After that just use them like you normaly would with ActiveModel:
|
62
|
+
|
63
|
+
```ruby
|
64
|
+
@user = User.create(name: 'Jack', last_name: 'Daniels')
|
65
|
+
@user.name = 'Nansy'
|
66
|
+
@user.last_name = 'Drew'
|
67
|
+
@user.age = 30
|
68
|
+
@user.save
|
69
|
+
```
|
70
|
+
|
71
|
+
For more examples see tests.
|
72
|
+
|
73
|
+
### Rake task usage
|
74
|
+
**Important**
|
75
|
+
- With `mixed` loading .ini files will be loaded first.
|
76
|
+
- All file names must be named after coresponding tables, nor models
|
77
|
+
|
78
|
+
To load fixtures all fixtures(both ini and json) from default directory(`PWD/db/fixtures`):
|
79
|
+
|
80
|
+
```
|
81
|
+
rake djoini:load
|
82
|
+
```
|
83
|
+
|
84
|
+
To load only ini fixtures:
|
85
|
+
|
86
|
+
```
|
87
|
+
rake djoini:load type=ini
|
88
|
+
```
|
89
|
+
|
90
|
+
To specify location of fixtures use configuration module:
|
91
|
+
|
92
|
+
```ruby
|
93
|
+
Djoini.config do |config|
|
94
|
+
config.fixtures_folder = 'path'
|
95
|
+
config.fixtures_type = 'ini/json/mixed'
|
96
|
+
end
|
97
|
+
```
|
98
|
+
Djoini will try to find `PWD/config/initializers/djoini.rb` and load it.
|
99
|
+
|
100
|
+
|
101
|
+
## Development
|
102
|
+
|
103
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake false` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
104
|
+
|
105
|
+
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).
|
106
|
+
|
107
|
+
## Contributing
|
108
|
+
|
109
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/faullik/djoini. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](contributor-covenant.org) code of conduct.
|
110
|
+
|
111
|
+
|
112
|
+
## License
|
113
|
+
|
114
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
115
|
+
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "djoini"
|
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 "irb"
|
14
|
+
IRB.start
|
data/bin/setup
ADDED
data/lib/djoini/base.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require_relative 'composite'
|
2
|
+
require_relative 'record'
|
3
|
+
require_relative 'relation'
|
4
|
+
|
5
|
+
module Djoini
|
6
|
+
# Basic abstract model to inherit
|
7
|
+
class Base
|
8
|
+
include Composable
|
9
|
+
|
10
|
+
def initialize(params)
|
11
|
+
features << Record.new(params)
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.inherited(child_class)
|
15
|
+
child_class.extend(ClassMethods)
|
16
|
+
end
|
17
|
+
|
18
|
+
# Holds method to specify table
|
19
|
+
module ClassMethods
|
20
|
+
include Composable
|
21
|
+
|
22
|
+
def table_name(table_name)
|
23
|
+
features << Relation.new(name: table_name,
|
24
|
+
record_class: self)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Djoini
|
2
|
+
# Handles array for dynamic attributes and the module to include
|
3
|
+
module Composable
|
4
|
+
def features
|
5
|
+
@__features__ ||= Composite.new
|
6
|
+
end
|
7
|
+
|
8
|
+
def respond_to_missing?(method, *_array)
|
9
|
+
features.reveives?(method)
|
10
|
+
end
|
11
|
+
|
12
|
+
def method_missing(method, *array, &block)
|
13
|
+
features.dispatch(method, *array, &block)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# Handles dynamic attributes of the model
|
18
|
+
class Composite
|
19
|
+
def initialize
|
20
|
+
self.recievers = []
|
21
|
+
end
|
22
|
+
|
23
|
+
def <<(method)
|
24
|
+
recievers.push(method)
|
25
|
+
end
|
26
|
+
|
27
|
+
def reveives?(method)
|
28
|
+
reciever(method)
|
29
|
+
end
|
30
|
+
|
31
|
+
def dispatch(method, *array, &block)
|
32
|
+
obj = reciever(method)
|
33
|
+
|
34
|
+
fail NoMethodError, "No component implements #{method}" unless obj
|
35
|
+
|
36
|
+
obj.send(method, *array, &block)
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def reciever(method)
|
42
|
+
recievers.find { |el| el.respond_to?(method) }
|
43
|
+
end
|
44
|
+
|
45
|
+
attr_accessor :recievers
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# Configuration provider
|
2
|
+
# Djoini.configure do |config|
|
3
|
+
# config.key1 = value
|
4
|
+
# config.key2 = value
|
5
|
+
# end
|
6
|
+
module Djoini
|
7
|
+
class << self
|
8
|
+
attr_accessor :configuration
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.configure
|
12
|
+
self.configuration ||= Configuration.new
|
13
|
+
yield(configuration)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Main configuration for app
|
17
|
+
class Configuration
|
18
|
+
# Fixtures config
|
19
|
+
attr_accessor :fixtures_folder
|
20
|
+
attr_accessor :fixtures_type
|
21
|
+
|
22
|
+
def initialize
|
23
|
+
self.fixtures_folder = File.join(Dir.pwd, '/db/fixtures')
|
24
|
+
self.fixtures_type = 'mixed'
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
require 'pg'
|
3
|
+
|
4
|
+
# Holds connection singleton class
|
5
|
+
module Djoini
|
6
|
+
def self.db
|
7
|
+
Connection.instance.conn
|
8
|
+
end
|
9
|
+
|
10
|
+
# Class to manage db connetion to postgres
|
11
|
+
class Connection
|
12
|
+
include Singleton
|
13
|
+
|
14
|
+
attr_reader :conn
|
15
|
+
|
16
|
+
def establish_connection(params)
|
17
|
+
_adapter = params.fetch('adapter', 'postgres')
|
18
|
+
_username = params.fetch('username')
|
19
|
+
_password = params.fetch('password')
|
20
|
+
_host = params.fetch('host', 'localhost')
|
21
|
+
_port = params.fetch('port', '5432')
|
22
|
+
_db_name = params.fetch('db_name')
|
23
|
+
|
24
|
+
@conn = PG.connect("#{_adapter}://#{_username}:#{_password}@#{_host}:#{_port}/#{_db_name}")
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
attr_writer :conn
|
30
|
+
end
|
31
|
+
end
|
data/lib/djoini/crud.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
module Djoini
|
2
|
+
# Holds basic crud operaions. Workds like wrapper above Table.
|
3
|
+
class Crud
|
4
|
+
def initialize(relation)
|
5
|
+
self.relation = relation
|
6
|
+
end
|
7
|
+
|
8
|
+
def create(values)
|
9
|
+
id = table.insert(values)[0]['id'].to_i
|
10
|
+
|
11
|
+
find(id)
|
12
|
+
end
|
13
|
+
|
14
|
+
def update(id, values)
|
15
|
+
table.update(where: { table.primary_key => id },
|
16
|
+
fields: values)
|
17
|
+
end
|
18
|
+
|
19
|
+
def find(id)
|
20
|
+
values = table.where(table.primary_key => id).first
|
21
|
+
|
22
|
+
return nil unless values
|
23
|
+
|
24
|
+
relation.new_record(values)
|
25
|
+
end
|
26
|
+
|
27
|
+
def where(params)
|
28
|
+
rows = table.where(params)
|
29
|
+
|
30
|
+
rows.map { |values| relation.new_record(values) }
|
31
|
+
end
|
32
|
+
|
33
|
+
def destroy(id)
|
34
|
+
table.delete(table.primary_key => id)
|
35
|
+
end
|
36
|
+
|
37
|
+
def all
|
38
|
+
table.all.map { |values| relation.new_record(values) }
|
39
|
+
end
|
40
|
+
|
41
|
+
def delete_all
|
42
|
+
table.delete_all
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
attr_accessor :relation
|
48
|
+
|
49
|
+
def table
|
50
|
+
relation.table
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Djoini
|
2
|
+
# Holds all fields and values in row\object
|
3
|
+
class Fields
|
4
|
+
def initialize(params)
|
5
|
+
self.data = {}
|
6
|
+
|
7
|
+
attributes = params.fetch(:attributes)
|
8
|
+
values = params.fetch(:values, {})
|
9
|
+
|
10
|
+
attributes.each { |name| data[name] = values[name.to_s] }
|
11
|
+
|
12
|
+
build_accessors(attributes)
|
13
|
+
end
|
14
|
+
|
15
|
+
def clone_hash
|
16
|
+
data.clone
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
attr_accessor :data
|
22
|
+
|
23
|
+
def build_accessors(attributes)
|
24
|
+
attributes.each do |name|
|
25
|
+
define_singleton_method(name) { data[name] }
|
26
|
+
define_singleton_method("#{name}=") { |value| data[name] = value }
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/djoini/files.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
require_relative 'loaders/ini_loader'
|
2
|
+
require_relative 'loaders/json_loader'
|
3
|
+
|
4
|
+
module Djoini
|
5
|
+
# Handles loading of ini and json fixtures
|
6
|
+
class Files
|
7
|
+
attr_accessor :path
|
8
|
+
|
9
|
+
def initialize(fixtures_path = '')
|
10
|
+
self.path = fixtures_path || Djoini.configuration.fixtures_folder
|
11
|
+
end
|
12
|
+
|
13
|
+
def load_files(type = 'mixed')
|
14
|
+
puts "Loading #{type} files from #{path}"
|
15
|
+
|
16
|
+
IniLoader.new(path).load_files(find_files('ini')) unless type == 'json'
|
17
|
+
JsonLoader.new(path).load_files find_files('json') unless type == 'ini'
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def find_files(type)
|
23
|
+
_files = []
|
24
|
+
|
25
|
+
Dir.foreach(path) do |file|
|
26
|
+
next unless File.extname(file) == ".#{type}"
|
27
|
+
_model = file.gsub(".#{type}", '')
|
28
|
+
_files << { model: _model, file: file }
|
29
|
+
end
|
30
|
+
|
31
|
+
_files
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'iniparse'
|
2
|
+
|
3
|
+
module Djoini
|
4
|
+
# Handles load of ini type files.
|
5
|
+
class IniLoader
|
6
|
+
attr_reader :path
|
7
|
+
|
8
|
+
def initialize(path)
|
9
|
+
self.path = path
|
10
|
+
end
|
11
|
+
|
12
|
+
# Accepts array of [ { model: name, file: File },.. ]
|
13
|
+
def load_files(array)
|
14
|
+
array.each do |fixture|
|
15
|
+
_model_table = Table.new(name: fixture[:model])
|
16
|
+
|
17
|
+
_data = parse_ini(fixture[:file])
|
18
|
+
|
19
|
+
_data.to_hash.each do |_, obj|
|
20
|
+
_model_table.insert(obj)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
attr_writer :path
|
28
|
+
|
29
|
+
def parse_ini(file)
|
30
|
+
IniParse.parse(File.read(File.join(path, file)))
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'multi_json'
|
2
|
+
|
3
|
+
module Djoini
|
4
|
+
# Handles load of ini type files.
|
5
|
+
class JsonLoader
|
6
|
+
attr_reader :path
|
7
|
+
|
8
|
+
def initialize(path)
|
9
|
+
self.path = path
|
10
|
+
end
|
11
|
+
|
12
|
+
# Accepts array of [ { model: name, file: File },.. ]
|
13
|
+
def load_files(array)
|
14
|
+
array.each do |fixture|
|
15
|
+
_model_table = Table.new(name: fixture[:model])
|
16
|
+
|
17
|
+
_data = parse_json(fixture[:file])
|
18
|
+
|
19
|
+
_data.each do |obj|
|
20
|
+
_model_table.insert(obj)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
attr_writer :path
|
28
|
+
|
29
|
+
def parse_json(file)
|
30
|
+
MultiJson.load(File.read(File.join(path, file)))
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require_relative 'composite'
|
2
|
+
require_relative 'fields'
|
3
|
+
|
4
|
+
module Djoini
|
5
|
+
# Holds creation and destruction of model, his fields
|
6
|
+
class Record
|
7
|
+
include Composable
|
8
|
+
|
9
|
+
def initialize(params)
|
10
|
+
self.key = params.fetch(:key, nil)
|
11
|
+
self.relation = params.fetch(:relation)
|
12
|
+
|
13
|
+
features << Fields.new(values: params.fetch(:values, {}),
|
14
|
+
attributes: relation.attributes)
|
15
|
+
end
|
16
|
+
|
17
|
+
def save
|
18
|
+
if key
|
19
|
+
relation.update(key, clone_hash)
|
20
|
+
else
|
21
|
+
relation.create(clone_hash)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def destroy
|
26
|
+
relation.destroy(key)
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
attr_accessor :relation, :key
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require_relative 'composite'
|
2
|
+
require_relative 'crud'
|
3
|
+
require_relative 'table'
|
4
|
+
|
5
|
+
module Djoini
|
6
|
+
# Hold creation of new records(rows\objects)
|
7
|
+
class Relation
|
8
|
+
include Composable
|
9
|
+
|
10
|
+
def initialize(params)
|
11
|
+
self.table = Table.new(name: params.fetch(:name))
|
12
|
+
|
13
|
+
self.record_class = params.fetch(:record_class)
|
14
|
+
|
15
|
+
features << Crud.new(self)
|
16
|
+
end
|
17
|
+
|
18
|
+
attr_reader :table
|
19
|
+
|
20
|
+
def attributes
|
21
|
+
table.columns.keys
|
22
|
+
end
|
23
|
+
|
24
|
+
def new_record(values)
|
25
|
+
record_class.new(relation: self,
|
26
|
+
values: values,
|
27
|
+
key: values[table.primary_key])
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
attr_accessor :record_class
|
33
|
+
attr_writer :table
|
34
|
+
end
|
35
|
+
end
|
data/lib/djoini/table.rb
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
module Djoini
|
2
|
+
# Holds basic table info and low-level operations
|
3
|
+
class Table
|
4
|
+
attr_reader :primary_key, :name, :columns
|
5
|
+
|
6
|
+
def initialize(params)
|
7
|
+
self.name = params.fetch(:name)
|
8
|
+
self.db = Djoini.db
|
9
|
+
self.columns = {}
|
10
|
+
|
11
|
+
parse_table_info
|
12
|
+
end
|
13
|
+
|
14
|
+
def insert(params)
|
15
|
+
check_keys params
|
16
|
+
|
17
|
+
_field_names = params.keys.join(', ')
|
18
|
+
|
19
|
+
_values = params.values.map { |a| %('#{a}') }.join(', ')
|
20
|
+
|
21
|
+
db.exec "insert into #{name} (#{_field_names}) values (#{_values})
|
22
|
+
returning #{primary_key}"
|
23
|
+
end
|
24
|
+
|
25
|
+
def update(params)
|
26
|
+
check_keys params[:fields]
|
27
|
+
|
28
|
+
db.exec "update #{name}
|
29
|
+
set #{bind_vars(params[:fields], ', ')}
|
30
|
+
where #{bind_vars(params[:where], ' AND ')}"
|
31
|
+
end
|
32
|
+
|
33
|
+
def where(params)
|
34
|
+
check_keys params
|
35
|
+
|
36
|
+
db.exec "select * from #{name}
|
37
|
+
where #{bind_vars(params, ' AND ')}"
|
38
|
+
end
|
39
|
+
|
40
|
+
def all
|
41
|
+
db.exec "select * from #{name}"
|
42
|
+
end
|
43
|
+
|
44
|
+
def delete(params)
|
45
|
+
db.exec "delete from #{name} where #{bind_vars(params, ', ')}"
|
46
|
+
end
|
47
|
+
|
48
|
+
def delete_all
|
49
|
+
db.exec "delete from #{name}"
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
attr_accessor :db
|
55
|
+
attr_writer :primary_key, :name, :columns
|
56
|
+
|
57
|
+
def check_keys(params)
|
58
|
+
fail unless params.keys.all? { |e| columns.key?(e.to_s) }
|
59
|
+
end
|
60
|
+
|
61
|
+
def bind_vars(params, separator)
|
62
|
+
check_keys params
|
63
|
+
|
64
|
+
params.map { |k, v| "#{k} = #{evaluate_value(v)}" }.join(separator)
|
65
|
+
end
|
66
|
+
|
67
|
+
def evaluate_value(value)
|
68
|
+
return "'#{value}'" unless value.to_s.empty?
|
69
|
+
'NULL'
|
70
|
+
end
|
71
|
+
|
72
|
+
def parse_table_info
|
73
|
+
_raw_data = db.exec("SELECT *
|
74
|
+
FROM information_schema.columns
|
75
|
+
WHERE table_schema = 'public'
|
76
|
+
AND table_name = '#{name}'")
|
77
|
+
_raw_data.each do |row|
|
78
|
+
column_name = row['column_name']
|
79
|
+
|
80
|
+
self.primary_key ||= column_name
|
81
|
+
|
82
|
+
columns[column_name] = { type: row['data_type'] }
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
data/lib/djoini.rb
ADDED
data/lib/tasks/load.rake
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
|
2
|
+
namespace :djoini do
|
3
|
+
desc 'Load fixtures'
|
4
|
+
task :load do |_, args|
|
5
|
+
require_relative '../djoini'
|
6
|
+
|
7
|
+
require File.expand_path('/config/initializers/djoini.rb')
|
8
|
+
# To make sure configure was called if initializer wasn't foundw
|
9
|
+
Djoini.configure {}
|
10
|
+
|
11
|
+
_conn_info = YAML.load(File.read(Dir.pwd + '/config/database.yml'))
|
12
|
+
Djoini::Connection.instance.establish_connection(_conn_info['postgres'])
|
13
|
+
|
14
|
+
# Path taken from configuration
|
15
|
+
_loader = Djoini::File.new
|
16
|
+
|
17
|
+
if args[:type] == 'ini' || Djoini.configuration.fixtures_type == 'ini'
|
18
|
+
_loader.load_files('ini')
|
19
|
+
elsif args[:type] == 'json' || Djoini.configuration.fixtures_type == 'json'
|
20
|
+
_loader.load_files('json')
|
21
|
+
else
|
22
|
+
_loader.load_files
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/spec/database.yml
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Djoini::Base do
|
4
|
+
context 'model of User' do
|
5
|
+
before(:each) do
|
6
|
+
User.delete_all
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'expected to set one value' do
|
10
|
+
_user = User.create(name: 'Jack', last_name: 'Daniels')
|
11
|
+
_user.name = 'Jack'
|
12
|
+
_user.save
|
13
|
+
|
14
|
+
expect(User.find(_user.id).name).to eq 'Jack'
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'expected to update multiple values' do
|
18
|
+
_user = User.create(name: 'Jack', last_name: 'Daniels')
|
19
|
+
_user.name = 'Nansy'
|
20
|
+
_user.last_name = 'Drew'
|
21
|
+
_user.age = 30
|
22
|
+
_user.save
|
23
|
+
|
24
|
+
_new_user = User.find(_user.id)
|
25
|
+
expect(_new_user.name).to eq 'Nansy'
|
26
|
+
expect(_new_user.last_name).to eq 'Drew'
|
27
|
+
expect(_new_user.age).to eq '30'
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'expected to return 3 users' do
|
31
|
+
3.times { User.create(name: 'Bot') }
|
32
|
+
|
33
|
+
expect(User.all.count).to eq 3
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'expected to succesfully delete user' do
|
37
|
+
_user = User.create(name: 'Sacrifice')
|
38
|
+
3.times { User.create(name: 'Bot') }
|
39
|
+
|
40
|
+
expect(User.all.count).to eq 4
|
41
|
+
|
42
|
+
_user.destroy
|
43
|
+
|
44
|
+
expect(User.all.count).to eq 3
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'should find user by name' do
|
48
|
+
User.create(name: 'Bilbo', last_name: 'Beggins')
|
49
|
+
|
50
|
+
_users = User.where(name: 'Bilbo')
|
51
|
+
expect(_users.count).to eq 1
|
52
|
+
|
53
|
+
expect(_users[0]).to be_a User
|
54
|
+
expect(_users[0].last_name).to eq 'Beggins'
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Djoini::Files do
|
4
|
+
before(:all) do
|
5
|
+
@loader = Djoini::Files.new(File.join(File.dirname(__FILE__), '/task_fixtures/'))
|
6
|
+
end
|
7
|
+
|
8
|
+
context 'Ini fixture' do
|
9
|
+
before(:all) { User.delete_all }
|
10
|
+
|
11
|
+
it 'should load all ini files' do
|
12
|
+
@loader.load_files('ini')
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'should find loaded entity in database' do
|
16
|
+
_users = User.where(name: 'Cowboy')
|
17
|
+
|
18
|
+
expect(_users.count).to eq 1
|
19
|
+
expect(_users[0].last_name).to eq 'Bebop'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
context 'Json fixture' do
|
24
|
+
before(:all) { User.delete_all }
|
25
|
+
|
26
|
+
it 'should load all json files' do
|
27
|
+
@loader.load_files('json')
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'should find loaded entity in database' do
|
31
|
+
_users = User.where(name: 'Tom')
|
32
|
+
|
33
|
+
expect(_users.count).to eq 1
|
34
|
+
expect(_users[0].last_name).to eq 'Sowyer'
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'Mixed fixtures' do
|
39
|
+
before(:all) { User.delete_all }
|
40
|
+
|
41
|
+
it 'should load all json files' do
|
42
|
+
@loader.load_files
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'should find loaded entity from json in database' do
|
46
|
+
_users = User.where(name: 'Tom')
|
47
|
+
|
48
|
+
expect(_users.count).to eq 1
|
49
|
+
expect(_users[0].last_name).to eq 'Sowyer'
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'should find loaded entity from ini in database' do
|
53
|
+
_users = User.where(name: 'Tom')
|
54
|
+
|
55
|
+
expect(_users.count).to eq 1
|
56
|
+
expect(_users[0].last_name).to eq 'Sowyer'
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
data/spec/models/post.rb
ADDED
data/spec/models/user.rb
ADDED
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'yaml'
|
3
|
+
require 'pry'
|
4
|
+
|
5
|
+
require_relative '../lib/djoini'
|
6
|
+
|
7
|
+
conn_info = YAML.load(File.read(File.dirname(__FILE__) + '/database.yml'))
|
8
|
+
|
9
|
+
Djoini::Connection.instance.establish_connection(conn_info['postgres'])
|
10
|
+
|
11
|
+
require_relative 'models/post'
|
12
|
+
require_relative 'models/user'
|
13
|
+
|
14
|
+
RSpec.configure do |config|
|
15
|
+
config.expect_with :rspec do |expectations|
|
16
|
+
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
|
17
|
+
end
|
18
|
+
|
19
|
+
config.mock_with :rspec do |mocks|
|
20
|
+
mocks.verify_partial_doubles = true
|
21
|
+
end
|
22
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: djoini
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- faul
|
@@ -100,7 +100,34 @@ email:
|
|
100
100
|
executables: []
|
101
101
|
extensions: []
|
102
102
|
extra_rdoc_files: []
|
103
|
-
files:
|
103
|
+
files:
|
104
|
+
- README.md
|
105
|
+
- Rakefile
|
106
|
+
- bin/console
|
107
|
+
- bin/setup
|
108
|
+
- lib/djoini.rb
|
109
|
+
- lib/djoini/base.rb
|
110
|
+
- lib/djoini/composite.rb
|
111
|
+
- lib/djoini/configuration.rb
|
112
|
+
- lib/djoini/connection.rb
|
113
|
+
- lib/djoini/crud.rb
|
114
|
+
- lib/djoini/fields.rb
|
115
|
+
- lib/djoini/files.rb
|
116
|
+
- lib/djoini/loaders/ini_loader.rb
|
117
|
+
- lib/djoini/loaders/json_loader.rb
|
118
|
+
- lib/djoini/record.rb
|
119
|
+
- lib/djoini/relation.rb
|
120
|
+
- lib/djoini/table.rb
|
121
|
+
- lib/djoini/version.rb
|
122
|
+
- lib/tasks/load.rake
|
123
|
+
- spec/database.yml
|
124
|
+
- spec/djoini/model_spec.rb
|
125
|
+
- spec/djoini/task_fixtures/users.ini
|
126
|
+
- spec/djoini/task_fixtures/users.json
|
127
|
+
- spec/djoini/task_spec.rb
|
128
|
+
- spec/models/post.rb
|
129
|
+
- spec/models/user.rb
|
130
|
+
- spec/spec_helper.rb
|
104
131
|
homepage:
|
105
132
|
licenses:
|
106
133
|
- MIT
|
@@ -125,4 +152,12 @@ rubygems_version: 2.4.8
|
|
125
152
|
signing_key:
|
126
153
|
specification_version: 4
|
127
154
|
summary: Implimentation of ActiveModel pattern and a fixture loader
|
128
|
-
test_files:
|
155
|
+
test_files:
|
156
|
+
- spec/database.yml
|
157
|
+
- spec/djoini/model_spec.rb
|
158
|
+
- spec/djoini/task_fixtures/users.ini
|
159
|
+
- spec/djoini/task_fixtures/users.json
|
160
|
+
- spec/djoini/task_spec.rb
|
161
|
+
- spec/models/post.rb
|
162
|
+
- spec/models/user.rb
|
163
|
+
- spec/spec_helper.rb
|