fera-api 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +7 -0
  2. data/.idea/fera-api.iml +86 -0
  3. data/.idea/modules.xml +8 -0
  4. data/.idea/vcs.xml +6 -0
  5. data/.idea/workspace.xml +91 -0
  6. data/.rspec +3 -0
  7. data/.rubocop.yml +56 -0
  8. data/Gemfile +14 -0
  9. data/Gemfile.lock +92 -0
  10. data/LICENSE.txt +21 -0
  11. data/README.md +256 -0
  12. data/Rakefile +12 -0
  13. data/lib/fera/api/version.rb +7 -0
  14. data/lib/fera/api.rb +69 -0
  15. data/lib/fera/app.rb +33 -0
  16. data/lib/fera/models/base.rb +374 -0
  17. data/lib/fera/models/collection.rb +26 -0
  18. data/lib/fera/models/concerns/belongs_to_customer.rb +70 -0
  19. data/lib/fera/models/concerns/belongs_to_order.rb +87 -0
  20. data/lib/fera/models/concerns/belongs_to_product.rb +48 -0
  21. data/lib/fera/models/concerns/belongs_to_review.rb +40 -0
  22. data/lib/fera/models/concerns/belongs_to_submission.rb +39 -0
  23. data/lib/fera/models/concerns/has_many_orders.rb +30 -0
  24. data/lib/fera/models/concerns/has_many_reviews.rb +30 -0
  25. data/lib/fera/models/concerns/has_many_submissions.rb +30 -0
  26. data/lib/fera/models/concerns/has_media.rb +95 -0
  27. data/lib/fera/models/concerns/has_subject.rb +44 -0
  28. data/lib/fera/models/customer.rb +8 -0
  29. data/lib/fera/models/media.rb +55 -0
  30. data/lib/fera/models/order.rb +5 -0
  31. data/lib/fera/models/photo.rb +5 -0
  32. data/lib/fera/models/product.rb +12 -0
  33. data/lib/fera/models/rating.rb +9 -0
  34. data/lib/fera/models/review.rb +18 -0
  35. data/lib/fera/models/store.rb +11 -0
  36. data/lib/fera/models/submission.rb +19 -0
  37. data/lib/fera/models/video.rb +5 -0
  38. data/lib/fera/models/webhook.rb +4 -0
  39. data/lib/fera.rb +4 -0
  40. metadata +167 -0
