shopifydev 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/NEXTSTEPS.md CHANGED
@@ -1,26 +1,45 @@
1
1
  # switch command
2
2
 
3
- should be some shortcuts
3
+ Z(2013.06.06):
4
+ M, I think you should work on memoizing the shop array and the 'refresh'
5
+ command. That lag is killing me.
4
6
 
5
- switch cronin
7
+ You should take a look at switch.handle_choices and switch.handle_by_shop_type
8
+ I realized that the object we are calling @cfg is either:
9
+ a string, in which case we should keep going
10
+ a result object, in which case we should switch shops
6
11
 
7
- should look for shops in an app
12
+ So, in handle_choice we determine whether we present a new menu, or go
13
+ ahead and update the current shop
8
14
 
9
- switch with no arguments
10
- you get a list:
15
+ The result object gets a key "shop_type" that lets us know how to deal
16
+ with it. The behaviour for test_shop is already there, but if you could
17
+ implement the behaviour for local, I would be happy
11
18
 
12
- test shops:
13
- 1. cronin
19
+ I wrote a bunch of comments around the commands.rb file, too, so feel free
20
+ to read those
14
21
 
15
- apps (development):
16
- 1. metafieldseditor
17
- 2. shipping
22
+ M: should be some shortcuts
18
23
 
19
- apps (heroku):
20
- 1. metafieldseditor
21
- 2. shipping
24
+ switch cronin
22
25
 
23
- _pry_.switch
26
+ should look for shops in an app
27
+
28
+ switch with no arguments
29
+ you get a list:
30
+
31
+ test shops:
32
+ 1. cronin
33
+
34
+ apps (development):
35
+ 1. metafieldseditor
36
+ 2. shipping
37
+
38
+ apps (heroku):
39
+ 1. metafieldseditor
40
+ 2. shipping
41
+
42
+ Z: _pry_.switch
24
43
  Switch is a class, and every instance of Pry has an instance of Switch. This way we can
25
44
  access _pry_.switch. In the global scope there will be an object called 'switch' that will
26
45
  be an alias to _pry_.switch so that we can call its public methods. There will also be a
@@ -39,11 +58,11 @@ _pry_.switch
39
58
 
40
59
  Or we can use tab completion to present the menu by invoking switch as a global object.
41
60
 
42
- ````
61
+ ````
43
62
  [1] pry(main)> switch.m[TAB]
44
63
  switch.metafieldseditor switch.morfars-metafields
45
64
  [2] pry(main)> switch.mo[TAB]rfars-metafields
46
- ````
65
+ ````
47
66
 
48
67
  to accomplish the same.
49
68
 
@@ -52,7 +71,7 @@ _pry_.switch
52
71
 
53
72
  So in a deep menu we might see:
54
73
 
55
- ````
74
+ ````
56
75
  [1] pry(main)> switch
57
76
  current shop: none
58
77
 
@@ -79,7 +98,7 @@ _pry_.switch
79
98
  2. the thing you wanted
80
99
  [1] pry(main)> switch 2
81
100
  current shop: none switching to "the thing you wanted"...
82
- ````
101
+ ````
83
102
 
84
103
  # To check out
85
104
 
@@ -89,8 +108,8 @@ https://github.com/cldwalker/bond
89
108
 
90
109
  # Menu of Shops in local apps
91
110
  - [x] run rake shops in chosen local app
92
- - [ ] display result of rake shops in a menu
93
- - how do we handle this? do we use letters? or does switch command remember state (which menu was displayed last)? ie, what does ```switch 1``` mean?
111
+ - [x] display result of rake shops in a menu
112
+ - [x] how do we handle this? do we use letters? or does switch command remember state (which menu was displayed last)? ie, what does ```switch 1``` mean?
94
113
  - [ ] memoize results of rake shops in a hash with same keys as the apps have in config (I would put this in config). This is because running rake shops is slow enough to be annoying.
95
114
  - [ ] add -r,--refresh option to switch command to tell it to get fresh data
