initial commit

This commit is contained in:
2018-01-20 13:02:44 -03:00
commit 203138a969
650 changed files with 19523 additions and 0 deletions
+45
View File
@@ -0,0 +1,45 @@
Dunlop workflow tool system
================================
Installation
---------------------------------------
To use Dunlop in your project add it to your Gemfile
```ruby
gem 'dunlop'
```
and create the project scaffold:
```
rails generate dunlop:install
```
Generators
---------------------------------------
### source_file
To add a source file to your project use the <tt>source_file</tt>
generator:
```
rails generate source_file planned_dslams
```
<strong>NOTE: do a git commit before you use a generator!</strong>
Possible options for the generator are:
* `--sql` to add scaffold sql templates to load data using sql
* `--source_record` if the data is loaded into a connected SourceRecord
model associated with the latest loaded source file.
* `--attributes="Attr 1" "Attr 2" attr_3` to list the header columns of
the source file. The attributes will be assumed to have an underscored
column name form with spaces replaced by underscores. Default column
type will be string. It is meant as a fast and good start, not a final
result.
So to generate a full featured source file the following will work:
```
rails generate source_file planned_dslams --sql --source_record --attributes="Attr 1" attr_etc
```
### dunlop:scenario
To add a scenario to your project:
```
rails generate dunlop:scenario VulaMigration
```
+1
View File
@@ -0,0 +1 @@
require "dunlop"
+123
View File
@@ -0,0 +1,123 @@
require "csv"
module Dunlop::CsvBuilder
extend ActiveSupport::Concern
included do
attr_reader :resource, :options, :csv_options, :controller
class_attribute :default_csv_options
self.default_csv_options = {}
end
def initialize(resource, options = {})
@resource, @options = resource, options
@csv_options = default_csv_options.merge(options.slice(:col_sep, :row_sep, :encoding, :field_size_limit, :quote_char, :force_quotes))
@controller = options[:controller]
end
def file_name
options[:file_name] || "#{Rails.application.config.application_name}-#{date_number}-data.csv"
end
def headers
[]
end
def for_each_serialized_row(&block)
iterate_over = iteration_resource
iterate_over = Array.wrap(iterate_over) unless iterate_over.respond_to?(:find_each_ordered) || iterate_over.respond_to?(:each) # allow resource to be a record using the index's csv builder
iteration_method = iterate_over.respond_to?(:find_each_ordered) ? :find_each_ordered : :each
iterate_over.public_send(iteration_method) do |*args|
block.call serialize_row(*args)
end
end
def serialize_row(record)
[record.id]
end
def data
# use #to_csv for base_class builders if present
# in custom class implement"
# def data
# resource.to_csv
# end
# since Arrays implement #to_csv, but we do not want to use it in this case we explicitly exclude it
return resource.to_csv if self.class == CsvBuilder and resource.present? and resource.respond_to?(:to_csv) and !resource.is_a?(Array)
# try iteration otherwise
str = CSV.generate csv_options do |csv|
csv << headers if headers.present?
for_each_serialized_row do |serialized_row|
csv << serialized_row
end
end
str
end
def date_number
Date.current.to_s(:number)
end
# This method can be overridden in order to use another iteration source than the resource eg:
# resouce = batch
# def iteration_resource
# resource.workflow_instances
# end
def iteration_resource
resource
end
#TODO: this is a separate include, not part of the core CsvBuilder object
def workflow_instances_in_batch
resource.workflow_instances.for_filtered_export
end
# Do a lookup on a record of an attribute and map the value to the
# csv required version if appliccable. At the moment booleans are
# converted to zeros and ones
def record_attribute(record, attribute_name)
result = record.public_send(attribute_name)
case result
when TrueClass then 1
when FalseClass then 0
when String then result.strip.gsub(/\r\n?|\n/, " ")
when DayTimeBase then result.number
else result
end
end
# Make some options available as methods
%i[action_name controller_path].each do |option_method|
define_method option_method do
options[option_method]
end
end
module ClassMethods
# find the csv builder for the given route spec
def find_for_route(route_spec)
find_for_route_lookup_order(route_spec).lazy.map(&:safe_constantize).find(&:itself)
end
# separate method since this is the important method to test, so extracted from the main method
def find_for_route_lookup_order(route_spec)
controller_path, action_name = route_spec.split('#')
controller_parts = controller_path.split('/')
if controller_parts.size < 2
parts = controller_parts.map(&:classify)
else
parts = controller_parts[0..-2].map(&:camelize)
parts << controller_parts.last.classify
end
# Create a lookup tree that uses all the namespaces, followed by the actoin name
# and ending with CsvBuilder for consitancy. Aka: if the route is:
# workflow_instances/scenario1s#show
# the lookup_order should be:
# ["WorkflowInstanceBatch::Scenario1::ShowCsvBuilder", "WorkflowInstanceBatch::ShowCsvBuilder"]
action_postfix = "::#{action_name.camelize}CsvBuilder"
parts.map.with_index{|p, i| parts[0..(i - 1)].join('::') + action_postfix}
end
end
end
+61
View File
@@ -0,0 +1,61 @@
# Asset groups
if (Rails.groups.map(&:to_s) & %w[development assets test]).any?
require "font-awesome-rails"
require "sass-rails"
require "js-routes"
require "momentjs-rails"
require 'coffee-rails'
require "pickadate-rails"
end
require "slim-rails"
require 'record_collection'
require 'request_store'
require 'ransack'
require 'devise'
require 'devise-token_authenticatable'
require 'state_machines-activerecord'
require 'carrierwave'
require 'simple_form'
require 'redcarpet'
require 'exception_notification'
require 'facets/enumerable/map_send'
require 'memoist'
require 'cancancan'
if Rails::VERSION::MAJOR < 5
ActiveRecord::Associations::Builder::Association.valid_options |= [:optional]
class ActiveRecord::Migration
# rails5 compatibility
def self.[](*)
self
end
end
end
module Dunlop
class Engine < ::Rails::Engine
isolate_namespace Dunlop
initializer 'dunlop.action_controller' do |app|
ActiveSupport.on_load :action_controller do
helper Dunlop::ApplicationHelper if respond_to?(:helper)
end
end
initializer "dunlop.ability", group: 'dunlop' do |app|
if ability_class = "Ability".safe_constantize and ability_class.respond_to?(:add_dunlop_allowed_authorization_classes!)
ability_class.add_dunlop_allowed_authorization_classes!
end
end
# add migrations to containing application
initializer :append_migrations do |app|
unless app.root.to_s.match root.to_s
config.paths["db/migrate"].expanded.each do |expanded_path|
app.config.paths["db/migrate"] << expanded_path
end
end
end
end
end
+8
View File
@@ -0,0 +1,8 @@
module Dunlop::Generators
end
module Dunlop::Install
end
require "dunlop/generators/generator_helpers"
+104
View File
@@ -0,0 +1,104 @@
module Dunlop::Generators::GeneratorHelpers
extend ActiveSupport::Concern
def inject_before_last_end(file_path, code)
code << "\n" unless code.last == "\n"
code = " #{code}" unless code.first =~ /^\s/
inject_into_file file_path, code, before: /^end/
end
module ClassMethods
def next_migration_number(path)
ActiveRecord::Generators::Base.next_migration_number(path)
end
end
class DunlopGeneratorAttribute
attr_reader :name
def initialize(spec)
@name, @type = spec.to_s.strip.split(':')
end
def type
@type || 'string'
end
def column_name
name.to_s.underscore.gsub(/\W/, '_')
end
def to_s
name
end
def form_type
case type
when 'boolean' then 'boolean'
else 'input'
end
end
def boolean?
type == 'boolean'
end
def integer?
type == 'integer'
end
def float?
%w[decimal float].include?(type)
end
def numeric?
integer? or float?
end
def date?
type == 'date'
end
end
private
def attributes
options.attributes.map{|a| DunlopGeneratorAttribute.new(a) }
end
# Taken from base rails and modified for gsub block support
def gsub_file(path, flag, *args, &block)
config = args.last.is_a?(Hash) ? args.pop : {}
path = File.expand_path(path, destination_root)
if not File.exist? path
say_status :gsub, set_color("The file #{path} cannot be found", :yellow)
return
end
say_status :gsub, relative_to_original_destination_root(path), config.fetch(:verbose, true)
unless options[:pretend]
content = File.binread(path)
if block.present? # modification from rails standard to support match data in supplied blocks
content.gsub!(flag, *args){ block.call( Regexp.last_match ) }
else
content.gsub!(flag, *args)
end
File.open(path, "wb") { |file| file.write(content) }
end
end
##
# Add a name to a definition list. eg:
# setup_secnarios %i[
# existing_scenario
# ]
# at the bottom.
def add_to_symbol_list(file_path, setup_method, name)
if behavior == :revoke
gsub_file file_path, /(#{setup_method} %i\[.*)\n\s+#{name}(.*)\]/m, '\1\2]'
else
return if File.read(file_path) =~ /^ #{setup_method} %i\[[^\]]*\W#{name}\W[^\]]*\]/m # only add once
gsub_file file_path, /(^ #{setup_method} %i\[\n[^\]]*)]/m, "\\1 #{name}\n ]"
end
end
end
+2
View File
@@ -0,0 +1,2 @@
module Dunlop
end
+3
View File
@@ -0,0 +1,3 @@
module Dunlop
VERSION = "1.4.0"
end