Class: Ptero::Application

Inherits:
Object
  • Object
show all
Defined in:
lib/ptero/application.rb

Overview

Each instance of this class represents a Ptero application. Within its directory, this class is used to test the presence of PHP, download the composer.phar file, install composer dependencies, and use Generators to automatically create new files and components in the application.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(dir = Dir.pwd) ⇒ Application

Input a directory String or Pathname to make a new Application from that path. (Defaults to Dir.pwd)

Parameters:

  • dir (Pathname, String) (defaults to: Dir.pwd)

    the Application directory



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/ptero/application.rb', line 20

def initialize(dir=Dir.pwd)
  @dir = Pathname.new(dir)
  
  @name = ''
  
  composer_path = @dir.join('composer.json')
  if File.exist? composer_path
    
    hash = JSON.parse File.read(composer_path)
    
    if hash['dinosaur'] && hash['dinosaur']['root'].eql?(true) && hash['dinosaur']['name']
      @name = hash['dinosaur']['name']
    end
    
    
  end
  
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method_name, *params) ⇒ Object

If the method name is of the type “generate_NAME(*params)”, such as generate_javascript(‘contact’,‘Display contact information’), call self.generate(NAME,*params), so self.generate(‘javascript’,‘contact’,‘Display contact information’)



245
246
247
248
249
250
251
252
# File 'lib/ptero/application.rb', line 245

def method_missing(method_name,*params)
  match = method_name.to_s.match /^generate_(\w+)$/
  super unless match
  type = match[1]
  generate(type, *params)
rescue NameError => e # Couldn't load the proper constant
  super
end

Instance Attribute Details

#dirObject (readonly)

Returns the value of attribute dir.



39
40
41
# File 'lib/ptero/application.rb', line 39

def dir
  @dir
end

#nameObject (readonly)

Returns the value of attribute name.



39
40
41
# File 'lib/ptero/application.rb', line 39

def name
  @name
end

Class Method Details

.app_for(dir = Dir.pwd) ⇒ Application

Return the first verified application in the specified directory or its parents

Parameters:

  • dir (String, Pathname) (defaults to: Dir.pwd)

    the starting directory

Returns:

Raises:



313
314
315
316
317
318
319
320
321
# File 'lib/ptero/application.rb', line 313

def app_for(dir=Dir.pwd)
  path = Pathname.new dir
  path.ascend do |level|
    app = new(level)
    return app if app.verify
  end
  
  raise Ptero::Exception::ApplicationException, "Couldn't find composer.json with dinosaur information in #{dir} or parent directories"
end

.create(name, dir = Pathname.new(Dir.pwd)) ⇒ Application

Create a new application with basic files and Composer dependencies. Yield the newly-created Application object to a block if one is given.

Parameters:

  • name (String)

    the name of the new application

  • dir (String, Pathname) (defaults to: Pathname.new(Dir.pwd))

    the directory in which to create the new application

Returns:



275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
# File 'lib/ptero/application.rb', line 275

def create(name,dir=Pathname.new(Dir.pwd))
  
  name = "#{name[0].upcase}#{name[1,name.length-1]}"
  
  Dir.chdir dir do
    raise Ptero::Exception::ApplicationException, "Cannot create project \"#{name}\" because a file already exists with that name" if File.exist? name.downcase 
  
    puts "Creating directory #{name.downcase} in #{Dir.pwd}"
    Dir.mkdir(name.downcase)
    Dir.chdir(name.downcase) do
      
      puts "Loading default composer.json"
      composer = JSON.parse( File.read("#{__dir__}/composer_default.json") )
      composer[:dinosaur] = {
        name: name,
        root: true
      }
    
      puts "Writing project composer.json"
      File.open('composer.json','w') do |file|
        file.puts JSON.pretty_generate(composer)
      end
    
      puts "Initializing app"
      app = app_for(Dir.pwd)
    
      yield app if block_given?
    
      return app
    
    end
  end
  
end

.current_appApplication

Return the verified Application object corresponding to Dir.pwd or its parent directories

Returns:

  • (Application)

    the Application object that represents the found verified application



327
328
329
# File 'lib/ptero/application.rb', line 327