96
115
  - [ ] deploy apps with shopify_dev gem
@@ -102,6 +121,5 @@ https://github.com/cldwalker/bond
102
121
 
103
122
 
104
123
  # Using pry features
105
- https://github.com/ConradIrwin/pry-rescue
106
- -- we **really** want to be using this in test/development environments in rails apps.
124
+ https://github.com/ConradIrwin/pry-rescue -- we **really** want to be using this in test/development environments in rails apps.
107
125
  https://github.com/envygeeks/pry-vterm_aliases
@@ -1,4 +1,5 @@
1
1
  require 'shopifydev/pry/commands'
2
+ require 'shopifydev/pry/save_json'
2
3
  require 'shopifydev/shopify_api/caches'
3
4
 
4
5
  require 'term/ansicolor'
@@ -13,3 +14,5 @@ class Color
13
14
  end
14
15
  end
15
16
  end
17
+
18
+ Pry.config.hooks.add_hook(:before_session, :set_context) { |_, _, pry| pry.input = StringIO.new("cd ShopifyAPI") }
@@ -1,11 +1,179 @@
1
+ # encoding: UTF-8
1
2
  require 'oj'
2
3
 
3
- class LocalShopifyApp
4
+ class Switch
5
+ def initialize
6
+ @current_shop = ''
7
+ @menu = default_menu
8
+ end
9
+
10
+ def current_shop
11
+ @current_shop = ShopifyAPI::Base.site || 'none'
12
+ Color.green{ "current shop:"} + " #{@current_shop}"
13
+ end
14
+
15
+ def reset
16
+ @menu = default_menu
17
+ end
18
+
19
+ def menu
20
+ @menu
21
+ end
22
+
23
+ def pick(ix)
24
+ result = ''
25
+
26
+ # TODO we need need need to rename cfg, as it is currently confusing
27
+ @breadcrumbs, @cfg = pick_config(ix)
28
+
29
+ if @breadcrumbs == :no_such_config
30
+ result << Color.red{ "I don't know about #{ix}\n" }
31
+ result << self.menu.print
32
+ else
33
+ # update the menu based on the choice
34
+ # if we've reached a terminal menu, then do something
35
+ # otherwise just present the next menu
36
+ result << handle_choice
37
+ end
38
+ end
39
+
40
+ private
41
+
42
+ def set_shop(key, password, domain)
43
+ @current_shop = domain
44
+ ShopifyAPI::Base.site = "https://#{key}:#{password}@#{domain}/admin/"
45
+ @current_shop
46
+ end
47
+
48
+ def pick_config(ix)
49
+ # this gives us the menu item
50
+ path = self.menu.pick(ix)
51
+ return :no_such_config if path.nil?
52
+ result = shopify_config
53
+
54
+ path.each do |x|
55
+ result = result[x]
56
+ end
57
+
58
+ [path, result]
59
+ end
60
+
61
+ # if we chose a test shop cfg is a hash of key, password, and domain
62
+ # if we chose a local shop, it is a path
63
+ # path is the path through the yaml file
64
+ def handle_choice
65
+ result = ''
66
+
67
+ case @cfg.class.to_s
68
+ when "String" then
69
+ case @breadcrumbs[1].to_sym
70
+ when :development then menu_method = self.method(:development_menu)
71
+ when :heroku then menu_method = self.method(:heroku_menu)
72
+ else menu_method = self.method(:missing_menu)
73
+ end
74
+ else result = handle_by_shop_type
75
+ end
76
+
77
+ if menu_method
78
+ result << "you picked #{@breadcrumbs.join('.')}\n"
79
+ result << @cfg.inspect + "\n"
80
+ result << Color.yellow { menu_method.call.print }
81
+ end
82
+ result
83
+ end
84
+
85
+ def handle_by_shop_type
86
+ if @cfg.keys.include?("shop_type")
87
+ result = case @cfg["shop_type"].to_sym
88
+ when :local then "local"
89
+ when :heroku then "heroku"
90
+ else "something else"
91
+ end
92
+ else
93
+ set_shop(@cfg[:api_key], @cfg[:password], @cfg[:myshopify_domain])
94
+ result = self.current_shop
95
+ end
96
+
97
+ result
98
+ end
99
+
100
+ def default_menu
101
+ @menu = ConfigMenu.new(Shopifydev::Config.config, :default).build
102
+ end
103
+
104
+ # TODO this needs to be renamed:
105
+ # It is the contents of .shopifydev.yaml, but it is also
106
+ # more than that, since it gets updated throughout the life
107
+ # of a switch object.
108
+ def shopify_config
109
+ @shopify_config ||= Shopifydev::Config.config
110
+ end
111
+
112
+ # TODO this method is pretty obscure
113
+ def development_menu
114
+ # this needs to be memoized
115
+ app = LocalShopifyApp.new(@cfg)
116
+ shops = app.shops
117
+
118
+ # add the shop_type to the array of shops
119
+ shops.each do |shop|
120
+ shop["shop_type"] = "local"
121
+ end
122
+
123
+ key = ''
124
+ domain = @cfg # at this point we know @cfg is a path on the local machine
125
+
126
+ # iterate over shopifydev.yaml and replace the local file path matching
127
+ # domain with the list of shops associated with that domain
128
+ # TODO drop M's terrible habbit of using k and v for key and value
129
+ shopify_config["apps"]["development"].each do |k, v|
130
+ if v == domain
131
+ shopify_config["apps"]["development"][k] = shops
132
+ key = k
133
+ break
134
+ end
135
+ end
136
+
137
+ # the menu relevant yaml needs to be [key, array]
138
+ @menu = ConfigMenu.new([key, shopify_config["apps"]["development"][key]], :development).build
139
+ end
140
+
141
+ def heroku_menu
142
+ app = HerokuShopifyApp.new(@cfg)
143
+ shops = app.shops
144
+ @menu = ConfigMenu.new(shops, :heroku).build
145
+ end
146
+
147
+ def missing_menu
148
+ @menu = ConfigMenu.new(shops, :missing).build
149
+ end
150
+ end
151
+
152
+ class Pry
153
+ attr_accessor :switch
154
+
155
+ def switch
156
+ @switch ||= Switch.new
157
+ end
158
+ end
159
+
160
+ # these mini classes JUST grabs the JSON that we need for making submenus
161
+ class ShopifyAppShopList
4
162
  attr_accessor :path
