yaml_b_sides 0.2.2 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: cf46816b3a78fe32bad41dc0fbcd5ee4d2642a01
4
- data.tar.gz: 24afd605cc2e41eef4a33a00db9c0fd3e3a34454
3
+ metadata.gz: 290831d7f1b375fdc3677f8482747c435028ac5f
4
+ data.tar.gz: 8ee7a67ada8164e8bbdbeb53fae5e49b9fc99f5c
5
5
  SHA512:
6
- metadata.gz: d8360db9e42b671111ab15622a2118aee1fd88f5b48dc6d68cbaab424546eacb17b8e290f0cf69916e2b7d1c44dcef8ef1798e62e778fd76f02878ed9511d52a
7
- data.tar.gz: 203d882c552eb01904ee6c2029d1e38d419dce056d23da6626bef28c656626cceb0ac0f371d7136168db09bf36cd0226c5963b714fdbcb3d8a7298d373917ae4
6
+ metadata.gz: a9e7b2bd03c35870aec5feb6ba9a42ffd79a139f05969a79b8a6f58d9454928261c139dec9a40289a1fe9e75c3855823b9ecc3d5f3046e37b1525d9d48992118
7
+ data.tar.gz: 9066c18974a19653f8adb232a53daea75ce2dcceb26a6c88b9eb3e14c67bd7871e6e7841555852277d8a16f8625104fb49c4c51cd3978f22addf9590c29c2a6e
data/README.md CHANGED
@@ -64,6 +64,18 @@ These are completely optional, but if you have a yaml file that's not uniform, a
64
64
  * `property( name, defaul= nil )` : will set a single field. will set defaul value to nil if omitted
65
65
  * `properties( props = {})` : takes a hash; will set many defaults at once
66
66
 
67
+ ### Associations
68
+
69
+ You can define simple associations that behave very much like ActiveRecord associations. Once you define your association, you will have a method with that name that will do the lookups and cache the results for you.
70
+
71
+ * `belongs_to association`: the base object has to have the association id
72
+ * will return a single object or nil
73
+ * `has_one`: the assiociation object has the id of the base.
74
+ * will return a single object or nil
75
+ * `has_many`: the association object has the id of the base.
76
+ * will return an array
77
+
78
+
67
79
  ### Example
68
80
 
69
81
  To use the `People` class from earlier, a fully fleshed out model would look something like:
@@ -74,11 +86,34 @@ class Person < YamlBSides::Base
74
86
  properties url_slug: "",
75
87
  bio: ""
76
88
 
89
+ has_many :nicknames
90
+
77
91
  index :name
78
92
  index :url_slug
79
93
  end
