contentful_model 0.1.6 → 0.1.7
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/lib/contentful_model/associations/belongs_to_many.rb +6 -0
- data/lib/contentful_model/associations/has_many_nested.rb +58 -2
- data/lib/contentful_model/base.rb +15 -1
- data/lib/contentful_model/query.rb +2 -1
- data/lib/contentful_model/validations/validates_presence_of.rb +18 -0
- data/lib/contentful_model/validations/validations.rb +56 -0
- data/lib/contentful_model/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 015f709379b38dc9c97ea758d9f31b7af2f07c45
|
4
|
+
data.tar.gz: c89faf96e42c1280a8b5ef8576fee9081136c1e0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 76cce2394531f2d80a9de03a8abf7aa93ce81f682f98b57374fdcb4d68ff38ad5092705ae97b736199db6b1befc81d98fa6a6cad6c922ff12bc7f275e5c6f660
|
7
|
+
data.tar.gz: c90aeaa083274dfcdf833ee5fa6927cffeb29ca1203a062ac845f23f64a71513b05dfecb37c0b45ff1d36fb31b0afc61ef12a219fe6b7461408e4c4c8ad8f314
|
@@ -25,6 +25,7 @@ module ContentfulModel
|
|
25
25
|
inverse_of: self.to_s.underscore.to_sym
|
26
26
|
}
|
27
27
|
options = default_options.merge(opts)
|
28
|
+
|
28
29
|
# Set up the association name for the instance which loaded this object
|
29
30
|
# This is useful in situations where, primarily, it's a 1:* relationship (i.e. belongs_to)
|
30
31
|
# even though this isn't actually supported by Contentful
|
@@ -39,9 +40,14 @@ module ContentfulModel
|
|
39
40
|
|
40
41
|
define_method "#{association_names.to_s.singularize}=" do |parent|
|
41
42
|
instance_variable_set(:"@#{association_names.to_s.singularize}",parent)
|
43
|
+
instance_variable_set(:"@loaded_with_parent", true)
|
42
44
|
return self
|
43
45
|
end
|
44
46
|
|
47
|
+
define_method "loaded_with_parent?" do
|
48
|
+
instance_variable_get(:"@loaded_with_parent") ? true : false
|
49
|
+
end
|
50
|
+
|
45
51
|
# Set up the association name (plural)
|
46
52
|
if self.respond_to?(association_names)
|
47
53
|
self.send(association_names)
|
@@ -13,7 +13,7 @@ module ContentfulModel
|
|
13
13
|
# To set this up in contentful, add a multi-entry field validated to the same model
|
14
14
|
# as the parent, and give it a name. For example, Page might have a field called childPages:
|
15
15
|
#
|
16
|
-
# has_many_nested :child_pages
|
16
|
+
# has_many_nested :child_pages, root: -> { Page.find("some_id")}
|
17
17
|
#
|
18
18
|
# would setup up an instance attribute called parent_pages which lists all the direct
|
19
19
|
# parents of this page. It would also create methods to find a page based on an array
|
@@ -21,9 +21,22 @@ module ContentfulModel
|
|
21
21
|
# ancestors which called the object; because 'many' associations in Contentful are actually
|
22
22
|
# 'belongs_to_many' from the child end, we might have several ancestors to a page. You will need
|
23
23
|
# to write your own recursion for this, because it's probably an implementation-specific problem.
|
24
|
-
def has_many_nested(association_name)
|
24
|
+
def has_many_nested(association_name, options = {})
|
25
25
|
has_many association_name, inverse_of: :"parent_#{self.to_s.underscore}"
|
26
26
|
belongs_to_many :"parent_#{self.to_s.underscore.pluralize}", class_name: self.to_s, inverse_of: association_name
|
27
|
+
if options[:root].is_a?(Proc)
|
28
|
+
@root_method = options[:root]
|
29
|
+
end
|
30
|
+
|
31
|
+
# If there's a root method defined, set up a class method called root_[class name]. In our example this would be
|
32
|
+
# Page.root_page.
|
33
|
+
# @return [Object] the root entity returned from the proc defined in has_many_nested
|
34
|
+
if defined?(@root_method) && @root_method.is_a?(Proc)
|
35
|
+
# @return [Object] the root entity
|
36
|
+
define_singleton_method :"root_#{self.to_s.underscore}" do
|
37
|
+
@root_method.call
|
38
|
+
end
|
39
|
+
end
|
27
40
|
|
28
41
|
# A utility method which returns the parent object; saves passing around interpolated strings
|
29
42
|
define_method :parent do
|
@@ -73,6 +86,49 @@ module ContentfulModel
|
|
73
86
|
self.send(association_name)
|
74
87
|
end
|
75
88
|
|
89
|
+
# @return [Hash] a hash of nested child objects
|
90
|
+
define_method :nested_children do
|
91
|
+
self.children.inject({}) do |h,c|
|
92
|
+
children = c.has_children? ? c.nested_children : nil
|
93
|
+
h[c] = children
|
94
|
+
h
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
# Return a nested hash of children, returning the field specified
|
99
|
+
# @param field [Symbol] the field you want to return, nested for each child
|
100
|
+
# @return [Hash] of nested children, by that field
|
101
|
+
define_method :nested_children_by do |field|
|
102
|
+
self.children.inject({}) do |h,c|
|
103
|
+
children = c.has_children? ? c.nested_children_by(field) : nil
|
104
|
+
h[c.send(field)] = children
|
105
|
+
h
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
# Return a flattened hash of children by the specified field
|
110
|
+
define_method :all_child_paths_by do |field, opts = {}|
|
111
|
+
options = {prefix: nil}.merge!(opts)
|
112
|
+
flatten_hash(nested_children_by(field)).keys.collect do |path|
|
113
|
+
options[:prefix] ? path.unshift(options[:prefix]) : path
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
# Search for a child by a certain field. This is called on the parent(s).
|
118
|
+
# e.g. Page.root.find_child_path_by(:slug, "some-slug"). Accepts a prefix if you want to
|
119
|
+
# prefix the children with the parent
|
120
|
+
define_method :find_child_path_by do |field, value, opts = {}|
|
121
|
+
all_child_paths_by(field,opts).select {|child| child.include?(value)}
|
122
|
+
end
|
123
|
+
|
124
|
+
# Private method to flatten a hash. Courtesy Cary Swoveland http://stackoverflow.com/a/23861946
|
125
|
+
define_method :flatten_hash do |h,f=[],g={}|
|
126
|
+
return g.update({ f=>h }) unless h.is_a? Hash
|
127
|
+
h.each { |k,r| flatten_hash(r,f+[k],g) }
|
128
|
+
g
|
129
|
+
end
|
130
|
+
self.send(:private, :flatten_hash)
|
131
|
+
|
76
132
|
end
|
77
133
|
end
|
78
134
|
end
|
@@ -2,6 +2,7 @@ module ContentfulModel
|
|
2
2
|
class Base < Contentful::Entry
|
3
3
|
include ContentfulModel::ChainableQueries
|
4
4
|
include ContentfulModel::Associations
|
5
|
+
include ContentfulModel::Validations
|
5
6
|
|
6
7
|
def initialize(*args)
|
7
8
|
super
|
@@ -11,6 +12,20 @@ module ContentfulModel
|
|
11
12
|
#use method_missing to call fields on the model
|
12
13
|
def method_missing(method, *args, &block)
|
13
14
|
result = fields[:"#{method.to_s.camelize(:lower)}"]
|
15
|
+
# we need to pull out any Contentful::Link references, and also things which don't have any fields at all
|
16
|
+
# because they're newly created (we think exposing these in the Contentful API is a bug, actually)
|
17
|
+
if result.is_a?(Array)
|
18
|
+
result.reject! {|r| r.is_a?(Contentful::Link) || r.invalid?}
|
19
|
+
elsif result.is_a?(Contentful::Link)
|
20
|
+
result = nil
|
21
|
+
elsif result.respond_to?(:fields) && result.send(:fields).empty?
|
22
|
+
result = nil
|
23
|
+
elsif result.respond_to?(:invalid?) && result.invalid?
|
24
|
+
result = nil
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
|
14
29
|
if result.nil?
|
15
30
|
# if self.class.rescue_from_no_attribute_fields.member?()
|
16
31
|
# end
|
@@ -23,7 +38,6 @@ module ContentfulModel
|
|
23
38
|
# if there's no coercion specified, return the result
|
24
39
|
if self.class.coercions[method].nil?
|
25
40
|
return result
|
26
|
-
|
27
41
|
#if there's a coercion specified for the field and it's a proc, pass the result
|
28
42
|
#to the proc
|
29
43
|
elsif self.class.coercions[method].is_a?(Proc)
|
@@ -16,7 +16,8 @@ module ContentfulModel
|
|
16
16
|
|
17
17
|
def execute
|
18
18
|
query = @parameters.merge!(default_parameters)
|
19
|
-
|
19
|
+
result = client.send(:entries,query)
|
20
|
+
return result.to_a.reject {|entity| entity.is_a?(Contentful::Link) || entity.invalid?}
|
20
21
|
end
|
21
22
|
|
22
23
|
def client
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Contentful
|
2
|
+
module Validations
|
3
|
+
module PresenceOf
|
4
|
+
def self.included(base)
|
5
|
+
base.extend(ClassMethods)
|
6
|
+
end
|
7
|
+
|
8
|
+
module ClassMethods
|
9
|
+
def validates_presence_of(*args)
|
10
|
+
@validations ||= {}
|
11
|
+
@validations[:presence] ||= []
|
12
|
+
@validations[:presence].push(args)
|
13
|
+
@validations[:presence].flatten!
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# A module to validate entries. A little like ActiveRecord. We don't think this should be necessary, really,
|
2
|
+
# because Contentful should be doing the validating, but they expose invalid entries through the preview API.
|
3
|
+
module ContentfulModel
|
4
|
+
module Validations
|
5
|
+
def self.included(base)
|
6
|
+
base.extend ClassMethods
|
7
|
+
base.include Contentful::Validations::PresenceOf
|
8
|
+
attr_reader :errors
|
9
|
+
end
|
10
|
+
|
11
|
+
def valid?
|
12
|
+
validate
|
13
|
+
end
|
14
|
+
|
15
|
+
def invalid?
|
16
|
+
!valid?
|
17
|
+
end
|
18
|
+
|
19
|
+
def validate
|
20
|
+
@errors ||= []
|
21
|
+
unless self.respond_to?(:fields)
|
22
|
+
@errors.push("Entity doesn't respond to the fields() method")
|
23
|
+
return false
|
24
|
+
end
|
25
|
+
|
26
|
+
validations = self.class.send(:validations)
|
27
|
+
unless validations.nil?
|
28
|
+
validations.each do |type, fields|
|
29
|
+
case type
|
30
|
+
# validates_presence_of
|
31
|
+
when :presence
|
32
|
+
fields.each do |field|
|
33
|
+
unless self.respond_to?(field)
|
34
|
+
@errors << "#{field} is required"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
if @errors.empty?
|
43
|
+
return true
|
44
|
+
else
|
45
|
+
return false
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
module ClassMethods
|
51
|
+
def validations
|
52
|
+
@validations
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: contentful_model
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Error Creative Studio
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-04-
|
11
|
+
date: 2015-04-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: contentful
|
@@ -89,6 +89,8 @@ files:
|
|
89
89
|
- lib/contentful_model/errors.rb
|
90
90
|
- lib/contentful_model/queries.rb
|
91
91
|
- lib/contentful_model/query.rb
|
92
|
+
- lib/contentful_model/validations/validates_presence_of.rb
|
93
|
+
- lib/contentful_model/validations/validations.rb
|
92
94
|
- lib/contentful_model/version.rb
|
93
95
|
- lib/tasks/contentful_rails_tasks.rake
|
94
96
|
homepage: https://github.com/errorstudio/contentful_model
|