163
+
5
164
  def initialize(path)
6
165
  @path = path
7
166
  end
8
167
 
168
+ def shops
169
+ raise "you must define the shops method"
170
+ end
171
+ end
172
+
173
+ class HerokuShopifyApp < ShopifyAppShopList
174
+ end
175
+
176
+ class LocalShopifyApp < ShopifyAppShopList
9
177
  def shops
10
178
  json = `/bin/bash -l -c "unset BUNDLE_GEMFILE; cd #{path} 2> /dev/null; bundle exec rake shops 2>/dev/null"`
11
179
  json = json.split("----snip----\n").last
@@ -15,65 +183,94 @@ class LocalShopifyApp
15
183
  end
16
184
 
17
185
  class ConfigMenu
18
- attr_accessor :cfg
186
+ attr_accessor :json
19
187
 
20
- def initialize(cfg)
21
- @cfg = cfg
22
- @menu_choices = [:do_nothing]
23
- @menu_display = []
188
+ def initialize(json, style=:default)
189
+ @json = json
190
+ @style = style
191
+ @choices = [:do_nothing]
192
+ @lines = []
24
193
  end
25
194
 
26
195
  def build
196
+ case @style
197
+ when :development then build_development
198
+ when :default then build_default
199
+ when :heroku then build_heroku
200
+ else build_missing
201
+ end
202
+ end
203
+
204
+ def print(output=nil)
205
+ if output.nil?
206
+ @lines.join("\n")
207
+ else
208
+ output.puts @lines.join("\n")
209
+ end
210
+ end
211
+
212
+ def pick(ix)
213
+ if ix >= @choices.length
214
+ nil
215
+ else
216
+ @choices[ix]
217
+ end
218
+ end
219
+
220
+ private
221
+
222
+ # instead of having infinite build_something methods, maybe we should have
223
+ # a way of passing in blocks, or something?
224
+ def build_default
27
225
  header("Test Shops")
