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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 038d352d42cc8f428379d27b2db70bccb7661244
4
- data.tar.gz: 1b370619c14aecd9ee170ff0f82b72315a9cef7c
3
+ metadata.gz: 015f709379b38dc9c97ea758d9f31b7af2f07c45
4
+ data.tar.gz: c89faf96e42c1280a8b5ef8576fee9081136c1e0
5
5
  SHA512:
6
- metadata.gz: 0692c693706a5211fc011398e410dc79b70557cfd8f260950f56548a0136875da82f6d7aaf6cbecdf45f2a9f4d1e26419d7c0d24249db480b80d78ab004c6313
7
- data.tar.gz: 3e20613dea10448a65e96a6f449389f6683dc967016ed26a9a0ba868247f8f90523709bbe5cffa6322da4cd7862d8871b9bfd38afdeaa2f1c1ff916d46565ce5
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
- return client.send(:entries,query)
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
@@ -1,3 +1,3 @@
1
1
  module ContentfulModel
2
- VERSION = "0.1.6"
2
+ VERSION = "0.1.7"
3
3
  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.6
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-10 00:00:00.000000000 Z
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