Skip to content

Commit

Permalink
Merge pull request #2 from TheDro/make-gem-configurable
Browse files Browse the repository at this point in the history
Make gem configurable
  • Loading branch information
TheDro authored Dec 4, 2020
2 parents a6b48b1 + 77c674a commit 574e675
Show file tree
Hide file tree
Showing 10 changed files with 151 additions and 23 deletions.
10 changes: 7 additions & 3 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
gql_serializer (1.0.0)
gql_serializer (1.1.0)
activerecord (>= 5.2, < 6.1)

GEM
Expand All @@ -18,12 +18,16 @@ GEM
minitest (~> 5.1)
tzinfo (~> 1.1)
zeitwerk (~> 2.2, >= 2.2.2)
byebug (11.1.3)
coderay (1.1.3)
concurrent-ruby (1.1.6)
diff-lcs (1.4.4)
i18n (1.8.2)
concurrent-ruby (~> 1.0)
method_source (1.0.0)
minitest (5.14.0)
pry (0.13.1)
coderay (~> 1.1)
method_source (~> 1.0)
rake (12.3.3)
rspec (3.10.0)
rspec-core (~> 3.10.0)
Expand All @@ -48,8 +52,8 @@ PLATFORMS
x64-mingw32

DEPENDENCIES
byebug (~> 11.1)
gql_serializer!
pry (~> 0.13.1)
rake (~> 12.0)
rspec (~> 3.0)
sqlite3 (~> 1.4.2)
Expand Down
Binary file removed gql_serializer-1.0.0.gem
Binary file not shown.
2 changes: 1 addition & 1 deletion gql_serializer.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ Gem::Specification.new do |spec|

spec.add_development_dependency "rake", "~> 12.0"
spec.add_development_dependency "rspec", "~> 3.0"
spec.add_development_dependency "byebug", "~> 11.1"
spec.add_development_dependency "pry", "~> 0.13.1"
spec.add_development_dependency "sqlite3", "~> 1.4.2"

spec.add_runtime_dependency "activerecord", ">= 5.2", "< 6.1"
Expand Down
50 changes: 39 additions & 11 deletions lib/gql_serializer.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
require "gql_serializer/version"
require "gql_serializer/extensions"
require "gql_serializer/configuration"


module GqlSerializer

def self.configuration
@configuration ||= Configuration.new
end

def self.configure
yield configuration
end


def self.parse_query(input)
query = input.dup
query.strip!
Expand Down Expand Up @@ -36,48 +46,52 @@ def self.query_include(model, hasharray)
include_array
end

def self.serialize(record, hasharray)
def self.serialize(record, hasharray, options)

if record.nil?
return nil
end

if record.respond_to? :map
return record.map do |r|
self.serialize(r, hasharray)
self.serialize(r, hasharray, options)
end
end

hash = {}
model = record.class
all_relations = model.reflections.keys

attributes = hasharray.filter do |e|
next false if !e.is_a?(String)
relations = hasharray.filter do |e|
next true if !e.is_a?(String)

key, alias_key = e.split(':')
model.attribute_names.include?(key)
all_relations.include?(key)
end

relations = hasharray - attributes
attributes = hasharray - relations
attributes = model.attribute_names if attributes.empty?

attributes.each do |e|
key, alias_key = e.split(':')
alias_key ||= key
alias_key = apply_case(alias_key || key, options[:case])

hash[alias_key] = record.public_send(key)
end

relations.each do |e|
if e.is_a? String
key, alias_key = e.split(':')
alias_key ||= key
alias_key = apply_case(alias_key || key, options[:case])

rel_records = record.public_send(key)
hash[alias_key] = self.serialize(rel_records, [])
hash[alias_key] = self.serialize(rel_records, [], options)
else
key, alias_key = e.keys.first.split(':')
alias_key ||= key
alias_key = apply_case(alias_key || key, options[:case])

rel_records = record.public_send(key)
hash[alias_key] = self.serialize(rel_records, e.values.first)
hash[alias_key] = self.serialize(rel_records, e.values.first, options)
end
end

Expand All @@ -87,6 +101,20 @@ def self.serialize(record, hasharray)

private

def self.apply_case(key, key_case)
case key_case
when Configuration::CAMEL_CASE
result = key.camelize
result[0] = result[0].downcase
when Configuration::SNAKE_CASE
result = key.underscore
else
result = key
end

result
end

def self.parse_it(query)
result = []
while query&.length&.> 0
Expand Down
25 changes: 25 additions & 0 deletions lib/gql_serializer/configuration.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@