28
- cfg[:test_shops].keys.each do |k|
226
+ json[:test_shops].keys.each do |k|
29
227
  choice([:test_shops, k], k)
30
228
  end
31
-
229
+
32
230
  header("Local Apps")
33
- cfg[:apps][:development].each do |k, path|
231
+ json[:apps][:development].each do |k, path|
34
232
  choice([:apps, :development, k], path)
35
233
  end
36
234
 
37
235
  header("Heroku Apps")
38
- cfg[:apps][:heroku].each do |k, name|
236
+ json[:apps][:heroku].each do |k, name|
39
237
  choice([:apps, :heroku, k], name)
40
238
  end
41
239
 
42
240
  self
43
241
  end
44
242
 
45
- def print(output)
46
- output.puts @menu_display.join("\n")
47
- end
243
+ def build_development
244
+ header("Development Shops")
48
245
 
49
- def header(label)
50
- @menu_display << ''
51
- @menu_display << Color.blue { label }
246
+ name = json.first
247
+ json.last.each_with_index do |h, index|
248
+ choice([:apps, :development, name, index], h["url"])
249
+ end
250
+
251
+ self
52
252
  end
53
253
 
54
- def choice(path, value)
55
- ix = @menu_choices.length
56
- @menu_display << Color.yellow{ ix.to_s } + '. ' + value.to_s
57
- @menu_choices[ix] = path
254
+ def build_missing
255
+ warn("AND I DON'T EVEN KNOW!")
256
+ self
58
257
  end
59
258
 
60
- def pick(ix)
61
- if ix >= @menu_choices.length
62
- nil
63
- else
64
- @menu_choices[ix]
65
- end
259
+ # TODO I think these three related methods could be moved into a module called "Writer" or something
260
+ def header(label)
261
+ @lines << ''
262
+ @lines << Color.blue { label }
66
263
  end
67
264
 
68
- def pick_config(ix)
69
- path = pick(ix)
70
- return :no_such_config if path.nil?
71
- result = cfg
72
- path.each do |x|
73
- result = result[x]
74
- end
265
+ def warn(label)
266
+ @lines << ''
267
+ @lines << Color.red { label }
268
+ end
75
269
 
76
- [path, result]
270
+ def choice(path, value)
271
+ ix = @choices.length
272
+ @lines << Color.yellow{ ix.to_s } + '. ' + value.to_s
273
+ @choices[ix] = path
77
274
  end
78
275
  end
79
276
 
@@ -81,99 +278,48 @@ shopifydev_command_set = Pry::CommandSet.new do
81
278
  create_command "switch" do
82
279
  description "switch shops"
83
280
 
84
-
85
281
  # opt is a Slop object, see https://github.com/injekt/slop/blob/master/README.md
86
282
  def options(opt)
87
283
  end
88
284
 
89
285
  def process
90
- print_current_shop
91
-
92
- config_menu = ConfigMenu.new(Shopifydev::Config.config).build
286
+ output.puts _pry_.switch.current_shop
93
287
 
94
288
  case true
95
289
  when args.empty?
96
- config_menu.print(output)
290
+ _pry_.switch.reset # reset to the first menu page
291
+ output.puts _pry_.switch.menu.print
292
+ print "ima ask for input:"
293
+ choice = $stdin.gets
294
+ puts "you chose #{choice}"
97
295
  when (args.length == 1)
98
296
  ix = args.first.to_i