def current_app
  app_for Dir.pwd
end

Instance Method Details

#dependencies_installed?Boolean

Returns:

  • (Boolean)


173
174
175
# File 'lib/ptero/application.rb', line 173

def dependencies_installed?
  @dir.join('vendor').directory?
end

#destroyObject

Remove the directory of this application



255
256
257
258
# File 'lib/ptero/application.rb', line 255

def destroy
  FileUtils.rm_r dir
  nil
end

#generate(klass, *params) ⇒ Object

Generate a file using the given arguments

Parameters:

  • klass (String, Class)

    what type of file to generate

  • *params

    all other parameters to pass to the generator



180
181
182
183
184
185
# File 'lib/ptero/application.rb', line 180

def generate(klass,*params)
  klass = generator_for_name(klass) if klass.is_a? String # if klass is a string, make sure it's a class
  generator = klass.new(*params)
  generator.generate
  self
end

#generated?(klass, *params) ⇒ Boolean

Returns:

  • (Boolean)


187
188
189
190
191
# File 'lib/ptero/application.rb', line 187

def generated?(klass,*params)
  klass = generator_for_name(klass) if klass.is_a? String
  generator = klass.new(*params)
  generator.generated?
end

#get_composerApplication, Boolean

Download the composer.phar file into the Application directory using the command ‘curl -sS getcomposer.org/installer | php’ as prescribed on the Composer website

Returns:

Raises:



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/ptero/application.rb', line 63

def get_composer
  raise Ptero::Exception::ApplicationException, "Application \"#{self.name}\" already has composer.phar file" if has_composer?
  Dir.chdir @dir do
    # Download code from the composer website
    # https://getcomposer.org
    command = "php -r \"readfile('https://getcomposer.org/installer');\" | php"
    Open3.popen2(command,{:err => [:child, :out]}) do |stdin,stdout,wait_thr|
      print 'Downloading composer'
      output = ''
      stdout.each_line do |line|
        output << line
        print '.'
      end
      exit_status = wait_thr.value
      
      puts
      
      unless exit_status.success?
        raise Ptero::Exception::ApplicationException, "Could not install Composer in Application \"#{self.name}\" with command `#{command}`. Output was: \"#{output.chomp}\"" 
      end
      
      puts 'Done!'
    end
  end
  self
end

#has_composer?Boolean

Find out if this Application has the composer.phar file.

Returns:

  • (Boolean)

    whether or not composer.phar was found



100
101
102
103
104
# File 'lib/ptero/application.rb', line 100

def has_composer?
  Dir.chdir @dir do
    File.exist? 'composer.phar'
  end
end

#install_dependenciesApplication

Install all dependencies listed in the composer.json file using Composer ‘php composer.phar install’

Returns:

Raises:



109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# File 'lib/ptero/application.rb', line 109

def install_dependencies
  raise Ptero::Exception::ApplicationException, "Not a dinosaur root: #{Dir.pwd}" unless verify
  raise Ptero::Exception::ApplicationException, "PHP command-line tool failed, update your version of PHP" unless test_php
  get_composer unless has_composer?
  Dir.chdir @dir do
    # Install dependencies using Composer
    # https://getcomposer.org
    command = 'php composer.phar install'
    Open3.popen2(command,{:err => [:child, :out]}) do |stdin,stdout,wait_thr|
      print 'Installing dependencies'
      output = ''
      stdout.each_line do |line|
        output << line
        print '.'
      end
      
      exit_status = wait_thr.value
      
      puts
      
      unless exit_status.success?
        raise Ptero::Exception::ApplicationException, "Could not install dependencies in Application \"#{self.name}\" with command `#{command}`. Output was: \"#{output.chomp}\""
      end
      puts 'Done!'
    end
  end
  self
end

#reload(klass, *params) ⇒ Object

Remove and reload an existing file

Parameters:

  • klass (String, Class)

    what type of file to reload

  • *params

    all other parameters to pass to the generator



196
197
198
199
200
201
# File 'lib/ptero/application.rb', line 196

def reload(klass,*params)
  klass = generator_for_name(klass) if klass.is_a? String
  generator = klass.new(*params)
  generator.reload
  self
