cornerstore 0.6.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: dfc2a280092553731812a736e6e328ca98c4684a
4
+ data.tar.gz: 91b3b7e4604d61bf9de7f93f5e9eddfda886bffb
5
+ SHA512:
6
+ metadata.gz: 0dfd5351f44be439ac06b31fb00d62434affced7c7549f5007cfb14f8aa517f0afe02387e914ebbe0867d1c898913f788fbf77c6bb95d53c7596be294a94c402
7
+ data.tar.gz: d3eae73f7a1b60d331b2ec5172b09a9094b029f98cccaa13cb743d3c4fd91228c9ec22cb300855f93874ce4956cc8d6fe306fed7c22fd5e2ea6d9139d88161b5
@@ -0,0 +1,15 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ tmp
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in cornerstore.gemspec
4
+ gemspec
@@ -0,0 +1,75 @@
1
+ # Cornerstore
2
+
3
+ This is a client for the Cornerstore API-based online shop. Cornerstore allows you to create custom online shops
4
+ with your own front-end code, platform and tool belt choices. Instead of reinventing the wheel however, Cornerstore will
5
+ supply you with common e-commerce resources like products and carts via API. It also includes a checkout and Manager interface,
6
+ so your customers can manage their products and orders without you having to code yet another admin back-end.
7
+
8
+ Learn more about Cornerstore at http://www.cornerstore.io and http://addons.heroku.com/cornerstore
9
+
10
+ ## Authentication
11
+
12
+ The gem tries to retrieve your Cornerstore credentials in the following order:
13
+
14
+ 1. It checks if the env variable CORNERSTORE_URL is set and extracts the credentials. If you provisioned
15
+ with Heroku this variable is already configured.
16
+
17
+ 2. If no env variable is available it checks the secrets.yml file on Rails 4.1 or looks for a
18
+ cornerstore.yml on previous versions. See examples/cornerstore.yml for an example.
19
+
20
+ 3. You can always set the credentials directly by using the Cornerstore.subdomain= and Cornerstore.api_key=
21
+ methods.
22
+
23
+ ## Getting products & collections
24
+
25
+ You can retrieve products from Cornerstore like so:
26
+
27
+ product = Cornerstore::Product.find('sugo-al-basilico')
28
+ product.manufacturer #=> "Fattoria Croccante"
29
+
30
+ product = Cornerstore::Product.find('5900338280000393023')
31
+ product.name #=> "Sugo Al Basilico"
32
+
33
+ collection = Cornerstore::Collection.find('spaghetti').child_collections.first
34
+ product = collection.products.first
35
+ product.variants.any? #=> true
36
+ product.variants.first.price.decimal_amount #=> 12.99
37
+
38
+ ## Creating carts and adding line items
39
+
40
+ You can create carts and handle line items as state below. Line items can either be created from scratch or you can
41
+ derive them from a product/variant.
42
+
43
+ cart = Cornerstore::Cart.new({
44
+ success_redirect_url: "http://yourshop.com/cart/success",
45
+ cart_url: "http://yourshop.com/cart"
46
+ })
47
+
48
+ product = Cornerstore::Product.find('sugo-al-basilico')
49
+ variant = product.variants.find('SBS-39993')
50
+
51
+ # Derive from variant
52
+ cart.line_items.create_from_variant(variant, qty: 10)
53
+
54
+ line_item = cart.line_items.first
55
+ line_item.qty = 15
56
+ line_item.save
57
+
58
+ another_line_item = cart.line_items.last
59
+ another_line_item.destroy
60
+
61
+ # Create a line item directly
62
+ line_item = Cornerstore::LineItem.create({
63
+ qty: 10,
64
+ description: 'My own custom line item',
65
+ unit: 'Piece',
66
+ weight: 0.5,
67
+ price: Cornerstore::Price.new(12.99, 'USD')
68
+ })
69
+
70
+ ## Learn more
71
+
72
+ We provide a full API documentation at http://developer.cornerstore.io/api, including many ruby examples. Generally every
73
+ attribute that is listed in the API docs corresponds to a ruby method that can be called on the respective objects. In
74
+ many cases there are additional methods available, just check out the classes of this gem and our Rails example store
75
+ and boilerplate at https://github.com/crispymtn/fattoria-croccante.
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'cornerstore/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "cornerstore"
8
+ gem.version = Cornerstore::VERSION
9
+ gem.authors = ['Johannes Treitz', 'Christian Weyer']
10
+ gem.email = ['jt@crispymtn.com', 'cw@crispymtn.com']
11
+ gem.description = "This is a client for the Cornerstore e-commerce API"
12
+ gem.summary = "This is a client for the Cornerstore e-commerce API"
13
+ gem.homepage = "https://www.github.com/crispymtn/cornerstore-gem"
14
+ gem.files = `git ls-files`.split($/)
15
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
16
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
17
+ gem.require_paths = ["lib"]
18
+
19
+ gem.add_dependency 'rest-client'
20
+ gem.add_dependency 'activemodel'
21
+ gem.add_development_dependency "rspec"
22
+
23
+ end
@@ -0,0 +1,11 @@
1
+ development:
2
+ subdomain: your-shop-staging
3
+ api_key: dffe7d7382199992dfe # You find the API keys in the Cornerstore Manager under Settings > API
4
+
5
+ test:
6
+ subdomain: your-shop-staging
7
+ api_key: dffe7d7382199992dfe
8
+
9
+ production:
10
+ subdomain: your-shop
11
+ api_key: deee636888117727782
@@ -0,0 +1,84 @@
1
+ require 'active_model'
2
+ require 'rest_client'
3
+
4
+ require 'cornerstore/version'
5
+ require 'cornerstore/resource'
6
+ require 'cornerstore/model'
7
+ require 'cornerstore/api'
8
+
9
+ module RestClient::AbstractResponse
10
+ def success?
11
+ (200..207).include? code
12
+ end
13
+ end
14
+
15
+ RestClient.log = 'stdout'
16
+
17
+ module Cornerstore
18
+ class << self
19
+ attr_writer :subdomain, :api_key
20
+ end
21
+
22
+ def self.subdomain
23
+ @subdomain ||= read_config[:subdomain]
24
+ end
25
+
26
+ def self.root_url
27
+ "https://#{subdomain}.cornerstore.io/api/v1"
28
+ end
29
+
30
+ def self.assets_url
31
+ "http://cskit-production.s3.amazonaws.com"
32
+ end
33
+
34
+ def self.headers
35
+ {
36
+ user_agent: "cornerstore-gem/#{Cornerstore::VERSION}",
37
+ authorization: "Token #{api_key}"
38
+ }
39
+ end
40
+
41
+ private
42
+ # We have three levels of configuration
43
+ # - Can be manually set with accessors on this module
44
+ # - Can be supplied by Rails secret file
45
+ # - Can be supplied by a cornerstore yml file
46
+ # - Can be supplied via CORNERSTORE_URL env variable
47
+ def self.read_config
48
+ config = {}
49
+
50
+ # ENV variable set beats everything. If we got one we use it regardless
51
+ # of other config options
52
+ if ENV.has_key?('CORNERSTORE_URL') and uri = URI.parse(ENV['CORNERSTORE_URL'])
53
+ config[:subdomain] = uri.host.sub('.cornerstore.io', '')
54
+ config[:api_key] = uri.password
55
+
56
+ else
57
+ # Is this Rails?
58
+ if defined?(Rails)
59
+ # Try to get the credentials from the secret storage,
60
+ # if that fails try to read the YAML file
61
+ if not (Rails.application.respond_to?(:secrets) and
62
+ config[:subdomain] = Rails.application.secrets.cornerstore_subdomain and
63
+ config[:api_key] = Rails.application.secrets.cornerstore_api_key)
64
+
65
+ yml_path = Rails.root.join('config', 'cornerstore.yml')
66
+
67
+ if File.exists?(yml_path) and yaml = YAML.load(File.read(yml_path))
68
+ config[:subdomain] = yaml[Rails.env]['subdomain']
69
+ config[:api_key] = yaml[Rails.env]['api_key']
70
+ end
71
+ end
72
+
73
+ else
74
+ raise ArgumentError, 'Could not find any Cornerstore credentials, please set them before proceeding'
75
+ end
76
+ end
77
+
78
+ return config
79
+ end
80
+
81
+ def self.api_key
82
+ @api_ley ||= read_config[:api_key]
83
+ end
84
+ end
@@ -0,0 +1,18 @@
1
+ require 'cornerstore/api/product'
2
+ require 'cornerstore/api/variant'
3
+ require 'cornerstore/api/price'
4
+ require 'cornerstore/api/property'
5
+ require 'cornerstore/api/differentiating_property'
6
+ require 'cornerstore/api/image'
7
+ require 'cornerstore/api/collection'
8
+ require 'cornerstore/api/cart'
9
+ require 'cornerstore/api/line_item'
10
+ require 'cornerstore/api/search'
11
+
12
+ require 'cornerstore/api/order'
13
+ require 'cornerstore/api/payment_means'
14
+ require 'cornerstore/api/cancellation'
15
+ require 'cornerstore/api/shipment'
16
+ require 'cornerstore/api/carrier'
17
+ require 'cornerstore/api/address'
18
+ require 'cornerstore/api/customer'
@@ -0,0 +1,12 @@
1
+ class Cornerstore::Address < Cornerstore::Model::Base
2
+ attr_accessor :firstname,
3
+ :name,
4
+ :company,
5
+ :street,
6
+ :number,
7
+ :addition,
8
+ :town,
9
+ :zip,
10
+ :country,
11
+ :state
12
+ end
@@ -0,0 +1,22 @@
1
+ class Cornerstore::Cancellation < Cornerstore::Model::Base
2
+ attr_accessor :created_at,
3
+ :line_item_ids
4
+
5
+ alias_method :canceled_at, :created_at
6
+
7
+ def initialize(attributes = {}, parent=nil)
8
+ self.line_item_ids = attributes.delete('canceled_items')
9
+ self.created_at = DateTime.parse(attributes.delete('created_at')) unless attributes['created_at'].blank?
10
+
11
+ super
12
+ end
13
+
14
+ def line_items
15
+ return [] unless self.parent
16
+ self.parent.line_items.select { |li| self.line_item_ids.include?(li.id) }
17
+ end
18
+ alias_method :canceled_items, :line_items
19
+
20
+ class Resource < Cornerstore::Resource::Base
21
+ end
22
+ end
@@ -0,0 +1,3 @@
1
+ class Cornerstore::Carrier < Cornerstore::Model::Base
2
+ attr_accessor :name, :service
3
+ end
@@ -0,0 +1,49 @@
1
+ class Cornerstore::Cart < Cornerstore::Model::Base
2
+ include Cornerstore::Model::Writable
3
+
4
+ attr_accessor :line_items, :reference, :total, :success_redirect_url, :cart_url, :invoice_pdf_callback_url,
5
+ :delivery_note_pdf_callback_url, :placed_email_callback_url, :shipped_email_callback_url, :paid_email_callback_url, :canceled_email_callback_url
6
+
7
+ def initialize(attributes = {}, parent=nil)
8
+ self.total = Cornerstore::Price.new(attributes.delete('total'))
9
+ self.line_items = Cornerstore::LineItem::Resource.new(self, attributes.delete('line_items') || [], 'line_items')
10
+ super
11
+ end
12
+
13
+ def id
14
+ reference
15
+ end
16
+ alias to_param id
17
+
18
+ def attributes
19
+ {
20
+ reference: reference,
21
+ success_redirect_url: success_redirect_url,
22
+ cart_url: cart_url,
23
+ invoice_pdf_callback_url: invoice_pdf_callback_url,
24
+ delivery_note_pdf_callback_url: delivery_note_pdf_callback_url,
25
+ placed_email_callback_url: placed_email_callback_url,
26
+ shipped_email_callback_url: shipped_email_callback_url,
27
+ paid_email_callback_url: paid_email_callback_url,
28
+ canceled_email_callback_url: canceled_email_callback_url
29
+ }
30
+ end
31
+
32
+ def empty!
33
+ line_items.delete_all
34
+ line_items.empty?
35
+ end
36
+
37
+ def empty?
38
+ line_items.empty?
39
+ end
40
+
41
+ def checkout_url
42
+ "https://#{Cornerstore.subdomain}.cornerstore.io/checkout/#{self.reference}"
43
+ end
44
+
45
+ class Resource < Cornerstore::Resource::Base
46
+ include Cornerstore::Resource::Remote
47
+ include Cornerstore::Resource::Writable
48
+ end
49
+ end
@@ -0,0 +1,25 @@
1
+ class Cornerstore::Collection < Cornerstore::Model::Base
2
+ attr_accessor :name,
3
+ :parent,
4
+ :members,
5
+ :childs,
6
+ :products,
7
+ :properties
8
+
9
+ def initialize(attributes = {}, parent = nil)
10
+ self.products = Cornerstore::Product::Resource.new(self)
11
+ self.childs = Cornerstore::Collection::Resource.new(self, attributes.delete('child_collections') || [], 'childs')
12
+ self.properties = Cornerstore::Property::Resource.new(self, attributes.delete('properties') || [])
13
+ super
14
+ end
15
+
16
+ def attributes
17
+ {
18
+ name: name
19
+ }
20
+ end
21
+
22
+ class Resource < Cornerstore::Resource::Base
23
+ include Cornerstore::Resource::Remote
24
+ end
25
+ end
@@ -0,0 +1,4 @@
1
+ class Cornerstore::Customer < Cornerstore::Model::Base
2
+ attr_accessor :email,
3
+ :phone
4
+ end
@@ -0,0 +1,15 @@
1
+ class Cornerstore::DifferentiatingProperty < Cornerstore::Model::Base
2
+ attr_accessor :key,
3
+ :value
4
+
5
+ def attributes
6
+ {
7
+ hide_from: hide_from,
8
+ key: key,
9
+ value: value
10
+ }
11
+ end
12
+
13
+ class Resource < Cornerstore::Resource::Base
14
+ end
15
+ end
@@ -0,0 +1,20 @@
1
+ class Cornerstore::Image < Cornerstore::Model::Base
2
+ attr_accessor :cover,
3
+ :size,
4
+ :format,
5
+ :height,
6
+ :width,
7
+ :key
8
+
9
+
10
+ alias content_type format
11
+ alias file_size size
12
+
13
+ # small, small_square, medium, medium_square, large
14
+ def url(w = 600, h = 600, mode = 'crop')
15
+ "http://res.cloudinary.com/hgzhd1stm/image/upload/c_#{mode},h_#{h},w_#{w}/#{self.key}"
16
+ end
17
+
18
+ class Resource < Cornerstore::Resource::Base
19
+ end
20
+ end
@@ -0,0 +1,74 @@
1
+ class Cornerstore::LineItem < Cornerstore::Model::Base
2
+ include Cornerstore::Model::Writable
3
+
4
+ attr_accessor :order_number,
5
+ :description,
6
+ :qty,
7
+ :unit,
8
+ :price,
9
+ :total,
10
+ :weight,
11
+ :properties,
12
+ :product,
13
+ :variant
14
+
15
+ alias cart parent
16
+
17
+ validates :order_number, length: { within: 1..50 }
18
+ validates :description, length: { within: 1..255 }
19
+ validates :qty, numericality: { greater_than: 0, only_integer: true }
20
+ validates :unit, length: { within: 1..20 }
21
+ validates :price, presence: true
22
+ validates :weight, numericality: { greater_than: 0, allow_nil: true }
23
+ validate do
24
+ errors.add(:price, 'Price must be valid') unless price.valid?
25
+ end
26
+
27
+ def initialize(attributes = {}, parent = nil)
28
+ self.price = Cornerstore::Price.new(attributes.delete('price'))
29
+ self.total = Cornerstore::Price.new(attributes.delete('total'))
30
+ self.properties = Cornerstore::Property::Resource.new(self, attributes.delete('properties') || [])
31
+ self.product = Cornerstore::Product.new(attributes.delete('product')) if attributes['product']
32
+ self.variant = Cornerstore::Variant.new(attributes.delete('variant'), self.product) if attributes['variant']
33
+ super
34
+ end
35
+
36
+ def attributes
37
+ {
38
+ order_number: order_number,
39
+ description: description,
40
+ qty: qty,
41
+ unit: unit,
42
+ price: price.attributes,
43
+ weight: weight
44
+ }
45
+ end
46
+
47
+ class Resource < Cornerstore::Resource::Base
48
+ include Cornerstore::Resource::Remote
49
+ include Cornerstore::Resource::Writable
50
+
51
+ def create_from_variant(variant, attr={})
52
+ attributes = {
53
+ variant_id: variant.id,
54
+ product_id: variant.product._id,
55
+ line_item: attr
56
+ }
57
+
58
+ RestClient.post("#{Cornerstore.root_url}/carts/#{@parent.id}/line_items/derive.json", attributes, Cornerstore.headers) do |response, request, result, &block|
59
+ if response.code == 201
60
+ attributes = ActiveSupport::JSON.decode(response)
61
+ line_item = @klass.new(attributes, @parent)
62
+ elsif response.code == 422 and data = ActiveSupport::JSON.decode(response) and data.has_key?('errors')
63
+ line_item = @klass.new(attr, @parent)
64
+ data['errors'].each_pair do |key, messages|
65
+ messages.map { |message| line_item.errors.add(key, message) }
66
+ end
67
+ end
68
+
69
+ push line_item
70
+ line_item
71
+ end
72
+ end
73
+ end
74
+ end