acts_as_nosql 0.1.0
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 +7 -0
- data/lib/acts_as_nosql/attribute.rb +39 -0
- data/lib/acts_as_nosql/attributes.rb +56 -0
- data/lib/acts_as_nosql/querying.rb +86 -0
- data/lib/acts_as_nosql/version.rb +3 -0
- data/lib/acts_as_nosql.rb +27 -0
- data/spec/acts_as_nosql/model_spec.rb +50 -0
- data/spec/acts_as_nosql/nested_spec.rb +53 -0
- data/spec/acts_as_nosql/querying_spec.rb +45 -0
- data/spec/spec_helper.rb +22 -0
- data/spec/support/schema.rb +64 -0
- metadata +146 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 6557e20a7d3813b7250a1a6b4e346d07e3b8f89b9ad984d66c6632e8e172bf9e
|
4
|
+
data.tar.gz: 8ddacccc9e46e5102dc4056fd4a139e6dde8302e15bd108f66ab7b15214880e7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: cf9a0fdfba234f852ffd8fc97fe18b709eaff996037da995bccb672696f03d749ac52e4dc2a82306c87f8bb12efd4f7d9f942a43718bb86d309d6b169fd868dd
|
7
|
+
data.tar.gz: 39662c4f73d0d4f1468a1e02d95ddb6624a907079a9ae4984b449356e51bc5ebf631c162508946f330035747591131f469249e8c72b5484ef0fc6c569aca3e5f
|
@@ -0,0 +1,39 @@
|
|
1
|
+
|
2
|
+
module ActsAsNosql
|
3
|
+
class Attribute
|
4
|
+
attr_reader :name, :type, :default, :path, :type_caster
|
5
|
+
|
6
|
+
def initialize(name, type: nil, default: nil, path: nil)
|
7
|
+
@name = name.to_s
|
8
|
+
@type = type
|
9
|
+
@default = default
|
10
|
+
@path = path&.map { |p| p.to_s }
|
11
|
+
@type_caster = type ? "ActiveRecord::Type::#{type}".safe_constantize : nil
|
12
|
+
end
|
13
|
+
|
14
|
+
def cast(value)
|
15
|
+
type_caster ? type_caster.new.cast(value) : value
|
16
|
+
end
|
17
|
+
|
18
|
+
def read(attr)
|
19
|
+
if path
|
20
|
+
attr&.dig(*path)
|
21
|
+
else
|
22
|
+
attr&.dig(name)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def write(attr, value)
|
27
|
+
if path
|
28
|
+
current = attr
|
29
|
+
path[0...-1].each do |key|
|
30
|
+
current[key] ||= {}
|
31
|
+
current = current[key]
|
32
|
+
end
|
33
|
+
current[path.last] = cast(value)
|
34
|
+
else
|
35
|
+
attr[name] = cast(value)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
|
2
|
+
module ActsAsNosql
|
3
|
+
module Attributes
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
after_initialize :_acts_as_nosql_init
|
8
|
+
end
|
9
|
+
|
10
|
+
def _acts_as_nosql_init
|
11
|
+
self.class.nosql_attributes.each do |name, attribute|
|
12
|
+
public_send("#{name}=", attribute.default.dup) if public_send(name).nil? && !attribute.default.nil?
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class_methods do
|
17
|
+
def nosql_attrs(*names, type: nil, default: nil, path: nil)
|
18
|
+
nosql_attr(*names, type: type, default: default, path: path)
|
19
|
+
end
|
20
|
+
|
21
|
+
def nosql_attr(*names, type: nil, default: nil, path: nil)
|
22
|
+
attribute = self._acts_as_nosql_options[:field_name]
|
23
|
+
|
24
|
+
names.each do |name|
|
25
|
+
raise "Attribute #{name} already defined" if instance_methods.include?(name.to_sym) || name.to_sym == attribute.to_sym
|
26
|
+
|
27
|
+
nosql_attributes[name] = ActsAsNosql::Attribute.new(name, type: type, default: default, path: path)
|
28
|
+
_acts_as_nosql_define_attribute(nosql_attributes[name])
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def nosql_attributes
|
33
|
+
self._acts_as_nosql_options[:attributes] ||= {}
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def nosql_data_attribute
|
39
|
+
@nosql_data_attribute ||= self._acts_as_nosql_options[:field_name]
|
40
|
+
end
|
41
|
+
|
42
|
+
def _acts_as_nosql_define_attribute(nosql_attribute)
|
43
|
+
attribute = nosql_data_attribute
|
44
|
+
|
45
|
+
define_method(nosql_attribute.name) do
|
46
|
+
nosql_attribute.read(self[attribute])
|
47
|
+
end
|
48
|
+
|
49
|
+
define_method("#{nosql_attribute.name}=") do |value|
|
50
|
+
self[attribute] ||= {}
|
51
|
+
nosql_attribute.write(self[attribute], value)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
|
2
|
+
module ActsAsNosql
|
3
|
+
module Querying
|
4
|
+
def where(*args)
|
5
|
+
args, json_args = *extract_json_args(args)
|
6
|
+
|
7
|
+
if json_args
|
8
|
+
chain = _acts_as_nosql_parse_where(json_args)
|
9
|
+
|
10
|
+
args.first.empty? ? chain : chain.where(*args)
|
11
|
+
else
|
12
|
+
super
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def extract_json_args(args)
|
19
|
+
return [args, nil] unless args.first.is_a?(Hash)
|
20
|
+
return [args, nil] unless model._acts_as_nosql_options
|
21
|
+
|
22
|
+
attrs = model._acts_as_nosql_options[:attributes]
|
23
|
+
hash = args.first
|
24
|
+
|
25
|
+
return [args, nil] if hash.keys.none? { |key| attrs.key?(key) }
|
26
|
+
|
27
|
+
json_hash = {}
|
28
|
+
nonjson_hash = {}
|
29
|
+
|
30
|
+
hash.each do |key, value|
|
31
|
+
if attrs.key?(key)
|
32
|
+
json_hash[key] = value
|
33
|
+
else
|
34
|
+
nonjson_hash[key] = value
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
[
|
39
|
+
[nonjson_hash, args[1..-1]],
|
40
|
+
json_hash
|
41
|
+
]
|
42
|
+
end
|
43
|
+
|
44
|
+
def _acts_as_nosql_parse_where(hash)
|
45
|
+
hash.inject(self) do |chain, (key, value)|
|
46
|
+
attr = model._acts_as_nosql_options[:attributes][key]
|
47
|
+
chain.where(*build_sql_query(attr, value))
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def build_sql_query(attribute, value)
|
52
|
+
field_name = model._acts_as_nosql_options[:field_name]
|
53
|
+
["#{quote_chain(attribute, field_name)} = ?", value]
|
54
|
+
end
|
55
|
+
|
56
|
+
def quote_chain(attribute, field_name)
|
57
|
+
if connection.adapter_name == 'PostgreSQL'
|
58
|
+
quote_chain_psql(attribute, field_name)
|
59
|
+
else
|
60
|
+
quote_chain_base(attribute, field_name)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def quote_chain_base(attribute, field_name)
|
65
|
+
base = quote_full_column(field_name)
|
66
|
+
path = attribute.path || [attribute.name]
|
67
|
+
"#{base}->>'$.#{path.join('.')}'"
|
68
|
+
end
|
69
|
+
|
70
|
+
def quote_chain_psql(attribute, field_name)
|
71
|
+
base = quote_full_column(field_name)
|
72
|
+
path = attribute.path
|
73
|
+
if attribute.path
|
74
|
+
"#{base}->#{path[0...-1].map { |e| "'#{e}'"}.join('->')}->>'#{path.last}'"
|
75
|
+
else
|
76
|
+
"#{base}->>'#{attribute.name}'"
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def quote_full_column(field_name)
|
81
|
+
connection.quote_table_name(arel_table.table_alias || arel_table.table_name) +
|
82
|
+
'.' +
|
83
|
+
connection.quote_column_name(field_name)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
|
3
|
+
module ActsAsNosql
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
extend ActiveSupport::Autoload
|
6
|
+
|
7
|
+
class_methods do
|
8
|
+
attr_accessor :_acts_as_nosql_options
|
9
|
+
# cattr_accessor :_acts_as_nosql_options
|
10
|
+
def acts_as_nosql(field_name: nil)
|
11
|
+
@_acts_as_nosql_options = { field_name: field_name }
|
12
|
+
|
13
|
+
include ActsAsNosql::Attributes
|
14
|
+
end
|
15
|
+
|
16
|
+
def _acts_as_nosql_options
|
17
|
+
@_acts_as_nosql_options
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
autoload :Attribute
|
22
|
+
autoload :Attributes
|
23
|
+
autoload :Querying
|
24
|
+
end
|
25
|
+
|
26
|
+
ActiveRecord::Base.include ActsAsNosql
|
27
|
+
ActiveRecord::Relation.prepend(ActsAsNosql::Querying)
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Fields declaration' do
|
4
|
+
|
5
|
+
subject { Article.new }
|
6
|
+
|
7
|
+
it 'has declared fields' do
|
8
|
+
expect(subject).to respond_to(:body)
|
9
|
+
expect(subject).to respond_to(:body=)
|
10
|
+
expect(subject).to respond_to(:comments_count)
|
11
|
+
expect(subject).to respond_to(:comments_count=)
|
12
|
+
expect(subject).to respond_to(:published)
|
13
|
+
expect(subject).to respond_to(:published=)
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'uses default values' do
|
17
|
+
expect(subject.comments_count).to eq(0)
|
18
|
+
expect(subject.published).to eq(false)
|
19
|
+
expect(subject.body).to eq(nil)
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'casts fields' do
|
23
|
+
subject.body = 2
|
24
|
+
expect(subject.body).to eq('2')
|
25
|
+
|
26
|
+
subject.published = '1'
|
27
|
+
expect(subject.published).to eq(true)
|
28
|
+
|
29
|
+
subject.comments_count = '1'
|
30
|
+
expect(subject.comments_count).to eq(1)
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'raises error if there\'s a name conflict with the field_name' do
|
34
|
+
expect { Article.nosql_attr :data }.to raise_error("Attribute data already defined")
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'raises error if there\'s a name conflict' do
|
38
|
+
expect { Article.nosql_attr :some_column }.to raise_error("Attribute some_column already defined")
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'fileds are saved as string' do
|
42
|
+
subject.editor = 'John Doe'
|
43
|
+
subject.save!
|
44
|
+
subject.reload
|
45
|
+
expect(subject.editor).to eq('John Doe')
|
46
|
+
expect(subject.data['editor']).to eq('John Doe')
|
47
|
+
expect(subject.data[:editor]).to eq(nil)
|
48
|
+
expect(subject.data.keys.first).to be_a(String)
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Nested fields declaration' do
|
4
|
+
|
5
|
+
subject { Setting.new }
|
6
|
+
|
7
|
+
it 'has declared fields' do
|
8
|
+
expect(subject).to respond_to(:user_auth_token)
|
9
|
+
expect(subject).to respond_to(:user_auth_token=)
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'uses default values' do
|
13
|
+
expect(subject.user_auth_token).to eq('')
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'casts fields' do
|
17
|
+
subject.user_auth_token = 2
|
18
|
+
expect(subject.user_auth_token).to eq('2')
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'writes nested values' do
|
22
|
+
subject.user_auth_token = 2
|
23
|
+
expect(subject.config).to eq({ 'user' => { 'auth' => { 'providers' => [], 'token' => '2' } } })
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'data is persisted' do
|
27
|
+
subject.user_auth_token = 2
|
28
|
+
subject.save!
|
29
|
+
subject.reload
|
30
|
+
expect(subject.user_auth_token).to eq('2')
|
31
|
+
expect(subject.config).to eq({ 'user' => { 'auth' => { 'providers' => [], 'token' => '2' } } })
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'with array type' do
|
35
|
+
it 'handles writes' do
|
36
|
+
expect(subject.user_auth_providers).to eq([])
|
37
|
+
subject.user_auth_providers = ['google']
|
38
|
+
expect(subject.user_auth_providers).to eq(['google'])
|
39
|
+
subject.save!
|
40
|
+
subject.reload
|
41
|
+
expect(subject.config).to eq({ 'user' => { 'auth' => { 'providers' => ['google'], 'token' => '' } } })
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'handles mutation' do
|
45
|
+
expect(subject.user_auth_providers).to eq([])
|
46
|
+
subject.user_auth_providers << 'google'
|
47
|
+
expect(subject.user_auth_providers).to eq(['google'])
|
48
|
+
subject.save!
|
49
|
+
subject.reload
|
50
|
+
expect(subject.config).to eq({ 'user' => { 'auth' => { 'providers' => ['google'], 'token' => '' } } })
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Querying' do
|
4
|
+
context 'simple attributes' do
|
5
|
+
let!(:article) do
|
6
|
+
Article.create!(
|
7
|
+
body: 'body',
|
8
|
+
published: true,
|
9
|
+
comments_count: 5,
|
10
|
+
)
|
11
|
+
end
|
12
|
+
|
13
|
+
let!(:article2) do
|
14
|
+
Article.create!
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'can be queried' do
|
18
|
+
query = Article.where(body: 'body')
|
19
|
+
# expect(query.to_sql).to eq(
|
20
|
+
# "SELECT \"articles\".* FROM \"articles\" WHERE (\"articles\".\"data\"->>\"body\" = 'body')"
|
21
|
+
# )
|
22
|
+
expect(query.to_a).to contain_exactly(article)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context 'nested attributes' do
|
27
|
+
let!(:setting) do
|
28
|
+
Setting.create!(
|
29
|
+
user_auth_token: '123123',
|
30
|
+
)
|
31
|
+
end
|
32
|
+
|
33
|
+
let!(:setting2) do
|
34
|
+
Setting.create!
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'can query nested attributes' do
|
38
|
+
query = Setting.where(user_auth_token: '123123')
|
39
|
+
# expect(query.to_sql).to eq(
|
40
|
+
# "SELECT \"settings\".* FROM \"settings\" WHERE (\"settings\".\"config\"->>\"user\"->>\"auth\"->>\"token\" = '123123')"
|
41
|
+
# )
|
42
|
+
expect(query.to_a).to contain_exactly(setting)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
require 'rspec'
|
3
|
+
require 'acts_as_nosql'
|
4
|
+
require 'active_record'
|
5
|
+
|
6
|
+
I18n.enforce_available_locales = false
|
7
|
+
RSpec::Expectations.configuration.warn_about_potential_false_positives = false
|
8
|
+
|
9
|
+
Dir[File.expand_path('support/*.rb', __dir__)].each { |f| require f }
|
10
|
+
|
11
|
+
RSpec.configure do |config|
|
12
|
+
config.before(:suite) do
|
13
|
+
Schema.create
|
14
|
+
end
|
15
|
+
|
16
|
+
config.around(:each) do |example|
|
17
|
+
ActiveRecord::Base.transaction do
|
18
|
+
example.run
|
19
|
+
raise ActiveRecord::Rollback
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
|
3
|
+
if ENV['ACTIVE_RECORD_ADAPTER'] == 'mysql'
|
4
|
+
puts 'Running on MySQL...'
|
5
|
+
ActiveRecord::Base.establish_connection(
|
6
|
+
adapter: 'mysql2',
|
7
|
+
username: ENV['DB_USERNAME'] || 'root',
|
8
|
+
password: ENV['DB_PASSWORD'],
|
9
|
+
database: 'acts_as_nosql'
|
10
|
+
)
|
11
|
+
elsif ENV['ACTIVE_RECORD_ADAPTER'] == 'postgresql'
|
12
|
+
puts 'Running on PostgreSQL...'
|
13
|
+
ActiveRecord::Base.establish_connection(
|
14
|
+
adapter: 'postgresql',
|
15
|
+
database: 'acts_as_nosql',
|
16
|
+
host: ENV['DB_HOST'] || '127.0.0.1',
|
17
|
+
username: ENV['DB_USERNAME'] || 'postgres',
|
18
|
+
password: ENV['DB_PASSWORD']
|
19
|
+
)
|
20
|
+
else
|
21
|
+
puts 'Running on SQLite...'
|
22
|
+
ActiveRecord::Base.establish_connection(
|
23
|
+
adapter: 'sqlite3',
|
24
|
+
database: ':memory:'
|
25
|
+
)
|
26
|
+
end
|
27
|
+
|
28
|
+
class Article < ActiveRecord::Base
|
29
|
+
acts_as_nosql field_name: :data
|
30
|
+
|
31
|
+
def some_column
|
32
|
+
end
|
33
|
+
|
34
|
+
nosql_attrs :body, :editor, type: String
|
35
|
+
nosql_attr :comments_count, type: :Integer, default: 0
|
36
|
+
nosql_attr :published, type: :Boolean, default: false
|
37
|
+
end
|
38
|
+
|
39
|
+
class Setting < ActiveRecord::Base
|
40
|
+
acts_as_nosql field_name: :config
|
41
|
+
|
42
|
+
nosql_attrs :user_auth_token, type: String, default: '', path: [:user, :auth, :token]
|
43
|
+
nosql_attrs :user_auth_providers, type: Array, default: [], path: [:user, :auth, :providers]
|
44
|
+
end
|
45
|
+
|
46
|
+
module Schema
|
47
|
+
def self.create
|
48
|
+
ActiveRecord::Migration.verbose = false
|
49
|
+
|
50
|
+
ActiveRecord::Schema.define do
|
51
|
+
create_table :articles, force: true do |t|
|
52
|
+
t.string :title
|
53
|
+
t.json :data
|
54
|
+
t.timestamps null: false
|
55
|
+
end
|
56
|
+
|
57
|
+
create_table :settings, force: true do |t|
|
58
|
+
t.string :title
|
59
|
+
t.json :config
|
60
|
+
t.timestamps null: false
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
metadata
ADDED
@@ -0,0 +1,146 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: acts_as_nosql
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Mònade
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2022-06-23 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: actionpack
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '5'
|
20
|
+
- - "<"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '8'
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '5'
|
30
|
+
- - "<"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '8'
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: activesupport
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '5'
|
40
|
+
- - "<"
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: '8'
|
43
|
+
type: :runtime
|
44
|
+
prerelease: false
|
45
|
+
version_requirements: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - ">="
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '5'
|
50
|
+
- - "<"
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '8'
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: activerecord
|
55
|
+
requirement: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '5'
|
60
|
+
- - "<"
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '8'
|
63
|
+
type: :runtime
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '5'
|
70
|
+
- - "<"
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: '8'
|
73
|
+
- !ruby/object:Gem::Dependency
|
74
|
+
name: rspec
|
75
|
+
requirement: !ruby/object:Gem::Requirement
|
76
|
+
requirements:
|
77
|
+
- - "~>"
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: '3'
|
80
|
+
type: :development
|
81
|
+
prerelease: false
|
82
|
+
version_requirements: !ruby/object:Gem::Requirement
|
83
|
+
requirements:
|
84
|
+
- - "~>"
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: '3'
|
87
|
+
- !ruby/object:Gem::Dependency
|
88
|
+
name: rubocop
|
89
|
+
requirement: !ruby/object:Gem::Requirement
|
90
|
+
requirements:
|
91
|
+
- - ">="
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
type: :development
|
95
|
+
prerelease: false
|
96
|
+
version_requirements: !ruby/object:Gem::Requirement
|
97
|
+
requirements:
|
98
|
+
- - ">="
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
version: '0'
|
101
|
+
description: It allows to handle JSON and JSONB fields as if they are proper database
|
102
|
+
columns, handling default values, type casting and easier validation.
|
103
|
+
email: team@monade.io
|
104
|
+
executables: []
|
105
|
+
extensions: []
|
106
|
+
extra_rdoc_files: []
|
107
|
+
files:
|
108
|
+
- lib/acts_as_nosql.rb
|
109
|
+
- lib/acts_as_nosql/attribute.rb
|
110
|
+
- lib/acts_as_nosql/attributes.rb
|
111
|
+
- lib/acts_as_nosql/querying.rb
|
112
|
+
- lib/acts_as_nosql/version.rb
|
113
|
+
- spec/acts_as_nosql/model_spec.rb
|
114
|
+
- spec/acts_as_nosql/nested_spec.rb
|
115
|
+
- spec/acts_as_nosql/querying_spec.rb
|
116
|
+
- spec/spec_helper.rb
|
117
|
+
- spec/support/schema.rb
|
118
|
+
homepage: https://rubygems.org/gems/acts_as_nosql
|
119
|
+
licenses:
|
120
|
+
- MIT
|
121
|
+
metadata: {}
|
122
|
+
post_install_message:
|
123
|
+
rdoc_options: []
|
124
|
+
require_paths:
|
125
|
+
- lib
|
126
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
127
|
+
requirements:
|
128
|
+
- - ">="
|
129
|
+
- !ruby/object:Gem::Version
|
130
|
+
version: 2.7.0
|
131
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
132
|
+
requirements:
|
133
|
+
- - ">="
|
134
|
+
- !ruby/object:Gem::Version
|
135
|
+
version: '0'
|
136
|
+
requirements: []
|
137
|
+
rubygems_version: 3.2.33
|
138
|
+
signing_key:
|
139
|
+
specification_version: 4
|
140
|
+
summary: Use JSON columns as real activerecord attributes
|
141
|
+
test_files:
|
142
|
+
- spec/acts_as_nosql/model_spec.rb
|
143
|
+
- spec/acts_as_nosql/nested_spec.rb
|
144
|
+
- spec/acts_as_nosql/querying_spec.rb
|
145
|
+
- spec/spec_helper.rb
|
146
|
+
- spec/support/schema.rb
|