Module: Padrino::Generators::Actions

Included in:
AdminApp, AdminPage, App, Component, Controller, Helper, Mailer, Migration, Model, Plugin, Project, Task
Defined in:
padrino-gen/lib/padrino-gen/generators/actions.rb

Overview

Common actions needed to support project and component generation.

Defined Under Namespace

Modules: ClassMethods

Instance Method Summary collapse

Instance Method Details

#already_exists?(name, project_name = nil) ⇒ Boolean

Returns true if constant name already exists.

Returns:

  • (Boolean)


218
219
220
221
# File 'padrino-gen/lib/padrino-gen/generators/actions.rb', line 218

def already_exists?(name, project_name = nil)
  project_name = project_name ? (Object.const_get(project_name) rescue nil) : nil
  Object.const_defined?(name) || (project_name && project_name.const_defined?(name))
end

#app_skeleton(app, tiny = false) ⇒ Object

Generates standard and tiny applications within a project.

Examples:

app_skeleton 'some_app'
app_skeleton 'sub_app', true

Parameters:

  • app (String)

    Name of application.

  • tiny (Boolean) (defaults to: false)

    Boolean to generate a tiny structure.



470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
# File 'padrino-gen/lib/padrino-gen/generators/actions.rb', line 470

def app_skeleton(app, tiny=false)
  directory('app/', destination_root(app))
  if tiny
    template 'templates/controller.rb.tt', destination_root(app, 'controllers.rb')
    @helper_name = DEFAULT_HELPER_NAME
    template 'templates/helper.rb.tt', destination_root(app, 'helpers.rb')
    @short_name = 'notifier'
    template 'templates/mailer.rb.tt', destination_root(app, 'mailers.rb')
  else
    empty_directory destination_root(app, 'controllers')
    empty_directory destination_root(app, 'helpers')
    empty_directory destination_root(app, 'views')
    empty_directory destination_root(app, 'views', 'layouts')
  end
end

#apply_component_for(choice, component) ⇒ Object

Returns the related module for a given component and option.

Examples:

apply_component_for('rr', :mock)

Parameters:

  • choice (String)

    The name of the component module.

  • component (Symbol)

    The type of the component module.



56
57
58
59
60
61
62
63
# File 'padrino-gen/lib/padrino-gen/generators/actions.rb', line 56

def apply_component_for(choice, component)
  # I need to override Thor#apply because for unknow reason :verbose => false break tasks.
  path = File.expand_path(File.dirname(__FILE__) + "/components/#{component.to_s.pluralize}/#{choice}.rb")
  say_status :apply, "#{component.to_s.pluralize}/#{choice}"
  shell.padding += 1
  instance_eval(File.read(path))
  shell.padding -= 1
end

#apply_default_fields(fields) ⇒ Array<String>

Apply default field types.

Parameters:

  • fields (Array<String>)

    Field names for generators.

Returns:

  • (Array<String>)

    fields with default types



247
248
249
# File 'padrino-gen/lib/padrino-gen/generators/actions.rb', line 247

def apply_default_fields(fields)
  fields.map! { |field| field =~ /:/ ? field : "#{field}:string" }
end

#check_app_existence(app) ⇒ Object

Raise SystemExit if the app does not exist.

Examples:

check_app_existence 'app'

Parameters:

  • app (String)

    Directory name of application.



447
448
449
450
451
452
453
454
455
456
# File 'padrino-gen/lib/padrino-gen/generators/actions.rb', line 447

def check_app_existence(app)
  unless File.exist?(destination_root(app))
    say
    say "================================================================="
    say "Unable to locate '#{app.underscore.camelize}' application        "
    say "================================================================="
    say
    raise SystemExit
  end
end

#destination_root(*paths) ⇒ String

Returns the root for this Thor class (also aliased as destination root).

Examples:

destination_root('config/boot.rb')

Parameters:

  • paths (Array<String>)

    The relative path from destination root.

Returns:



