djoini 0.1.2 → 0.1.3
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.
- 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
|