shopifydev 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. data/.gitignore +17 -0
  2. data/.pryrc +3 -0
  3. data/.root.shopifydev.yaml.sample +21 -0
  4. data/.ruby-version +1 -0
  5. data/.shopifydev.yaml.sample +7 -0
  6. data/Gemfile +4 -0
  7. data/LICENSE.txt +22 -0
  8. data/NEXTSTEPS.md +33 -0
  9. data/README.md +78 -0
  10. data/Rakefile +1 -0
  11. data/bin/shopify_console +15 -0
  12. data/bin/shopifydev +100 -0
  13. data/lib/rails/generators/shopifydev/shops_generator.rb +11 -0
  14. data/lib/rails/generators/shopifydev/templates/shops.rake +5 -0
  15. data/lib/rails/tasks/shops.rake +7 -0
  16. data/lib/shopifydev/asset.rb +58 -0
  17. data/lib/shopifydev/commands.rb +83 -0
  18. data/lib/shopifydev/config.rb +9 -0
  19. data/lib/shopifydev/generators/shop.rb +29 -0
  20. data/lib/shopifydev/generators/templates/Gemfile +10 -0
  21. data/lib/shopifydev/generators/templates/gitignore +1 -0
  22. data/lib/shopifydev/generators/templates/rvmrc +1 -0
  23. data/lib/shopifydev/generators/templates/shopify-tmbundle +21 -0
  24. data/lib/shopifydev/pry/commands.rb +194 -0
  25. data/lib/shopifydev/railtie.rb +11 -0
  26. data/lib/shopifydev/shop.rb +38 -0
  27. data/lib/shopifydev/template.rb +73 -0
  28. data/lib/shopifydev/version.rb +3 -0
  29. data/lib/shopifydev.rb +10 -0
  30. data/shopifydev.gemspec +35 -0
  31. data/spec/shopifydev/config_spec.rb +5 -0
  32. data/spec/shopifydev/generators/shopifydev/shopifydev_generator_spec.rb +5 -0
  33. data/spec/shopifydev/pry/commands_spec.rb +5 -0
  34. data/spec/shopifydev/railtie_spec.rb +5 -0
  35. data/templates/customers/order.liquid +109 -0
  36. data/templates/customers/register.liquid +42 -0
  37. data/templates/page.support.liquid +78 -0
  38. data/templates/page.verbose.liquid +18 -0
  39. data/templates/product.liquid +284 -0
  40. data/templates/search.liquid +63 -0
  41. data/test_driver.rb +31 -0
  42. metadata +275 -0