94
+
95
+ class Nickname < YamlBSides::Base
96
+ belongs_to :person
97
+ end
98
+
99
+ ```
100
+
101
+ and the YAML files will look like
102
+
103
+ ```yml
104
+ # in people.yml
105
+ mark_twain:
106
+ name: Mark Twain
107
+ url_slug: mark-twain
108
+ #...
109
+
110
+ # in nicknames.yml
111
+ sam_clemmens:
112
+ name: Samuel Clemmens
113
+ person_id: mark_twain
80
114
  ```
81
115
 
116
+
82
117
  ## Setup
83
118
 
84
119
  The setup is pretty straightforward. Yaml B-Sides wants a logger and a base dir to look for files in. An example config for a Rails app would look like:
data/lib/yaml_b_sides.rb CHANGED
@@ -8,6 +8,8 @@ require 'active_support/core_ext/hash'
8
8
  require 'yaml'
9
9
 
10
10
  module YamlBSides
11
+ autoload :Associatable, 'yaml_b_sides/associatable'
12
+ autoload :Associations, 'yaml_b_sides/associations'
11
13
  autoload :Base, 'yaml_b_sides/base'
12
14
  autoload :Cacheable, 'yaml_b_sides/cacheable'
13
15
  autoload :Instanceable, 'yaml_b_sides/instanceable'
@@ -0,0 +1,51 @@
1
+ module YamlBSides
2
+ module Associatable
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ class_attribute :__associations
7
+ self.__associations = {}
8
+
9
+ attr_accessor :_cached_associations
10
+
11
+ class << self
12
+
13
+ def belongs_to( name, opts = {} )
14
+ process Associations::BelongsTo.new( self, name, opts )
15
+ end
16
+
17
+ def has_one( name, opts = {} )
18
+ process Associations::HasOne.new( self, name, opts )
19
+ end
20
+
21
+ def has_many( name, opts = {} )
22
+ process Associations::HasMany.new( self, name, opts )
23
+ end
24
+
25
+ protected
26
+
27
+ def process( association )
28
+ associate association
29
+ methodize association
30
+ end
31
+
32
+ def associate( association )
33
+ self.__associations = __associations.merge association.name => association
34
+ end
35
+
36
+ def methodize( association )
37
+ define_method association.name do
38
+ self._cached_associations ||= {}
39
+
40
+ unless self._cached_associations.has_key? association.name
41
+ result = association.klass.send( association.action, association.query( self ) )
42
+
43
+ self._cached_associations[association.name] = result
44
+ end
45
+ self._cached_associations[association.name]
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,8 @@
1
+ module YamlBSides
2
+ module Associations
3
+ autoload :Base, 'yaml_b_sides/associations/base'
4
+ autoload :BelongsTo, 'yaml_b_sides/associations/belongs_to'
5
+ autoload :HasMany, 'yaml_b_sides/associations/has_many'
6
+ autoload :HasOne, 'yaml_b_sides/associations/has_one'
7
+ end
8
+ end
@@ -0,0 +1,33 @@
1
+ module YamlBSides
2
+ module Associations
3
+ class Base
4
+
5
+ attr_accessor :name, :opts, :key
6
+
7
+ def initialize( base_class, name, opts = {} )
8
+ self.name = name
9
+ self.opts = opts
10
+ self.key = "#{base_class.to_s.demodulize.underscore}_id"
11
+ end
12
+
13
+ def klass
14
+ @klass ||= association_class name, opts
15
+ end
16
+
17
+ protected
18
+
19
+ def association_class( name, opts = {} )
20
+ a_class = opts[:class] if opts.has_key? :class
21
+ a_class_name = opts[:class_name].constantize if opts.has_key? :class_name
22
+ derived_class = derived_class_for name
23
+
24
+ a_class || a_class_name || derived_class
25
+ end
26
+
27
+ def derived_class_for( name )
28
+ name.to_s.singularize.classify.constantize
29
+ end
30
+
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,13 @@
1
+ module YamlBSides
2
+ module Associations
3
+ class BelongsTo < Base
4
+ def action
5
+ :find
6
+ end
7
+
8
+ def query( instance )
9
+ instance.send "#{name}_id"
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module YamlBSides
2
+ module Associations
3
+ class HasMany < Base
4
+ def action
5
+ :where
6
+ end
7
+
8
+ def query( instance )
9
+ { key => instance.id }
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module YamlBSides
2
+ module Associations
3
+ class HasOne < Base
4
+ def action
5
+ :find_by
6
+ end
7
+
8
+ def query( instance )
9
+ { key => instance.id }
10
+ end
11
+ end
12
+ end
13
+ end
@@ -1,6 +1,7 @@
1
1
  module YamlBSides
2
2
  class Base
3
3
  include ActiveModel::Model
4
+ include Associatable
4
5
  include Cacheable
5
6
  include Propertiable
6
7
  include Indexable
@@ -15,7 +16,9 @@ module YamlBSides
15
16
  def load!
16
17
  @data = YAML.load_file( data_file ).with_indifferent_access
17
18
  idify_data!
18
- puts "#{self} successfully loaded data"
19
+ logger.info "#{self} successfully loaded data"
20
+ # let's preemptively index by id so that when we do a find_by id:, or a where id: it won't table scan
21
+ index :id
19
22
  rescue => e
20
23
  logger.error "#{self} failed to load data: #{e}"
21
24
  end
@@ -4,7 +4,7 @@ module YamlBSides
4
4
 
5
5
  included do
6
6
  class_attribute :__indices
7
- self.__indices = {}
7
+ self.__indices = { }
8
8
 
9
9
  class << self
10
10
  def index(field)
@@ -28,7 +28,6 @@ module YamlBSides
28
28
  def index_for(field)
29
29
  __indices[field]
30
30
  end
31
-
32
31
  end
33
32
  end
34
33
  end
@@ -11,13 +11,9 @@ module YamlBSides
11
11
  end
12
12
 
13
13
  def find_by(params = {})
14
- if all_indexed?(params.keys)
15
- results = find_by_indexed(params)
16
- else
17
- results = find_by_scan(params)
18
- end
14
+ results = where params
19
15
  raise "Could not find record that matches: #{params.inspect}" if results.empty?
20
- new results.first
16
+ results.first
21
17
  end
22
18
 
23
19
  def all
@@ -30,6 +26,18 @@ module YamlBSides
30
26
  new @data.values.first
31
27
  end
32
28
 
29
+ # TODO: move this into scopes
30
+ def where(params)
31
+ if all_indexed?(params.keys)
32
+ results = find_by_indexed(params)
33
+ else
34
+ results = find_by_scan(params)
35
+ end
36
+ results.map do |result|
37
+ new result
38
+ end
39
+ end
40
+
33
41
  private
34
42
 
35
43
  def find_by_scan(params)
@@ -1,3 +1,3 @@
1
1
  module YamlBSides
2
- VERSION = "0.2.2"
2
+ VERSION = "0.3.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yaml_b_sides
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Greg Orlov
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-09-13 00:00:00.000000000 Z
11
+ date: 2016-09-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -97,6 +97,12 @@ files:
97
97
  - bin/console
98
98
  - bin/setup
99
99
  - lib/yaml_b_sides.rb
100
+ - lib/yaml_b_sides/associatable.rb
101
+ - lib/yaml_b_sides/associations.rb
102
+ - lib/yaml_b_sides/associations/base.rb
103
+ - lib/yaml_b_sides/associations/belongs_to.rb
104
+ - lib/yaml_b_sides/associations/has_many.rb
105
+ - lib/yaml_b_sides/associations/has_one.rb
100
106
  - lib/yaml_b_sides/base.rb
101
107
  - lib/yaml_b_sides/cacheable.rb
102
108
  - lib/yaml_b_sides/index.rb