204
205
206
# File 'padrino-gen/lib/padrino-gen/generators/actions.rb', line 204

def destination_root(*paths)
  File.expand_path(File.join(@destination_stack.last, paths))
end

#empty_directory_with_keep_file(destination, config = {}) ⇒ Object

Creates an empty directory with .keep file



531
532
533
534
# File 'padrino-gen/lib/padrino-gen/generators/actions.rb', line 531

def empty_directory_with_keep_file(destination, config = {})
  empty_directory(destination, config)
  keep_file(destination)
end

#execute_component_setup(component, choice) ⇒ Object

Performs the necessary generator for a given component choice.

Examples:

execute_component_setup(:mock, 'rr')

Parameters:

  • component (Symbol)

    The type of component module.

  • choice (String)

    The name of the component module choice.



38
39
40
41
42
43
# File 'padrino-gen/lib/padrino-gen/generators/actions.rb', line 38

def execute_component_setup(component, choice)
  return true && say_status(:skipping, "#{component} component...") if choice.to_s == 'none'
  say_status(:applying, "#{choice} (#{component})...")
  apply_component_for(choice, component)
  send("setup_#{component}") if respond_to?("setup_#{component}")
end

#fetch_app_name(app = 'app') ⇒ String

Returns the app_name for the application at root.

Examples:

fetch_app_name('subapp')

Parameters:

  • app (String) (defaults to: 'app')

    folder name of application.

Returns:

  • (String)

    class name for application.



291
292
293
294
# File 'padrino-gen/lib/padrino-gen/generators/actions.rb', line 291

def fetch_app_name(app='app')
  app_path = destination_root(app, 'app.rb')
  @app_name ||= File.read(app_path).scan(/class\s(.*?)\s</).flatten[0]
end

#fetch_component_choice(component) ⇒ String

Returns the component choice stored within the .component file of an application.

Examples:

fetch_component_choice(:mock)

Parameters:

  • component (Symbol)

    The type of component module.

Returns:

  • (String)

    Name of the component module.



95
96
97
# File 'padrino-gen/lib/padrino-gen/generators/actions.rb', line 95

def fetch_component_choice(component)
  retrieve_component_config(destination_root('.components'))[component]
end

#fetch_project_name(app = 'app') ⇒ String

Returns the namespace for the project.

Examples:

fetch_project_name

Parameters:

  • app (String) (defaults to: 'app')

    folder name of application.

Returns:

  • (String)

    namespace for application.



261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
# File 'padrino-gen/lib/padrino-gen/generators/actions.rb', line 261

def fetch_project_name(app='app')
  app_path = destination_root(app, 'app.rb')
  @project_name = fetch_component_choice(:namespace) if @project_name.empty?
  @project_name ||= begin
    say "Autodetecting project namespace using folder name.", :red
    say ""
    detected_namespace = File.basename(destination_root('.')).gsub(/\W/, '_').camelize
    say(<<-WARNING, :red)
From v0.11.0 on, applications should have a `namespace` setting
in their .components file. Please include a line like the following
in your .components file:
WARNING
    say "\t:namespace: #{detected_namespace}", :yellow
    say ""

    detected_namespace
  end
end

#in_app_root?Boolean

Returns true if inside a Padrino application.

Returns:

  • (Boolean)


211
212
213
# File 'padrino-gen/lib/padrino-gen/generators/actions.rb', line 211

def in_app_root?
  File.exist?(destination_root('config/boot.rb'))
end

#include_component_module_for(component, choice = nil) ⇒ Object

Includes the component module for the given component and choice. It determines the choice using .components file.

Examples:

include_component_module_for(:mock)
include_component_module_for(:mock, 'rr')

Parameters:

  • component (Symbol)

    The type of component module.

  • choice (String) (defaults to: nil)

    The name of the component module.



78
79
80
81
82
# File 'padrino-gen/lib/padrino-gen/generators/actions.rb', line 78

def include_component_module_for(component, choice=nil)
  choice = fetch_component_choice(component) unless choice
  return false if choice.to_s == 'none'
  apply_component_for(choice, component)