module GqlSerializer
class Configuration
CAMEL_CASE = :camel
SNAKE_CASE = :snake
NONE_CASE = :none
SUPPORTED_CASES = [CAMEL_CASE, SNAKE_CASE, NONE_CASE]

def initialize
@case = NONE_CASE
end

attr_reader :case

def case=(value)
raise "Specified case '#{value}' is not supported" unless SUPPORTED_CASES.include?(value)
@case = value
end

def to_h
{case: @case}
end
end
end
14 changes: 8 additions & 6 deletions lib/gql_serializer/extensions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,27 @@ def as_gql(query = nil)
end

module Relation
def as_gql(query = nil)
def as_gql(query = nil, options = {})
query_hasharray = query ? GqlSerializer.parse_query(query) : []
include_hasharray = GqlSerializer.query_include(self.model, query_hasharray)
records = self.includes(include_hasharray).records
GqlSerializer.serialize(records, query_hasharray)
options_with_defaults = GqlSerializer.configuration.to_h.merge(options)
GqlSerializer.serialize(records, query_hasharray, options_with_defaults)
end
end

module ActiveRecord
def self.as_gql(query = nil)
self.all.as_gql(query)
def self.as_gql(query = nil, options = {})
self.all.as_gql(query, options)
end

def as_gql(query = nil)
def as_gql(query = nil, options = {})

query_hasharray = query ? GqlSerializer.parse_query(query) : []
include_hasharray = GqlSerializer.query_include(self.class, query_hasharray)
record = include_hasharray.empty? ? self : self.class.where(id: self).includes(include_hasharray).first
GqlSerializer.serialize(record, query_hasharray)
options_with_defaults = GqlSerializer.configuration.to_h.merge(options)
GqlSerializer.serialize(record, query_hasharray, options_with_defaults)
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion lib/gql_serializer/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module GqlSerializer
VERSION = "1.0.0"
VERSION = "1.1.0"
end
27 changes: 27 additions & 0 deletions spec/gql_serializer/configuration_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@


RSpec.describe GqlSerializer::Configuration do
describe 'case' do
it 'supports none, snake case and camel case' do
GqlSerializer.configure do |config|
config.case= GqlSerializer::Configuration::NONE_CASE
config.case= GqlSerializer::Configuration::SNAKE_CASE
config.case= GqlSerializer::Configuration::CAMEL_CASE
end

expect(GqlSerializer.configuration.case).to eq(:camel)
end

it 'raises an error for unsupported cases' do
GqlSerializer.configure do |config|
config.case= :unsupported
end

raise "error was not raised"
rescue => e
expect(e.message).to include("not supported")
end
end


end
43 changes: 42 additions & 1 deletion spec/serializer_spec.rb → spec/gql_serializer_spec.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
require 'active_record'
require 'byebug'

RSpec.describe GqlSerializer do
it "has a version number" do
Expand Down Expand Up @@ -59,6 +58,9 @@

class TestUser < ActiveRecord::Base
has_many :test_orders
def encoded_id
"TestUser-#{id}"
end
end

class TestOrder < ActiveRecord::Base
Expand Down Expand Up @@ -141,6 +143,45 @@ class TestItem < ActiveRecord::Base
'orders' => [{'cost' => orders[0].total}, {'cost' => orders[1].total}]
})
end

it 'supports methods' do
user = TestUser.create(name: 'John', email: 'john@test.com')

expect(user.as_gql('encoded_id')).to eq({'encoded_id' => "TestUser-#{user.id}"})
expect(user.as_gql('encoded_id:id')).to eq({'id' => "TestUser-#{user.id}"})
end

describe 'case conversions' do
class CaseUser < TestUser
def snake_case
'snake'
end

def camelCase
'camel'
end
end

it 'converts keys to camel case' do
user = CaseUser.create(name: 'John')

expect(user.as_gql('snake_case camelCase',
{case: GqlSerializer::Configuration::CAMEL_CASE}))
.to eq({'snakeCase' => 'snake', 'camelCase' => 'camel'})
end

it 'converts keys to snake case' do
user = CaseUser.create(name: 'John')

expect(user.as_gql('snake_case camelCase',
{case: GqlSerializer::Configuration::SNAKE_CASE}))
.to eq({'snake_case' => 'snake', 'camel_case' => 'camel'})
end

it 'uses the configured case by default' do
binding.pry
end
end
end

end
1 change: 1 addition & 0 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
require "bundler/setup"
require "gql_serializer"
require "pry"

RSpec.configure do |config|
# Enable flags like --only-failures and --next-failure
Expand Down

0 comments on commit 574e675

Please sign in to comment.