dcparker-shopify 0.1.0
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.
- data/CHANGELOG +1 -0
- data/LICENSE +0 -0
- data/Manifest +13 -0
- data/README +9 -0
- data/lib/shopify.rb +93 -0
- data/lib/shopify/address.rb +17 -0
- data/lib/shopify/order.rb +36 -0
- data/lib/shopify/product.rb +45 -0
- data/lib/shopify/sale.rb +11 -0
- data/lib/shopify/session.rb +83 -0
- data/lib/shopify/shop.rb +8 -0
- data/lib/shopify/site.rb +14 -0
- data/shopify.gemspec +37 -0
- metadata +100 -0
data/CHANGELOG
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
v0.1.0 First release, a rewrite of Shopify's own Rails plugin, turned into a gem with similar workings.
|
data/LICENSE
ADDED
File without changes
|
data/Manifest
ADDED
data/README
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
Example Usage:
|
2
|
+
|
3
|
+
Shopify.current_session = Shopify::Session.new('store_name', 'api-key', 'api-secret')
|
4
|
+
Shopify.current_session.token = 'api-session-token'
|
5
|
+
Shopify.apply_current_session!
|
6
|
+
|
7
|
+
Shopify::Shop.current
|
8
|
+
Shopify::Product.find(:first)
|
9
|
+
Shopify::Order.find(:first)
|
data/lib/shopify.rb
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
module Shopify
|
2
|
+
autoload :Session, 'shopify/session'
|
3
|
+
autoload :Shop, 'shopify/shop'
|
4
|
+
autoload :Product, 'shopify/product'
|
5
|
+
autoload :Variant, 'shopify/product'
|
6
|
+
autoload :Image, 'shopify/product'
|
7
|
+
autoload :Order, 'shopify/order'
|
8
|
+
autoload :LineItem, 'shopify/order'
|
9
|
+
autoload :ShippingLine, 'shopify/order'
|
10
|
+
autoload :CustomCollection, 'shopify/order'
|
11
|
+
autoload :ShippingAddress, 'shopify/address'
|
12
|
+
autoload :BillingAddress, 'shopify/address'
|
13
|
+
autoload :Country, 'shopify/address'
|
14
|
+
autoload :Province, 'shopify/address'
|
15
|
+
autoload :Sale, 'shopify/sale'
|
16
|
+
autoload :Authorization, 'shopify/sale'
|
17
|
+
autoload :Payment, 'shopify/sale'
|
18
|
+
autoload :Page, 'shopify/site'
|
19
|
+
autoload :Blog, 'shopify/site'
|
20
|
+
autoload :Article, 'shopify/site'
|
21
|
+
|
22
|
+
class << self
|
23
|
+
attr_reader :key, :secret
|
24
|
+
|
25
|
+
# Lists the session stack.
|
26
|
+
def sessions
|
27
|
+
@sessions ||= []
|
28
|
+
end
|
29
|
+
|
30
|
+
# Returns the last session on the sessions stack.
|
31
|
+
def current_session
|
32
|
+
sessions.last
|
33
|
+
end
|
34
|
+
|
35
|
+
# Sets the current_session / appends a session to the sessions stack.
|
36
|
+
def current_session=(session)
|
37
|
+
sessions << session
|
38
|
+
end
|
39
|
+
|
40
|
+
# Injects the generated site (with basic auth params) into the ActiveResource::Base subclasses.
|
41
|
+
def apply_current_session!
|
42
|
+
current_session.apply!
|
43
|
+
end
|
44
|
+
|
45
|
+
# Perform a block within a specific session, and reset the current session to the previous after execution.
|
46
|
+
def with_session(session,&block)
|
47
|
+
sessions << session
|
48
|
+
apply_current_session!
|
49
|
+
result = yield
|
50
|
+
sessions.pop
|
51
|
+
apply_current_session!
|
52
|
+
return result
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# To fix a silly bug in ActiveResource loading... :(
|
58
|
+
module Enumerable # :nodoc: all
|
59
|
+
def group_by
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# Load ActiveResource
|
64
|
+
gem 'activeresource', '>= 2.1.0'
|
65
|
+
require 'active_resource'
|
66
|
+
module ActiveResource # :nodoc: all
|
67
|
+
class Base
|
68
|
+
class << self
|
69
|
+
def site
|
70
|
+
# Not using superclass_delegating_reader because don't want subclasses to modify superclass instance
|
71
|
+
#
|
72
|
+
# With superclass_delegating_reader
|
73
|
+
#
|
74
|
+
# Parent.site = 'http://anonymous@test.com'
|
75
|
+
# Subclass.site # => 'http://anonymous@test.com'
|
76
|
+
# Subclass.site.user = 'david'
|
77
|
+
# Parent.site # => 'http://david@test.com'
|
78
|
+
#
|
79
|
+
# Without superclass_delegating_reader (expected behaviour)
|
80
|
+
#
|
81
|
+
# Parent.site = 'http://anonymous@test.com'
|
82
|
+
# Subclass.site # => 'http://anonymous@test.com'
|
83
|
+
# Subclass.site.user = 'david' # => TypeError: can't modify frozen object
|
84
|
+
#
|
85
|
+
if defined?(@site)
|
86
|
+
@site
|
87
|
+
elsif superclass != Object && superclass.site
|
88
|
+
superclass.site.dup.freeze
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Shopify
|
2
|
+
class ShippingAddress < ActiveResource::Base
|
3
|
+
end
|
4
|
+
|
5
|
+
class BillingAddress < ActiveResource::Base
|
6
|
+
def name
|
7
|
+
"#{first_name} #{last_name}"
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class Country < ActiveResource::Base
|
12
|
+
end
|
13
|
+
|
14
|
+
class Province < ActiveResource::Base
|
15
|
+
self.prefix = "/admin/countries/:country_id/"
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Shopify
|
2
|
+
class Order < ActiveResource::Base
|
3
|
+
def fulfilled?
|
4
|
+
!!fulfillment_status
|
5
|
+
end
|
6
|
+
|
7
|
+
def closed?
|
8
|
+
closed_at < Time.now
|
9
|
+
end
|
10
|
+
|
11
|
+
def close
|
12
|
+
load_attributes_from_response(post(:close))
|
13
|
+
end
|
14
|
+
|
15
|
+
def open
|
16
|
+
load_attributes_from_response(post(:open))
|
17
|
+
end
|
18
|
+
|
19
|
+
def payments
|
20
|
+
Payment.get
|
21
|
+
end
|
22
|
+
|
23
|
+
def capture(amount=nil)
|
24
|
+
load_attributes_from_response(post(:capture, :amount => amount))
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class LineItem < ActiveResource::Base
|
29
|
+
end
|
30
|
+
|
31
|
+
class ShippingLine < ActiveResource::Base
|
32
|
+
end
|
33
|
+
|
34
|
+
class CustomCollection < ActiveResource::Base
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Shopify
|
2
|
+
class Product < ActiveResource::Base
|
3
|
+
class << self
|
4
|
+
# Share all items of this store with the shopify marketplace
|
5
|
+
def share_all
|
6
|
+
post :share
|
7
|
+
end
|
8
|
+
# Stop sharing all items of this store with the shopify marketplace
|
9
|
+
def unshare_all
|
10
|
+
delete :share
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
# Auto-compute the price range
|
15
|
+
def price_range
|
16
|
+
prices = variants.collect(&:price)
|
17
|
+
format = "%0.2f"
|
18
|
+
if prices.min != prices.max
|
19
|
+
"#{format % prices.min} - #{format % prices.max}"
|
20
|
+
else
|
21
|
+
format % prices.min
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class Variant < ActiveResource::Base
|
27
|
+
self.prefix = "/admin/products/:product_id/"
|
28
|
+
end
|
29
|
+
|
30
|
+
class Image < ActiveResource::Base
|
31
|
+
self.prefix = "/admin/products/:product_id/"
|
32
|
+
|
33
|
+
# generate a method for each possible image variant
|
34
|
+
[:pico, :icon, :thumb, :small, :medium, :large, :original].each do |m|
|
35
|
+
reg_exp_match = "/\\1_#{m}.\\2"
|
36
|
+
define_method(m) { src.gsub(/\/(.*)\.(\w{2,4})/, reg_exp_match) }
|
37
|
+
end
|
38
|
+
|
39
|
+
# Attach an image to a product.
|
40
|
+
def attach_image(data, filename = nil)
|
41
|
+
attributes[:attachment] = Base64.encode64(data)
|
42
|
+
attributes[:filename] = filename unless filename.nil?
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/lib/shopify/sale.rb
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'digest/md5'
|
2
|
+
|
3
|
+
module Shopify
|
4
|
+
# Shopify Session
|
5
|
+
#
|
6
|
+
# Example:
|
7
|
+
# class LoginController < ApplicationController
|
8
|
+
# layout 'empty'
|
9
|
+
#
|
10
|
+
# before { Shopify.sessions << Shopify::Session.new(session[:store_name] || params[:store_name], session[:shopify_token], SHOPIFY_APP_SECRET) if Shopify.sessions.empty? && (session[:store_name] || params[:store_name]) }
|
11
|
+
#
|
12
|
+
# def signin
|
13
|
+
# # ask user for his myshopify.com address.
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# # POST to this with the store name
|
17
|
+
# def login
|
18
|
+
# # Set the store_name into the session for future requests.
|
19
|
+
# session[:store_name] = params[:store_name]
|
20
|
+
# # This will redirect the user to their Shopify store to authorize your application.
|
21
|
+
# # Shopify will redirect the user back to your :finalize action when finished.
|
22
|
+
# redirect Shopify.current_session.permission_url
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# def finalize
|
26
|
+
# Shopify.current_session.token = params[:t]
|
27
|
+
# Shopify.apply_current_session!
|
28
|
+
# if Shopify.current_session.signed_in?
|
29
|
+
# redirect # logged in area
|
30
|
+
# else
|
31
|
+
# flash[:notice] = "Couldn't sign in to your shopify store."
|
32
|
+
# redirect url(:signin)
|
33
|
+
# end
|
34
|
+
# end
|
35
|
+
# end
|
36
|
+
#
|
37
|
+
class Session
|
38
|
+
cattr_accessor :protocol
|
39
|
+
self.protocol = 'http'
|
40
|
+
|
41
|
+
attr_accessor :host, :key, :secret, :token
|
42
|
+
|
43
|
+
def initialize(host, key=nil, secret=nil, token=nil)
|
44
|
+
host.gsub!(/https?:\/\//, '') # remove http://
|
45
|
+
host = "#{host}.myshopify.com" unless host.include?('.') # extend url to myshopify.com if no host is given
|
46
|
+
|
47
|
+
self.host = host
|
48
|
+
self.key = key
|
49
|
+
self.secret = secret
|
50
|
+
self.token = token
|
51
|
+
end
|
52
|
+
|
53
|
+
# mode can be either r to request read rights or w to request read/write rights.
|
54
|
+
def permission_url(mode='w')
|
55
|
+
"http://#{host}/admin/api/auth?api_key=#{key}&mode=#{mode}"
|
56
|
+
end
|
57
|
+
|
58
|
+
def apply!
|
59
|
+
ActiveResource::Base.site = site if signed_in?
|
60
|
+
end
|
61
|
+
|
62
|
+
# use this to initialize ActiveResource:
|
63
|
+
#
|
64
|
+
# ActiveResource::Base.site = Shopify.current_session.site
|
65
|
+
#
|
66
|
+
def site
|
67
|
+
"#{protocol}://#{key}:#{password}@#{host}/admin"
|
68
|
+
end
|
69
|
+
|
70
|
+
def signed_in?
|
71
|
+
[host, key, secret, token].all?
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
# The secret is computed by taking the shared_secret which we got when
|
77
|
+
# registring this third party application and concating the request_to it,
|
78
|
+
# and then calculating a MD5 hexdigest.
|
79
|
+
def password
|
80
|
+
Digest::MD5.hexdigest("#{secret.chomp}#{token.chomp}")
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
data/lib/shopify/shop.rb
ADDED
data/lib/shopify/site.rb
ADDED
data/shopify.gemspec
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{shopify}
|
5
|
+
s.version = "0.1.0"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Daniel Parker"]
|
9
|
+
s.date = %q{2008-12-10}
|
10
|
+
s.description = %q{Easily communicate with Shopify.com's restful API.}
|
11
|
+
s.email = %q{gems@behindlogic.com}
|
12
|
+
s.extra_rdoc_files = ["CHANGELOG", "lib/shopify/address.rb", "lib/shopify/order.rb", "lib/shopify/product.rb", "lib/shopify/sale.rb", "lib/shopify/session.rb", "lib/shopify/shop.rb", "lib/shopify/site.rb", "lib/shopify.rb", "LICENSE", "README"]
|
13
|
+
s.files = ["CHANGELOG", "lib/shopify/address.rb", "lib/shopify/order.rb", "lib/shopify/product.rb", "lib/shopify/sale.rb", "lib/shopify/session.rb", "lib/shopify/shop.rb", "lib/shopify/site.rb", "lib/shopify.rb", "LICENSE", "Manifest", "README", "shopify.gemspec"]
|
14
|
+
s.has_rdoc = true
|
15
|
+
s.homepage = %q{http://github.com/dcparker/shopify/tree}
|
16
|
+
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Shopify", "--main", "README"]
|
17
|
+
s.require_paths = ["lib"]
|
18
|
+
s.rubyforge_project = %q{shopify}
|
19
|
+
s.rubygems_version = %q{1.3.1}
|
20
|
+
s.summary = %q{Easily communicate with Shopify.com's restful API.}
|
21
|
+
|
22
|
+
if s.respond_to? :specification_version then
|
23
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
24
|
+
s.specification_version = 2
|
25
|
+
|
26
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
27
|
+
s.add_runtime_dependency(%q<activeresource>, [">= 0", "= 2.1.0"])
|
28
|
+
s.add_development_dependency(%q<echoe>, [">= 0"])
|
29
|
+
else
|
30
|
+
s.add_dependency(%q<activeresource>, [">= 0", "= 2.1.0"])
|
31
|
+
s.add_dependency(%q<echoe>, [">= 0"])
|
32
|
+
end
|
33
|
+
else
|
34
|
+
s.add_dependency(%q<activeresource>, [">= 0", "= 2.1.0"])
|
35
|
+
s.add_dependency(%q<echoe>, [">= 0"])
|
36
|
+
end
|
37
|
+
end
|
metadata
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: dcparker-shopify
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Daniel Parker
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2008-12-10 00:00:00 -08:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: activeresource
|
17
|
+
version_requirement:
|
18
|
+
version_requirements: !ruby/object:Gem::Requirement
|
19
|
+
requirements:
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: "0"
|
23
|
+
- - "="
|
24
|
+
- !ruby/object:Gem::Version
|
25
|
+
version: 2.1.0
|
26
|
+
version:
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: echoe
|
29
|
+
version_requirement:
|
30
|
+
version_requirements: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - ">="
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: "0"
|
35
|
+
version:
|
36
|
+
description: Easily communicate with Shopify.com's restful API.
|
37
|
+
email: gems@behindlogic.com
|
38
|
+
executables: []
|
39
|
+
|
40
|
+
extensions: []
|
41
|
+
|
42
|
+
extra_rdoc_files:
|
43
|
+
- CHANGELOG
|
44
|
+
- lib/shopify/address.rb
|
45
|
+
- lib/shopify/order.rb
|
46
|
+
- lib/shopify/product.rb
|
47
|
+
- lib/shopify/sale.rb
|
48
|
+
- lib/shopify/session.rb
|
49
|
+
- lib/shopify/shop.rb
|
50
|
+
- lib/shopify/site.rb
|
51
|
+
- lib/shopify.rb
|
52
|
+
- LICENSE
|
53
|
+
- README
|
54
|
+
files:
|
55
|
+
- CHANGELOG
|
56
|
+
- lib/shopify/address.rb
|
57
|
+
- lib/shopify/order.rb
|
58
|
+
- lib/shopify/product.rb
|
59
|
+
- lib/shopify/sale.rb
|
60
|
+
- lib/shopify/session.rb
|
61
|
+
- lib/shopify/shop.rb
|
62
|
+
- lib/shopify/site.rb
|
63
|
+
- lib/shopify.rb
|
64
|
+
- LICENSE
|
65
|
+
- Manifest
|
66
|
+
- README
|
67
|
+
- shopify.gemspec
|
68
|
+
has_rdoc: true
|
69
|
+
homepage: http://github.com/dcparker/shopify/tree
|
70
|
+
post_install_message:
|
71
|
+
rdoc_options:
|
72
|
+
- --line-numbers
|
73
|
+
- --inline-source
|
74
|
+
- --title
|
75
|
+
- Shopify
|
76
|
+
- --main
|
77
|
+
- README
|
78
|
+
require_paths:
|
79
|
+
- lib
|
80
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
81
|
+
requirements:
|
82
|
+
- - ">="
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: "0"
|
85
|
+
version:
|
86
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: "1.2"
|
91
|
+
version:
|
92
|
+
requirements: []
|
93
|
+
|
94
|
+
rubyforge_project: shopify
|
95
|
+
rubygems_version: 1.2.0
|
96
|
+
signing_key:
|
97
|
+
specification_version: 2
|
98
|
+
summary: Easily communicate with Shopify.com's restful API.
|
99
|
+
test_files: []
|
100
|
+
|