99
- path, cfg = config_menu.pick_config(ix)
100
- if path == :no_such_config
101
- output.puts Color.red{ "I don't know about #{ix}" }
102
- config_menu.print(output)
103
- else
104
- handle_choice(path, cfg)
105
- end
106
- end
107
- end
108
-
109
- def print_current_shop
110
- current_shop = ShopifyAPI::Base.site || 'none'
111
- output.puts Color.green{ "current shop:"} + " #{current_shop}"
112
- end
113
-
114
- def handle_choice(path, cfg)
115
- case path.first.to_sym
116
- when :test_shops
117
- url = "https://#{cfg[:api_key]}:#{cfg[:password]}@#{cfg[:myshopify_domain]}/admin/"
118
- ShopifyAPI::Base.site = url
119
- print_current_shop
120
- when :apps
121
- case path[1].to_sym
122
- when :development
123
- output.puts "you picked #{path.join('.')}"
124
- output.puts cfg.inspect
125
- app = LocalShopifyApp.new(cfg)
126
- output.puts Color.yellow{ app.shops.inspect }
127
- when :heroku
128
- output.puts "you picked #{path.join('.')}"
129
- output.puts cfg.inspect
130
-
131
- output.puts Color.yellow{ "but it's not ready yet!"}
132
- else
133
- output.puts "you picked #{path.join('.')}"
134
- output.puts cfg.inspect
135
- output.puts Color.red{ "AND I DON'T EVEN KNOW!"}
136
- end
137
- else
138
- output.puts "you picked #{path.join('.')}"
139
- output.puts cfg.inspect
140
- output.puts Color.red{ "AND I DON'T EVEN KNOW!"}
297
+ output.puts _pry_.switch.pick(ix)
141
298
  end
142
299
  end
300
+ end
143
301
 
144
-
145
- def output_menu_choices(arr, ix=1)
146
- my_ix = 0
147
- arr.each do |item|
148
- output.puts menu_choice(ix+my_ix, item.to_s)
149
- my_ix +=1
302
+ create_command "arlog", "Turn ActiveResource logging on/off" do
303
+ def process
304
+ case args.first
305
+ when 'off'
306
+ puts Color.black{"ActiveResource logging "} + Color.red{'off'}
307
+ ActiveResource::Base.logger = nil
308
+ else
309
+ puts Color.black{"ActiveResource logging "} + Color.yellow{'on'}
310
+ ActiveResource::Base.logger = Logger.new STDOUT
150
311
  end
151
- my_ix
152
312
  end
313
+ end
153
314
 
154
- def menu_choice(ix, s)
155
- Color.yellow{ ix.to_s } + '. ' + s.to_s
156
- end
157
-
158
- def menu_header(s)
159
- Color.blue { s }
160
- end
161
-
162
- def write_menu(cfg)
163
- ix = 1
164
- # output.puts "Test Shops"
165
- output.puts menu_header("Test Shops")
166
- ix += output_menu_choices(cfg[:test_shops].keys.sort, ix)
167
-
168
- output.puts
169
- output.puts menu_header("Local Apps")
170
- ix += output_menu_choices(cfg[:apps][:development].keys.sort, ix)
315
+ block_command "tree", "display directory using unix 'tree'" do |path|
316
+ dir ||= Pathname.getwd
317
+ dir = Pathname.new(dir) unless dir.is_a?(Pathname)
318
+ puts Color.blue{ "listing #{dir}..."}
319
+ puts `cd #{dir.expand_path.to_s}; tree`.gsub(%r{(^[^\w]+)}, Color.black{'\1'})
171
320
 
172
- output.puts
173
- output.puts menu_header("Heroku Apps")
174
- ix += output_menu_choices(cfg[:apps][:heroku].keys.sort, ix)
175
- end
176
321
  end
322
+
177
323
  end
178
324
 
179
325
  Pry::Commands.import shopifydev_command_set