end

#initializer(name, data = nil) ⇒ Object

Registers and creates initializer.

Examples:

initializer(:test, "some stuff here")
#=> generates 'lib/test_init.rb'

Parameters:

  • name (Symbol)

    Name of the initializer.

  • data (String) (defaults to: nil)

    Text to generate into the initializer file.



378
379
380
381
382
383
# File 'padrino-gen/lib/padrino-gen/generators/actions.rb', line 378

def initializer(name, data=nil)
  @_init_name, @_init_data = name, data
  register = data ? "    register #{name.to_s.underscore.camelize}Initializer\n" : "    register #{name}\n"
  inject_into_file destination_root("/app/app.rb"), register, :after => "Padrino::Application\n"
  template "templates/initializer.rb.tt", destination_root("/config/initializers/#{name}.rb") if data
end

#inject_into_file(destination, *args, &block) ⇒ Object

Avoids editing destination file if it does not exist.



21
22
23
24
25
# File 'padrino-gen/lib/padrino-gen/generators/actions.rb', line 21

def inject_into_file(destination, *args, &block)
  destination_path = Pathname.new(destination).absolute? ? destination : destination_root(destination)
  return unless File.exist?(destination_path)
  super
end

#insert_hook(include_text, where) ⇒ Object

Inserts an hook before or after load in our boot.rb.

Examples:

insert_hook("DataMapper.finalize", :after_load)

Parameters:

  • include_text (String)

    Text to include into hooks in boot.rb.

  • where (Symbol)

    method hook to call from Padrino, i.e :after_load, :before_load.



348
349
350
# File 'padrino-gen/lib/padrino-gen/generators/actions.rb', line 348

def insert_hook(include_text, where)
  inject_into_file('config/boot.rb', "  #{include_text}\n", :after => "Padrino.#{where} do\n")
end

#insert_into_gemfile(name, options = {}) ⇒ Object

Inserts a required gem into the Gemfile to add the bundler dependency.

Examples:

insert_into_gemfile(name)
insert_into_gemfile(name, :group => 'test', :require => 'foo')
insert_into_gemfile(name, :group => 'test', :version => ">1.2.3")

Parameters:

  • name (String)

    Name of gem to insert into Gemfile.

  • options (Hash) (defaults to: {})

    Options to generate into Gemfile for gem.



327
328
329
330
331
332
333
334
335
# File 'padrino-gen/lib/padrino-gen/generators/actions.rb', line 327

def insert_into_gemfile(name, options={})
  after_pattern = options[:group] ? "#{options[:group].to_s.capitalize} requirements\n" : "Component requirements\n"
  version       = options.delete(:version)
  gem_options   = options.map { |k, v| k.to_s == 'require' && [true,false].include?(v) ? ":#{k} => #{v}" : ":#{k} => '#{v}'" }.join(", ")
  write_option  = gem_options.empty? ? '' : ", #{gem_options}"
  write_version = version ? ", '#{version}'" : ''
  include_text  = "gem '#{name}'" << write_version << write_option << "\n"
  inject_into_file('Gemfile', include_text, :after => after_pattern)
end

#insert_middleware(include_text, app = nil) ⇒ Object

Inserts a middleware inside app.rb.

Examples:

insert_middleware(ActiveRecord::ConnectionAdapters::ConnectionManagement)

Parameters:

  • include_text (String)

    Text to include into hooks in boot.rb.



361
362
363
364
# File 'padrino-gen/lib/padrino-gen/generators/actions.rb', line 361

def insert_middleware(include_text, app=nil)
  name = app || (options[:name] ? @app_name.downcase : 'app')
  inject_into_file("#{name}/app.rb", "    use #{include_text}\n", :after => "Padrino::Application\n")
end

#invalid_fields(fields) ⇒ Array<String>

Returns the field with an unacceptable name(for symbol) else returns nil.

Examples:

invalid_fields ['foo:bar', 'hello:world']