@@ -0,0 +1,48 @@
1
+ require 'active_support/concern'
2
+
3
+ module Fera
4
+ module BelongsToProduct
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ belongs_to :product, class_name: "Fera::Product"
9
+ end
10
+
11
+ def product=(product)
12
+ product_id = if product.is_a?(Product)
13
+ product.id
14
+ else
15
+ product.try(:with_indifferent_access).try(:[], :id)
16
+ end
17
+ external_product_id = if product.is_a?(Product)
18
+ product.external_id
19
+ else
20
+ product.try(:with_indifferent_access).try(:[], :external_id)
21
+ end
22
+ @product = if product.is_a?(Product)
23
+ product
24
+ else
25
+ Product.new(product, product_id.present?)
26
+ end
27
+ self.attributes['product_id'] = product_id
28
+ self.attributes['external_product_id'] = external_product_id
29
+ self.attributes.delete('product')
30
+ @product
31
+ end
32
+
33
+ def product
34
+ if @product.present?
35
+ @product
36
+ elsif attributes.key?('product') && attributes['product'].present?
37
+ Product.new(attributes['product'], true)
38
+ elsif attributes.key?('product_id') && product_id.present?
39
+ Product.find(product_id)
40
+ elsif attributes.key?('external_product_id') && external_product_id.present?
41
+ Product.find(external_product_id)
42
+ else
43
+ nil
44
+ end
45
+ end
46
+
47
+ end
48
+ end
@@ -0,0 +1,40 @@
1
+ require 'active_support/concern'
2
+
3
+ module Fera
4
+ module BelongsToReview
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ belongs_to :review, class_name: "Fera::Review"
9
+ end
10
+
11
+ def review=(review)
12
+ review_id = if review.is_a?(Review)
13
+ review.id
14
+ else
15
+ review.try(:with_indifferent_access).try(:[], :id)
16
+ end
17
+ @review = if review.is_a?(Review)
18
+ review
19
+ else
20
+ Review.new(review, review_id.present?)
21
+ end
22
+ self.attributes['review_id'] = review_id
23
+ self.attributes.delete('review')
24
+ @review
25
+ end
26
+
27
+ def review
28
+ if @review.present?
29
+ @review
30
+ elsif attributes.key?('review') && attributes['review'].present?
31
+ Review.new(attributes['review'], true)
32
+ elsif attributes.key?('review_id') && review_id.present?
33
+ Review.find(review_id)
34
+ else
35
+ nil
36
+ end
37
+ end
38
+
39
+ end
40
+ end
@@ -0,0 +1,39 @@
1
+ require 'active_support/concern'
2
+
3
+ module Fera
4
+ module BelongsToSubmission
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ belongs_to :submission, class_name: "Fera::Submission"
9
+ end
10
+
11
+ def submission=(submission)
12
+ submission_id = if submission.is_a?(Submission)
13
+ submission.id
14
+ else
15
+ submission.try(:with_indifferent_access).try(:[], :id)
16
+ end
17
+ @submission = if submission.is_a?(Submission)
18
+ submission
19
+ else
20
+ Submission.new(submission, submission_id.present?)
21
+ end
22
+ self.attributes['submission_id'] = submission_id
23
+ self.attributes.delete('submission')
24
+ @submission
25
+ end
26
+
27
+ def submission
28
+ if @submission.present?
29
+ @submission
30
+ elsif attributes.key?('submission') && attributes['submission'].present?
31
+ Submission.new(attributes['submission'], true)
32
+ elsif attributes.key?('submission_id') && submission_id.present?
33
+ Submission.find(submission_id)
34
+ else
35
+ nil
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,30 @@
1
+ require 'active_support/concern'
2
+
3
+ module Fera
4
+ module HasManyOrders
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ has_many :orders, class_name: "Fera::Order"
9
+ end
10
+
11
+ def orders=(new_orders)
12
+ @orders = new_orders.to_a.map do |model|
13
+ if model.is_a?(Order)
14
+ model
15
+ else
16
+ model_id = model.try(:with_indifferent_access).try(:[], :id)
17
+ Order.new(model, model_id.present?)
18
+ end
19
+ end
20
+ end
21
+
22
+ def photos(query = {})
23
+ if @orders && query.blank?
24
+ @orders.to_a
25
+ else
26
+ Order.where(query.merge("#{ self.class.name.demodulize.underscore }_id" => id))
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,30 @@
1
+ require 'active_support/concern'
2
+
3
+ module Fera
4
+ module HasManyReviews
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ has_many :reviews, class_name: "Fera::Review"
9
+ end
10
+
11
+ def reviews=(new_reviews)
12
+ @reviews = new_reviews.to_a.map do |model|
13
+ if model.is_a?(Review)
14
+ model
15
+ else
16
+ model_id = model.try(:with_indifferent_access).try(:[], :id)
17
+ Review.new(model, model_id.present?)
18
+ end
19
+ end
20
+ end
21
+
22
+ def reviews(query = {})
23
+ if @reviews && query.blank?
24
+ @reviews.to_a
25
+ else
26
+ Review.where(query.merge("#{ self.class.name.demodulize.underscore }_id" => id))
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,30 @@
1
+ require 'active_support/concern'
2
+
3
+ module Fera
4
+ module HasManySubmissions
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ has_many :submission, class_name: "Fera::Submission"
9
+ end
10
+
11
+ def submissions=(new_submissions)
12
+ @submissions = new_submissions.to_a.map do |model|
13
+ if model.is_a?(Submission)
14
+ model
15
+ else
16
+ model_id = model.try(:with_indifferent_access).try(:[], :id)
17
+ Submission.new(model, model_id.present?)
18
+ end
19
+ end
20
+ end
21
+
22
+ def submissions(query = {})
23
+ if @submissions && query.blank?
24
+ @submissions.to_a
25
+ else
26
+ Submission.where(query.merge("#{ self.class.name.demodulize.underscore }_id" => id))
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,95 @@
1
+ require 'active_support/concern'
2
+
3
+ module Fera
4
+ module HasMedia
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ has_many :media, class_name: "Fera::Media"
9
+ has_many :videos, class_name: "Fera::Video"
10
+ has_many :photos, class_name: "Fera::Photo"
11
+ end
12
+
13
+ def media=(inputs)
14
+ @media = inputs.to_a.map do |input|
15
+ self.new_media(input)
16
+ end
17
+ end
18
+
19
+ def add_media(input)
20
+ new_model = self.new_media(input)
21
+ if @media.nil?
22
+ @media = [new_model]
23
+ else
24
+ @media << new_model
25
+ end
26
+ end
27
+
28
+ def new_media(input = nil)
29
+ model_class = [Photo, Video].include?(input.class) ? input.class : Media
30
+ new_has_many_associated_model(model_class, input)
31
+ end
32
+
33
+ def media(query = {})
34
+ if @media && query.blank?
35
+ @media.to_a
36
+ else
37
+ Media.where(query.merge("#{ self.class.name.demodulize.underscore }_id" => id))
38
+ end
39
+ end
40
+
41
+ def photos=(inputs)
42
+ @photos = inputs.to_a.map do |input|
43
+ new_has_many_associated_model(Photo, input)
44
+ end
45
+ end
46
+
47
+ def add_photo(input)
48
+ new_model = self.new_photo(input)
49
+ if @photos.nil?
50
+ @photos = [new_model]
51
+ else
52
+ @photos << new_model
53
+ end
54
+ end
55
+
56
+ def new_photo(input = nil)
57
+ new_has_many_associated_model(Photo, input)
58
+ end
59
+
60
+ def photos(query = {})
61
+ if @photos && query.blank?
62
+ @photos.to_a
63
+ else
64
+ Photo.where(query.merge("#{ self.class.name.demodulize.underscore }_id" => id))
65
+ end
66
+ end
67
+
68
+ def videos=(inputs)
69
+ @videos = inputs.to_a.map do |input|
70
+ self.new_video(input)
71
+ end
72
+ end
73
+
74
+ def add_video(input)
75
+ new_model = self.new_video(input)
76
+ if @videos.nil?
77
+ @videos = [new_model]
78
+ else
79
+ @videos << new_model
80
+ end
81
+ end
82
+
83
+ def new_video(input = nil)
84
+ new_has_many_associated_model(Video, input)
85
+ end
86
+
87
+ def videos(query = {})
88
+ if @videos && query.blank?
89
+ @videos.to_a
90
+ else
91
+ Video.where(query.merge("#{ self.class.name.demodulize.underscore }_id" => id))
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,44 @@
1
+ require 'active_support/concern'
2
+
3
+ module Fera
4
+ module HasSubject
5
+ extend ActiveSupport::Concern
6
+
7
+ module ClassMethods
8
+ def for_products(product_ids = nil)
9
+ if product_ids.present?
10
+ where(product_id: product_ids)
11
+ else
12
+ where(subject: :product)
13
+ end
14
+ end
15
+
16
+ def for_product(product_id)
17
+ for_products(product_id).try(:first)
18
+ end
19
+
20
+ def for_store
21
+ all.where(subject: :store).try(:first)
22
+ end
23
+ end
24
+
25
+ ##
26
+ # Returns the associated product model if it was preloaded in the original request and if the object is for a product.
27
+ # @return [::Fera::Product, NilClass]
28
+ def product
29
+ if attributes['subject'] =~ /^product/i
30
+ super
31
+ else
32
+ nil
33
+ end
34
+ end
35
+
36
+ def for_product?
37
+ subject.to_s == 'product'
38
+ end
39
+
40
+ def for_store?
41
+ subject.to_s == 'store'
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,8 @@
1
+ module Fera
2
+ class Customer < Base
3
+ include HasManyReviews
4
+ include HasMedia
5
+ include HasManyOrders
6
+ include HasManySubmissions
7
+ end
8
+ end
@@ -0,0 +1,55 @@
1
+ module Fera
2
+ class Media < Base
3
+ include HasSubject
4
+ include BelongsToCustomer
5
+ include BelongsToProduct
6
+ include BelongsToReview
7
+ include BelongsToSubmission
8
+
9
+ after_create :remove_file_param
10
+
11
+ class << self
12
+ def instantiate_record(record, prefix_options = {})
13
+ new_klass = if record['type'] == 'video'
14
+ Video
15
+ else
16
+ Photo
17
+ end
18
+ new_klass.new(record, record['id'].present?).tap do |resource|
19
+ resource.prefix_options = prefix_options
20
+ end
21
+ end
22
+ end
23
+
24
+ def is_video?
25
+ type.to_s == 'video'
26
+ end
27
+ alias_method :video?, :is_video?
28
+
29
+ def is_photo?
30
+ type.to_s == 'photo'
31
+ end
32
+ alias_method :photo?, :is_photo?
33
+
34
+ def file=(f)
35
+ if f.is_a?(File)
36
+ file_name = File.basename(f.path)
37
+ mime_type_group = type == 'video' ? 'video' : 'image'
38
+ self.attributes['file'] = {
39
+ 'name' => File.basename(file_name),
40
+ 'data' => "data:#{ mime_type_group }/#{ file_name.split('.').last };base64,#{ Base64.encode64(f.read) }"
41
+ }
42
+ else
43
+ self.attributes['file'] = f
44
+ end
45
+ end
46
+
47
+ private
48
+
49
+ def remove_file_param
50
+ if self.attributes.key?('file')
51
+ self.attributes.delete('file')
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,5 @@
1
+ module Fera
2
+ class Order < Base
3
+ include BelongsToCustomer
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ module Fera
2
+ class Photo < Media
3
+ def type; 'video'; end
4
+ end
5
+ end
@@ -0,0 +1,12 @@
1
+ module Fera
2
+ class Product < Base
3
+ include HasManyReviews
4
+ include HasMedia
5
+
6
+ alias_attribute :rating, :average_rating
7
+
8
+ def self.ratings(query = {})
9
+ ProductRating.where(query)
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,9 @@
1
+ module Fera
2
+ class Rating < Base
3
+ include HasSubject
4
+ include BelongsToProduct
5
+
6
+ alias_attribute :value, :average
7
+ alias_attribute :rating, :average
8
+ end
9
+ end
@@ -0,0 +1,18 @@
1
+ module Fera
2
+ class Review < Base
3
+ include HasMedia
4
+ include HasSubject
5
+ include BelongsToCustomer
6
+ include BelongsToProduct
7
+ include BelongsToSubmission
8
+
9
+ def only_rating?
10
+ body.blank? && heading.blank?
11
+ end
12
+ alias_method :rating_only?, :only_rating?
13
+
14
+ def stars
15
+ (('★' * rating) + ('☆' * (5 - rating))).chars.join(" ")
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,11 @@
1
+ module Fera
2
+ class Store < Base
3
+ include ActiveResource::Singleton
4
+
5
+ self.singleton_name = :store
6
+
7
+ def self.current(options = {})
8
+ find(options)
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,19 @@
1
+ module Fera
2
+ class Submission < Base
3
+ include HasMedia
4
+ include HasManyReviews
5
+ include BelongsToCustomer
6
+ include BelongsToOrder
7
+
8
+ schema do
9
+ string 'id'
10
+ string 'external_customer_id'
11
+ string 'customer_id'
12
+
13
+ boolean 'is_test'
14
+
15
+ timestamp 'created_at'
16
+ timestamp 'updated_at'
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,5 @@
1
+ module Fera
2
+ class Video < Media
3
+ def type; 'video'; end
4
+ end
5
+ end
@@ -0,0 +1,4 @@
1
+ module Fera
2
+ class Webhook < Base
3
+ end
4
+ end
data/lib/fera.rb ADDED
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Fera
4
+ end