contentful_model 0.1.6 → 0.1.7

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: 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