Parameters:

  • fields (Array<String>)

    Field names for generators.

Returns:

  • (Array<String>)

    array of invalid fields



234
235
236
237
# File 'padrino-gen/lib/padrino-gen/generators/actions.rb', line 234

def invalid_fields(fields)
  results = fields.select { |field| field.split(":").first =~ /\W/ }
  results.empty? ? nil : results
end

#keep_file(destination) ⇒ Object

Creates an empty .keep file



539
540
541
# File 'padrino-gen/lib/padrino-gen/generators/actions.rb', line 539

def keep_file(destination)
  create_file("#{destination}/.keep")
end

#middleware(name, source) ⇒ Object

Creates and inserts middleware.

Examples:

middleware(:hello, "class Hello\nend")
#=> generates 'lib/hello_middleware.rb'

Parameters:

  • name (Symbol, String)

    Name of the middleware.

  • source (String)

    Text to generate into the middleware file.



396
397
398
399
# File 'padrino-gen/lib/padrino-gen/generators/actions.rb', line 396

def middleware(name, source)
  create_file destination_root("lib/#{name}_middleware.rb"), source
  insert_middleware name.to_s.underscore.camelize
end

#recognize_pathObject

Recognizes the path of application.



524
525
526
# File 'padrino-gen/lib/padrino-gen/generators/actions.rb', line 524

def recognize_path
  options[:app] == '.' ? '/..' : '/../..'
end

#require_contrib(contrib) ⇒ Object

Insert the regired gem and add in boot.rb custom contribs.

Examples:

require_contrib('auto_locale')

Parameters:

  • contrib (String)

    name of library from padrino-contrib



410
411
412
413
414
# File 'padrino-gen/lib/padrino-gen/generators/actions.rb', line 410

def require_contrib(contrib)
  insert_into_gemfile 'padrino-contrib'
  contrib = "require '" + File.join("padrino-contrib", contrib) + "'\n"
  inject_into_file destination_root("/config/boot.rb"), contrib, :before => "\nPadrino.load!"
end

#require_dependencies(*gem_names) ⇒ Object

Adds all the specified gems into the Gemfile for bundler.

Examples:

require_dependencies('active_record')
require_dependencies('mocha', 'bacon', :group => 'test')
require_dependencies('json', :version => ">=1.2.3")

Parameters:

  • gem_names (Array<String>)

    Splat of gems to require in Gemfile.

  • options (Hash)

    The options to pass to gem in Gemfile.



309
310
311
312
# File 'padrino-gen/lib/padrino-gen/generators/actions.rb', line 309

def require_dependencies(*gem_names)
  options = gem_names.last.is_a?(Hash) ? gem_names.pop : {}
  gem_names.reverse_each { |lib| insert_into_gemfile(lib, options) }
end

#resolve_valid_choice(component) ⇒ String

Prompts the user if necessary until a valid choice is returned for the component.

Examples:

resolve_valid_choice(:mock)

Parameters:

  • component (Symbol)

    The type of component module.

Returns:

  • (String)

    Name of component if valid, otherwise ask for valid choice.



147
148
149
150
151
152
153
154
155
# File 'padrino-gen/lib/padrino-gen/generators/actions.rb', line 147

def resolve_valid_choice(component)
  choices = self.class.available_choices_for(component).map(&:to_s)
  choice = options[component]
  until valid_choice?(component, choice)
    say("Option for --#{component} '#{choice}' is not available.", :red)
    choice = ask("Please enter a valid option for #{component}:", :limited_to => choices)
  end
  choice
end

#retrieve_component_config(target) ⇒ Hash

Loads the component config back into a hash.

Examples:

retrieve_component_config(...)
# => { :mock => 'rr', :test => 'rspec', ... }

Parameters:

  • target (String)

    Path to component config file.

Returns:

  • (Hash)

    Loaded YAML file.



132
133
134
# File 'padrino-gen/lib/padrino-gen/generators/actions.rb', line 132