data/.gitignore ADDED
@@ -0,0 +1,17 @@
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
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.pryrc ADDED
@@ -0,0 +1,3 @@
1
+ require 'bundler/setup'
2
+ require 'shopifydev'
3
+ require 'shopifydev/pry/commands'
@@ -0,0 +1,21 @@
1
+ test_shops:
2
+ cronin:
3
+ api_key: akey
4
+ password: aword
5
+ myshopify_domain: cronin-group3575.myshopify.com
6
+ schumm:
7
+ api_key: anotherkey
8
+ password: anotherword
9
+ myshopify_domain: schumm-durgan-and-lang94.myshopify.com
10
+
11
+ apps:
12
+ development:
13
+ meta: ~/clients/webify/metafieldeditor
14
+ ship: ~/clients/webify/shipping
15
+
16
+ heroku:
17
+ metafieldseditor: metafieldseditor
18
+ morfars-metafields: morfars-metafields
19
+ red-pepper-shipping: red-pepper-shipping
20
+ shipping-lifemap-bioreagents: shipping-lifemap-bioreagents
21
+ shipping-staging: shipping-staging
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ ruby-1.9.3-p429
@@ -0,0 +1,7 @@
1
+ # rename this to .shopifydev.yaml and don't add live secrets here
2
+ ---
3
+ api_key: youneedakey
4
+ password: andapassword
5
+ url: my_store_url.myshopify.com/
6
+ project_root: relative/path
7
+ project_root_variable: SOME_ENVIRONMENT_VARIABLE
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in shopifydev.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Michael Johnston
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/NEXTSTEPS.md ADDED
@@ -0,0 +1,33 @@
1
+ # switch command
2
+
3
+ should be some shortcuts
4
+
5
+ switch cronin
6
+
7
+ should look for shops in an app
8
+
9
+ switch with no arguments
10
+ you get a list:
11
+
12
+ test shops:
13
+ 1. cronin
14
+
15
+ apps (development):
16
+ 1. metafieldseditor
17
+ 2. shipping
18
+
19
+ apps (heroku):
20
+ 1. metafieldseditor
21
+ 2. shipping
22
+
23
+
24
+
25
+ when you choose
26
+
27
+
28
+ # To check out
29
+
30
+ https://github.com/pry/pry-coolline
31
+ https://github.com/cldwalker/bond
32
+
33
+
data/README.md ADDED
@@ -0,0 +1,78 @@
1
+ # Shopifydev
2
+
3
+ Abstract out and port to ruby the functionality of the shopify textmate bundle for use in other editors.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'shopifydev'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install shopifydev
18
+
19
+ Once Shopifydev is installed, you'll need to add a .shopifydev.yaml file to your project root. This config
20
+ file should contain the secrets specific to the shopify site you are working on. Here's a sample:
21
+
22
+ api_key: youneedakey
23
+ password: andapassword
24
+ url: my_store_url.myshopify.com
25
+ project_root: relative/path (this might just be '.' for a lot of you cats)
26
+ project_root_variable: SOME_ENVIRONMENT_VARIABLE
27
+
28
+ Don't include 'http://' in the url, and don't commit this file to your repo (because secrets). The project
29
+ root should be the directory where the 'assets' directory lives. If you would rather use an environment
30
+ variable specific to your text editor of choice, like TM_PROJECT_DIRECTORY, you can supply that as well.
31
+ Shopifydev will always prefer the environment variable, though.
32
+
33
+ ## Usage
34
+
35
+ WARNING: Files will always be uploaded from `project_root/`. This is great, because it means you can keep
36
+ the shopify files separate from whatever sweet app you happen to be working on. Unfortunately, at the
37
+ moment, this means autocompletion of file names really only works if `project_root` is `'.'`. But Imma fix
38
+ that.
39
+
40
+ With shopifydev uploading a shopify file is a snap!
41
+
42
+ $ shopifydev upload assets/some_pic.jpg
43
+
44
+ Uploading two files is also a snap!
45
+
46
+ $ shopifydev upload assets/cart.png templates/cart.liquid
47
+
48
+ More files? It's a UNIX system! You know this!
49
+
50
+ $ shopifydev upload {snippets,templates}/*.liquid
51
+
52
+ But Mr Authors, what if I don't have any files to upload?
53
+
54
+ $ shopify download
55
+
56
+ What could be better than that? How about uploading all your files:
57
+
58
+ $ shopifydev upload --patchify patch_directory
59
+
60
+ (I wouldn't recommend running that with '.' or any directory that contains subdirectories shopify wouldn't recognize. I'll fix that someday too! (^o ^)//)
61
+
62
+ Oh, you don't want to upload all your files, and you're too lazy to glob?
63
+ Use `--gitify` to upload all the shopify files with changes.
64
+
65
+ $ shopifydev upload --gitify
66
+
67
+ (this uses the output of `git status --porcelain`, and it also runs `git add` on all those files so that
68
+ you won't upload a file twice unless it gets changed twice in the same commit)
69
+
70
+ One final tip: `alias upify='shopifydev upload'`
71
+
72
+ ## Contributing
73
+
74
+ 1. Fork it
75
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
76
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
77
+ 4. Push to the branch (`git push origin my-new-feature`)
78
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+ require 'pry'
3
+ require 'shopifydev'
4
+ require 'shopifydev/pry/commands'
5
+
6
+
7
+ MY_OBJ = []
8
+
9
+ def bob
10
+ "yo, bob here"
11
+ end
12
+ # start a REPL session
13
+ binding.pry
14
+
15
+ puts "Thank you for using Shopify Console. Enjoy your day."
data/bin/shopifydev ADDED
@@ -0,0 +1,100 @@
1
+ #!/usr/bin/env ruby
2
+ require 'gli'
3
+ begin # XXX: Remove this begin/rescue before distributing your app
4
+ require 'shopifydev'
5
+ rescue LoadError
6
+ STDERR.puts "In development, you need to use `bundle exec bin/todo` to run your app"
7
+ STDERR.puts "At install-time, RubyGems will make sure lib, etc. are in the load path"
8
+ STDERR.puts "Feel free to remove this message from bin/foxhole now"
9
+ exit 64
10
+ end
11
+
12
+ include GLI::App
13
+
14
+ program_desc "Upload shopify files from the command-line like a boss."
15
+
16
+ version Shopifydev::VERSION
17
+
18
+ desc 'verbose'
19
+ switch [:v, :verbose]
20
+
21
+ desc 'Download the theme from an existing shopify site'
22
+ arg_name '' # Download take no particular args
23
+ command :download do |c|
24
+
25
+ c.action do |global_options,options,args|
26
+
27
+ Shopifydev::CommandRunner.new.download(options)
28
+
29
+ # If you have any errors, just raise them
30
+ # raise "that command made no sense"
31
+
32
+ puts "download command ran"
33
+ end
34
+ end
35
+
36
+ desc 'Upload a particular file to shopify'
37
+ arg_name 'remote key' # upload requires the remote key be specified here
38
+ command :upload do |c|
39
+
40
+ c.desc 'Upload all files from a given root'
41
+ c.default_value 'none'
42
+ c.arg_name 'patch_root'
43
+ c.flag [:p, :patchify]
44
+
45
+ c.desc 'Upload all files with changes in git'
46
+ c.default_value 'none'
47
+ c.switch [:g, :gitify]
48
+
49
+ c.action do |global_options,options,args|
50
+ gitify = options[:gitify] != 'none'
51
+ patchify = options[:patchify] != 'none'
52
+ raise "gitify and patchify are mutually exclusive" if gitify && patchify
53
+
54
+ mode = (patchify) ? 'patchify' : ''
55
+ mode = (gitify) ? 'gitify' : '' if mode.blank?
56
+
57
+ runner = Shopifydev::CommandRunner.new
58
+
59
+ case mode
60
+ when 'patchify'
61
+ puts mode
62
+ raise "patchify takes no args" if args.length > 0
63
+
64
+ runner.patchify(options[:p])
65
+ when 'gitify'
66
+ puts mode
67
+ raise "patchify takes no args" if args.length > 0
68
+
69
+ runner.gitify
70
+ else
71
+ puts mode
72
+ runner.upload(args)
73
+ end
74
+
75
+ puts "upload command ran"
76
+ end
77
+ end
78
+
79
+ pre do |global,command,options,args|
80
+ # Pre logic here
81
+ # Return true to proceed; false to abourt and not call the
82
+ # chosen command
83
+ # Use skips_pre before a command to skip this block
84
+ # on that command only
85
+ true
86
+ end
87
+
88
+ post do |global,command,options,args|
89
+ # Post logic here
90
+ # Use skips_post before a command to skip this
91
+ # block on that command only
92
+ end
93
+
94
+ on_error do |exception|
95
+ # Error logic here
96
+ # return false to skip default error handling
97
+ true
98
+ end
99
+
100
+ exit run(ARGV)
@@ -0,0 +1,11 @@
1
+ require 'rails/generators/base'
2
+
3
+ module Shopifydev
4
+ class ShopsGenerator < Rails::Generators::Base
5
+ source_root File.expand_path('../templates', __FILE__)
6
+
7
+ def rake_task
8
+ copy_file "shops.rake", "lib/tasks/shops.rake"
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,5 @@
1
+ desc "Outputs list of shops that have installed the app"
2
+ task :shops => :environment do
3
+ url_column = Shop.column_names.detect{|c| c =~ /url|domain/}
4
+ puts Shop.select("id,#{url_column},token").all.to_json
5
+ end
@@ -0,0 +1,7 @@
1
+ desc "Outputs list of shops that have installed the app"
2
+ task :shops => :environment do
3
+ url_column = Shop.column_names.detect{|c| c =~ /url|domain/}
4
+ json = Shop.select("id,#{url_column},token").all.to_json
5
+ puts "----snip----"
6
+ puts json
7
+ end
@@ -0,0 +1,58 @@
1
+ require 'shopify_api'
2
+ require 'filemagic'
3
+
4
+ module Shopifydev
5
+ class Asset
6
+ attr_accessor :shop, :remote_key
7
+
8
+ def initialize(shop, path=ENV['TM_FILEPATH'], project_root)
9
+ puts "in asset::initialize"
10
+ @shop = shop
11
+
12
+ # Asset name should be relative to TM_PROJECT_DIRECTORY
13
+ # but if it isn't, then gsub just doesn't replace anything
14
+ # so if you know the key, you can just supply the key?
15
+ unless project_root.nil?
16
+ @remote_key = path.gsub(project_root + '/', '') # fix absolute path
17
+ @local_path = Pathname.new(project_root + '/' + @remote_key) # prepend project root
18
+ else
19
+ raise Exception, "could no determine project_root. In .shopifydev.yaml include\n project_root: relative/path"
20
+ end
21
+ end
22
+
23
+ def upload(root=nil)
24
+ # check that it's not binary
25
+ puts "in upload"
26
+
27
+ puts "creating asset for " + @remote_key
28
+ puts @remote_key
29
+ asset = ShopifyAPI::Asset.new(:key => @remote_key)
30
+
31
+ puts "filling with 1's and 0's from " + @local_path.to_path
32
+
33
+ contents = File.read(@local_path.to_path)
34
+
35
+ fm = FileMagic.new
36
+
37
+ if (fm.file(@local_path.realpath.to_path).include?('image'))
38
+ asset.attach contents
39
+ else
40
+ asset.value = contents
41
+ end
42
+
43
+ # TODO this doesn't fail spectacularly enough... I don't
44
+ # feel comfortable with that
45
+ puts "saving..."
46
+ if asset.valid?
47
+ if asset.save
48
+ puts "Success!"
49
+ else
50
+ puts "failed to save"
51
+ end
52
+ else
53
+ puts "failed to validate"
54
+ end
55
+ puts "---"
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,83 @@
1
+
2
+ require "logger"
3
+ require "shopify_api"
4
+
5
+ module Shopifydev
6
+ class CommandRunner
7
+
8
+ def initialize
9
+ @devshop = Shopifydev::Shop.new(credentials)
10
+ end
11
+
12
+ def credentials
13
+ unless @credentials
14
+ @credentials = YAML::load(
15
+ File.open('.shopifydev.yaml'))
16
+ end
17
+
18
+ @credentials
19
+ end
20
+
21
+ def upload(remote_keys)
22
+ # upload one asset or directory
23
+ raise "no shopify files were specified" if remote_keys.empty?
24
+
25
+ remote_keys.each do |remote_key|
26
+ if File.directory?(remote_key) then
27
+ self.upload_dir(remote_key)
28
+ else
29
+ @devshop.asset(remote_key).upload
30
+ end
31
+ end
32
+ end
33
+
34
+ def patchify(patch_dir)
35
+
36
+ ENV['PATCHIFY_ROOT'] = patch_dir # temporarily set an environment variable
37
+
38
+ Dir.glob(File.join(ENV['PATCHIFY_ROOT'], "*/*")).reverse.each do |file|
39
+
40
+ self.upload(Array.wrap(File.join(file.split('/')[-2..-1])))
41
+ end
42
+ end
43
+
44
+ def gitify
45
+ porcelain = `git status --porcelain`
46
+
47
+ modified = porcelain.scan(/^[ AM][M](.*)/).flatten.each {|f| f.strip!}
48
+
49
+ remote_keys = modified.delete_if do |file|
50
+ not ["assets", "snippets", "templates", "layout"].include?(file.split('/')[0].strip)
51
+ end
52
+
53
+ remote_keys.each do |file|
54
+ `git add #{file}`
55
+ end
56
+
57
+ upload(remote_keys)
58
+ end
59
+
60
+ def upload_dir(upload_dir)
61
+ # upload all assets in the given dir
62
+
63
+ Dir[upload_dir + "/*"].each do |remote_key|
64
+ self.upload(remote_key)
65
+ end
66
+ end
67
+
68
+ def upload_glob(glob)
69
+ # upload all assets in the given dir matching a given pattern
70
+
71
+ glob.each do |remote_key|
72
+ self.upload(remote_key)
73
+ end
74
+ end
75
+
76
+ def download(options={})
77
+ # Download the whole template
78
+
79
+ @devshop.template.download
80
+ end
81
+
82
+ end
83
+ end
@@ -0,0 +1,9 @@
1
+ require 'active_support/core_ext/hash'
2
+
3
+ module Shopifydev
4
+ module Config
5
+ def self.config
6
+ YAML::load(File.open(File.expand_path('~/.shopifydev.yaml'))).with_indifferent_access
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,29 @@
1
+ module Shopifydev
2
+ module Generators
3
+ class Shop < Thor::Group
4
+ include Thor::Actions
5
+
6
+ source_root File.expand_path('../templates', __FILE__)
7
+
8
+ argument :name
9
+ class_option :test_shop
10
+ class_option :live_shop
11
+
12
+ def setup
13
+ create_file "#{name}/TODO"
14
+ copy_file "Gemfile", "#{name}/Gemfile"
15
+ copy_file "rvmrc", "#{name}/.rvmrc"
16
+ copy_file "gitignore", "#{name}/.gitignore"
17
+ copy_file "shopify-tmbundle", "#{name}/.shopify-tmbundle"
18
+ system "git init"
19
+ system "git add --all"
20
+ system 'git commit -m "initial setup"'
21
+ end
22
+
23
+ def download_template
24
+ say "TODO: automate downloading template from test shop"
25
+ end
26
+
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,10 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem "mechanize"
4
+ gem 'watchr'
5
+ gem 'thor'
6
+ gem 'shopify_api'
7
+ gem "shopify-api-limits"
8
+ gem 'guard'
9
+ gem 'activesupport'
10
+ gem 'inifile'
@@ -0,0 +1 @@
1
+ .shopify-tmbundle
@@ -0,0 +1 @@
1
+ rvm use ruby-1.9.3-p194@shopify
@@ -0,0 +1,21 @@
1
+ ; config file for shopify.tmbundle
2
+ ; You can now setup multiple shops. Just follow the pattern you see below.
3
+ ; You can have more than 2 (as many as you want really)
4
+ ; this config uses ini style http://php.net/manual/en/function.parse-ini-file.php
5
+ ; you can just change the settings under default, and everything should work.
6
+ ; or you can do things the old way as well.
7
+
8
+ ; this is the currently active shop. you can change it here
9
+ use="default"
10
+
11
+ ; test shop for development
12
+ [default]
13
+ api_key="###TEST_SHOP_API_KEY###"
14
+ password="###TEST_SHOP_PASSWORD###"
15
+ store="TEST_SHOP_DOMAIN"
16
+
17
+ ; and the live shop
18
+ [live]
19
+ api_key="###LIVE_SHOP_API_KEY###"
20
+ password="###LIVE_SHOP_PASSWORD###"
21
+ store="###LIVE_SHOP_DOMAIN###"