@@ -0,0 +1,78 @@
1
+ module Kernel
2
+ def save_json(obj, path=nil)
3
+ json = Oj.dump(obj, object:true, circular:true)
4
+ path = UnixTree.get_path(path, require: :file, new: true)
5
+ if path
6
+ puts Color.green{"writing json to #{path.to_s}..."}
7
+ File.open(path, 'w'){|f| f.write(json)}
8
+ true
9
+ else
10
+ false
11
+ end
12
+ end
13
+
14
+ def load_json(path=nil)
15
+ path = UnixTree.get_path(path, require: :file)
16
+ if path
17
+ puts Color.green{"loading json from #{path.to_s}..."}
18
+ Oj.load(path)
19
+ else
20
+ nil
21
+ end
22
+ end
23
+
24
+ end
25
+
26
+ module UnixTree
27
+ class << self
28
+ def get_path(path, opts={})
29
+ path = Pathname.new(path) unless path.nil?
30
+ while path.nil? || !viable_path(path, opts) do
31
+ missing = nil
32
+ path.expand_path.descend{|p| unless p.exist?; missing = p; break; end} if path
33
+ if missing
34
+ what = (missing == path) ? opts[:require].to_s : 'directory'
35
+ puts Color.red{ "couldn't find #{what} #{missing.to_s}" }
36
+ missing = missing.dirname
37
+ print_tree missing
38
+
39
+ end
40
+ print Color.yellow{ "enter path: "}
41
+ in_path = $stdin.gets.chomp
42
+ return nil if in_path == 'q'
43
+ unless in_path.blank?
44
+ in_path = Pathname(in_path)
45
+ path = missing if missing
46
+ path ||= Pathname.getwd
47
+ path = in_path.relative? ? path.join(in_path) : in_path
48
+ end
49
+ end
50
+ path.expand_path
51
+ end
52
+
53
+ def viable_path(path, opts={})
54
+ path = Pathname(path) unless path.is_a?(Pathname)
55
+ if opts[:new]
56
+ return false unless path.dirname.expand_path.exist?
57
+ else
58
+ return false unless path.expand_path.exist?
59
+ end
60
+ case opts[:require]
61
+ when :file
62
+ opts[:new] ? !(path.exist? && path.directory?) : path.expand_path.file?
63
+ when :directory
64
+ opts[:new] ? !path.exist? : path.expand_path.directory?
65
+ else
66
+ true
67
+ end
68
+ end
69
+
70
+ def print_tree(path=nil)
71
+ path ||= Pathname.getwd
72
+ path = Pathname.new(path) unless path.is_a?(Pathname)
73
+ path = path.dirname if path.file?
74
+ puts Color.blue{ "listing #{path}..."}
75
+ puts `cd #{path.expand_path.to_s}; tree`.gsub(%r{(^[^\w]+)}, Color.black{'\1'})
76
+ end
77
+ end
78
+ end
@@ -1,5 +1,3 @@
1
- puts "yo, included"
2
-
3
1
  module Shopifydev
4
2
  module ShopifyAPI
5
3
  module DirtyCache
@@ -1,3 +1,3 @@
1
1
  module Shopifydev
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shopifydev
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -222,6 +222,7 @@ files:
222
222
  - lib/shopifydev/generators/templates/rvmrc
223
223
  - lib/shopifydev/generators/templates/shopify-tmbundle
224
224
  - lib/shopifydev/pry/commands.rb
225
+ - lib/shopifydev/pry/save_json.rb
225
226
  - lib/shopifydev/railtie.rb
226
227
  - lib/shopifydev/shop.rb
227
228
  - lib/shopifydev/shopify_api/caches.rb
@@ -249,7 +250,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
249
250
  version: '0'
250
251
  segments:
251
252
  - 0
252
- hash: -20439056481340104
253
+ hash: 3714550711815646135
253
254
  required_rubygems_version: !ruby/object:Gem::Requirement
254
255
  none: false
255
256
  requirements:
@@ -258,7 +259,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
258
259
  version: '0'
259
260
  segments:
260
261
  - 0
261
- hash: -20439056481340104
262
+ hash: 3714550711815646135
262
263
  requirements: []
263
264
  rubyforge_project:
264
265
  rubygems_version: 1.8.25