def retrieve_component_config(target)
  YAML.load_file(target)
end

#run_bundlerObject

Run the bundler.



433
434
435
436
# File 'padrino-gen/lib/padrino-gen/generators/actions.rb', line 433

def run_bundler
  say 'Bundling application dependencies using bundler...', :yellow
  in_root { run 'bundle install --binstubs' }
end

#store_component_choice(key, value) ⇒ Symbol

Set the component choice in the .component file of the application.

Examples:

store_component_choice(:renderer, :haml)

Parameters:

  • key (Symbol)

    The type of component module.

  • value (Symbol)

    The name of the component module.

Returns:

  • (Symbol)

    The name of the component module.



112
113
114
115
116
117
118
# File 'padrino-gen/lib/padrino-gen/generators/actions.rb', line 112

def store_component_choice(key, value)
  path        = destination_root('.components')
  config      = retrieve_component_config(path)
  config[key] = value
  create_file(path, :force => true) { config.to_yaml }
  value
end

#store_component_config(destination, opts = {}) ⇒ Object

Creates a component_config file at the destination containing all component options. Content is a YAMLized version of a hash containing component name mapping to chosen value.

Examples:

store_component_config('/foo/bar')

Parameters:

  • destination (String)

    The file path to store the component config.



184
185
186
187
188
189
190
191
# File 'padrino-gen/lib/padrino-gen/generators/actions.rb', line 184

def store_component_config(destination, opts = {})
  components = @_components || options
  create_file(destination, opts) do
    self.class.component_types.inject({}) { |result, comp|
      result[comp] = components[comp].to_s; result
    }.to_yaml
  end
end

#test?Boolean

Return true if our project has test component.

Returns:

  • (Boolean)


419
420
421
# File 'padrino-gen/lib/padrino-gen/generators/actions.rb', line 419

def test?
  fetch_component_choice(:test).to_s != 'none'
end

#tiny?Boolean

Return true if we have a tiny skeleton.

Returns:

  • (Boolean)


426
427
428
# File 'padrino-gen/lib/padrino-gen/generators/actions.rb', line 426

def tiny?
  File.exist?(destination_root('app/controllers.rb'))
end

#valid_choice?(component, choice) ⇒ Boolean

Returns true if the option passed is a valid choice for component.

Examples:

valid_choice?(:mock, 'rr')

Parameters:

  • component (Symbol)

    The type of component module.

  • choice (String)

    The name of the component module.

Returns:

  • (Boolean)

    Boolean of whether the choice is valid.



170
171
172
# File 'padrino-gen/lib/padrino-gen/generators/actions.rb', line 170

def valid_choice?(component, choice)
  choice && self.class.available_choices_for(component).include?(choice.to_sym)
end

#valid_constant?(name) ⇒ Exception

Ensures that project name is valid, else raise an NameError.

Examples:

valid_constant '1235Stuff'
valid_constant '#Abc'

Parameters:

  • name (String)

    Name of project.

Returns:

  • (Exception)

    Exception with error message if not valid.



498
499
500
501
502
503
504
# File 'padrino-gen/lib/padrino-gen/generators/actions.rb', line 498

def valid_constant?(name)
  if name =~ /^\d/
    fail ::NameError, "Constant name #{name} cannot start with numbers"
  elsif name =~ /^\W/
    fail ::NameError, "Constant name #{name} cannot start with non-word character"
  end
end

#validate_namespace(name) ⇒ Object

Validates namespace name (controller name, etc.) or fails with an error.

Examples:

validate_namespace 'Project_One1' #=> pass
validate_namespace 'Erroneous/name' #=> fail

Parameters:

  • name (String)

    Name of namespace



516
517
518
519
# File 'padrino-gen/lib/padrino-gen/generators/actions.rb', line 516

def validate_namespace(name)
  valid_constant? name
  name.match(/^[[:alnum:]_]+$/) || fail(::NameError, "Namespace '#{name}' must consist only of alphanumeric characters or '_'")
end