end

#remove(klass, *params) ⇒ Object

Remove a previously generated file

Parameters:

  • klass (String, Klass)

    what kind of file to remove

  • *params

    all other parameters to identify the file to be removed



225
226
227
228
229
230
# File 'lib/ptero/application.rb', line 225

def remove(klass,*params)
  klass = generator_for_name(klass) if klass.is_a? String # if klass is a string, make sure it's a class
  generator = klass.new(*params)
  generator.remove
  self
end

#remove_composerApplication, Boolean

Remove the composer.phar file

Returns:

  • (Application, Boolean)

    self if composer was removed, flse if composer is not downloaded

Raises:



92
93
94
95
96
# File 'lib/ptero/application.rb', line 92

def remove_composer
  raise Ptero::Exception::ApplicationException, "Application \"#{self.name}\" does not have a composer.phar file" unless has_composer?
  File.unlink(dir.join('composer.phar'))
  self
end

#remove_dependenciesObject



169
170
171
# File 'lib/ptero/application.rb', line 169

def remove_dependencies
  FileUtils.rm_r(dir.join('vendor'))
end

#route(path, controller) ⇒ Object

Add a route to the Application routes file

Parameters:

  • path (String)

    the new route’s path

  • controller (String)

    the name of the new route’s controller



206
207
208
209
210
211
# File 'lib/ptero/application.rb', line 206

def route(path,controller)
  klass = generator_for_name('Routes')
  generator = klass.new
  generator.route(path,controller)
  self
end

#routesHash

Find all routes set in the current Application

Returns:

  • (Hash)

    a Hash-map of each path to its corresponding controller



234
235
236
237
238
239
# File 'lib/ptero/application.rb', line 234

def routes
  klass = generator_for_name('Routes')
  generator = klass.new
  generator.get_current_routes
  generator.routes.dup
end

#test_phpBoolean

Find out whether or not the user has the PHP command-line tool installed so that they can use Composer.

Returns:

  • (Boolean)

    whether or not the user’s PHP command works.



53
54
55
56
57
# File 'lib/ptero/application.rb', line 53

def test_php
  Dir.chdir @dir do
    `php -r'echo "Success!";'` == 'Success!'
  end
end

#unroute(path) ⇒ Object

Remove a rotue from the Application routes file

Parameters:

  • path (String)

    the path to be deleted



215
216
217
218
219
220
# File 'lib/ptero/application.rb', line 215

def unroute(path)
  klass = generator_for_name('Routes')
  generator = klass.new
  generator.unroute(path)
  self
end

#update_dependenciesApplication

Update all dependencies listed in the composer.json file using Composer ‘php composer.phar update’

Returns:

Raises:



141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/ptero/application.rb', line 141

def update_dependencies
  raise Ptero::Exception::ApplicationException, "Not a dinosaur root: #{Dir.pwd}" unless verify
  raise Ptero::Exception::ApplicationException, "PHP command-line tool failed, update your version of PHP" unless test_php
  get_composer unless has_composer?
  Dir.chdir @dir do
    # Update dependencies using Composer
    # https://getcomposer.org
    command = 'php composer.phar update'
    Open3.popen2(command,{:err => [:child, :out]}) do |stdin,stdout,wait_thr|
      print 'Updating dependencies'
      output = ''
      stdout.each_line do |line|
        output << line
        print '.'
      end
      exit_status = wait_thr.value  
      puts
      
      unless exit_status.success?
        raise Ptero::Exception::ApplicationException, "Could not update dependencies in Application \"#{self.name}\" with command `#{command}`. Output was: \"#{output.chomp}\""
      end
      
      puts 'Done!'
    end
  end
  self
end

#verifyBoolean

Find out if this folder really contains a Ptero application using metadat

Returns:

  • (Boolean)

    whether or not this application was verified successfully



43
44
45
46
47
48
49
# File 'lib/ptero/application.rb', line 43

def verify
  composer_path = dir.join('composer.json')
  return false unless File.exist? composer_path
  hash = JSON.parse File.read(composer_path)
  return false unless hash['dinosaur'] && hash['dinosaur']['root']
  true
end