1668122160
A starter project that makes creating a TypeScript library extremely easy.
git clone https://github.com/alexjoverm/typescript-library-starter.git YOURFOLDERNAME
cd YOURFOLDERNAME
# Run npm install and write your library name when asked. That's all!
npm install
Start coding! package.json
and entry files are already set up for you, so don't worry about linking to your main file, typings, etc. Just keep those files with the same name.
npm install
things will setup for you :wink:gh-pages
, using TypeDoc(*.d.ts)
file generationYou can import the generated bundle to use the whole library generated by this starter:
import myLib from 'mylib'
Additionally, you can import the transpiled modules from dist/lib
in case you have a modular library:
import something from 'mylib/dist/lib/something'
npm t
: Run test suitenpm start
: Run npm run build
in watch modenpm run test:watch
: Run test suite in interactive watch modenpm run test:prod
: Run linting and generate coveragenpm run build
: Generate bundles and typings, create docsnpm run lint
: Lints codenpm run commit
: Commit using conventional commit style (husky will tell you to use it if you haven't :wink:)On library development, one might want to set some peer dependencies, and thus remove those from the final bundle. You can see in Rollup docs how to do that.
Good news: the setup is here for you, you must only include the dependency name in external
property within rollup.config.js
. For example, if you want to exclude lodash
, just write there external: ['lodash']
.
Prerequisites: you need to create/login accounts and add your project to:
Prerequisite for Windows: Semantic-release uses node-gyp so you will need to install Microsoft's windows-build-tools using this command:
npm install --global --production windows-build-tools
Follow the console instructions to install semantic release and run it (answer NO to "Do you want a .travis.yml
file with semantic-release setup?").
Note: make sure you've setup repository.url
in your package.json
file
npm install -g semantic-release-cli
semantic-release-cli setup
# IMPORTANT!! Answer NO to "Do you want a `.travis.yml` file with semantic-release setup?" question. It is already prepared for you :P
From now on, you'll need to use npm run commit
, which is a convenient way to create conventional commits.
Automatic releases are possible thanks to semantic release, which publishes your code automatically on github and npm, plus generates automatically a changelog. This setup is highly influenced by Kent C. Dodds course on egghead.io
There is already set a precommit
hook for formatting your code with Prettier :nail_care:
By default, there are two disabled git hooks. They're set up when you run the npm run semantic-release-prepare
script. They make sure:
git push
This makes more sense in combination with automatic releases
Array.prototype.from
, Promise
, Map
... is undefined?TypeScript or Babel only provides down-emits on syntactical features (class
, let
, async/await
...), but not on functional features (Array.prototype.find
, Set
, Promise
...), . For that, you need Polyfills, such as core-js
or babel-polyfill
(which extends core-js
).
For a library, core-js
plays very nicely, since you can import just the polyfills you need:
import "core-js/fn/array/find"
import "core-js/fn/string/includes"
import "core-js/fn/promise"
...
npm install
doing on first run?It runs the script tools/init
which sets up everything for you. In short, it:
package.json
(typings file, main file, etc)Then you may want to:
commitmsg
, postinstall
scripts from package.json
. That will not use those git hooks to make sure you make a conventional commitnpm run semantic-release
from .travis.yml
Remove npm run report-coverage
from .travis.yml
typescript-library-starter
Here are some projects that use typescript-library-starter
:
Author: Alexjoverm
Source Code: https://github.com/alexjoverm/typescript-library-starter
License: MIT license
1668122160
A starter project that makes creating a TypeScript library extremely easy.
git clone https://github.com/alexjoverm/typescript-library-starter.git YOURFOLDERNAME
cd YOURFOLDERNAME
# Run npm install and write your library name when asked. That's all!
npm install
Start coding! package.json
and entry files are already set up for you, so don't worry about linking to your main file, typings, etc. Just keep those files with the same name.
npm install
things will setup for you :wink:gh-pages
, using TypeDoc(*.d.ts)
file generationYou can import the generated bundle to use the whole library generated by this starter:
import myLib from 'mylib'
Additionally, you can import the transpiled modules from dist/lib
in case you have a modular library:
import something from 'mylib/dist/lib/something'
npm t
: Run test suitenpm start
: Run npm run build
in watch modenpm run test:watch
: Run test suite in interactive watch modenpm run test:prod
: Run linting and generate coveragenpm run build
: Generate bundles and typings, create docsnpm run lint
: Lints codenpm run commit
: Commit using conventional commit style (husky will tell you to use it if you haven't :wink:)On library development, one might want to set some peer dependencies, and thus remove those from the final bundle. You can see in Rollup docs how to do that.
Good news: the setup is here for you, you must only include the dependency name in external
property within rollup.config.js
. For example, if you want to exclude lodash
, just write there external: ['lodash']
.
Prerequisites: you need to create/login accounts and add your project to:
Prerequisite for Windows: Semantic-release uses node-gyp so you will need to install Microsoft's windows-build-tools using this command:
npm install --global --production windows-build-tools
Follow the console instructions to install semantic release and run it (answer NO to "Do you want a .travis.yml
file with semantic-release setup?").
Note: make sure you've setup repository.url
in your package.json
file
npm install -g semantic-release-cli
semantic-release-cli setup
# IMPORTANT!! Answer NO to "Do you want a `.travis.yml` file with semantic-release setup?" question. It is already prepared for you :P
From now on, you'll need to use npm run commit
, which is a convenient way to create conventional commits.
Automatic releases are possible thanks to semantic release, which publishes your code automatically on github and npm, plus generates automatically a changelog. This setup is highly influenced by Kent C. Dodds course on egghead.io
There is already set a precommit
hook for formatting your code with Prettier :nail_care:
By default, there are two disabled git hooks. They're set up when you run the npm run semantic-release-prepare
script. They make sure:
git push
This makes more sense in combination with automatic releases
Array.prototype.from
, Promise
, Map
... is undefined?TypeScript or Babel only provides down-emits on syntactical features (class
, let
, async/await
...), but not on functional features (Array.prototype.find
, Set
, Promise
...), . For that, you need Polyfills, such as core-js
or babel-polyfill
(which extends core-js
).
For a library, core-js
plays very nicely, since you can import just the polyfills you need:
import "core-js/fn/array/find"
import "core-js/fn/string/includes"
import "core-js/fn/promise"
...
npm install
doing on first run?It runs the script tools/init
which sets up everything for you. In short, it:
package.json
(typings file, main file, etc)Then you may want to:
commitmsg
, postinstall
scripts from package.json
. That will not use those git hooks to make sure you make a conventional commitnpm run semantic-release
from .travis.yml
Remove npm run report-coverage
from .travis.yml
typescript-library-starter
Here are some projects that use typescript-library-starter
:
Author: Alexjoverm
Source Code: https://github.com/alexjoverm/typescript-library-starter
License: MIT license
1667468640
BUILD STATUS
NAME
Perl::Critic - Critique Perl source code for best-practices.
SYNOPSIS
use Perl::Critic;
my $file = shift;
my $critic = Perl::Critic->new();
my @violations = $critic->critique($file);
print @violations;
DESCRIPTION
Perl::Critic is an extensible framework for creating and applying coding standards to Perl source code. Essentially, it is a static source code analysis engine. Perl::Critic is distributed with a number of Perl::Critic::Policy modules that attempt to enforce various coding guidelines. Most Policy modules are based on Damian Conway's book Perl Best Practices. However, Perl::Critic is not limited to PBP and will even support Policies that contradict Conway. You can enable, disable, and customize those Polices through the Perl::Critic interface. You can also create new Policy modules that suit your own tastes.
For a command-line interface to Perl::Critic, see the documentation for perlcritic. If you want to integrate Perl::Critic with your build process, Test::Perl::Critic provides an interface that is suitable for test programs. Also, Test::Perl::Critic::Progressive is useful for gradually applying coding standards to legacy code. For the ultimate convenience (at the expense of some flexibility) see the criticism pragma.
If you'd like to try Perl::Critic without installing anything, there is a web-service available at http://perlcritic.com. The web-service does not yet support all the configuration features that are available in the native Perl::Critic API, but it should give you a good idea of what it does.
Also, ActivePerl includes a very slick graphical interface to Perl-Critic called perlcritic-gui
. You can get a free community edition of ActivePerl from http://www.activestate.com.
PREREQUISITES
Perl::Critic runs on Perl back to Perl 5.6.1. It relies on the PPI module to do the heavy work of parsing Perl.
INTERFACE SUPPORT
The Perl::Critic
module is considered to be a public class. Any changes to its interface will go through a deprecation cycle.
CONSTRUCTOR
new( [ -profile => $FILE, -severity => $N, -theme => $string, -include => \@PATTERNS, -exclude => \@PATTERNS, -top => $N, -only => $B, -profile-strictness => $PROFILE_STRICTNESS_{WARN|FATAL|QUIET}, -force => $B, -verbose => $N ], -color => $B, -pager => $string, -allow-unsafe => $B, -criticism-fatal => $B)
new()
Returns a reference to a new Perl::Critic object. Most arguments are just passed directly into Perl::Critic::Config, but I have described them here as well. The default value for all arguments can be defined in your .perlcriticrc
file. See the "CONFIGURATION" section for more information about that. All arguments are optional key-value pairs as follows:
-profile is a path to a configuration file. If $FILE
is not defined, Perl::Critic::Config attempts to find a .perlcriticrc
configuration file in the current directory, and then in your home directory. Alternatively, you can set the PERLCRITIC
environment variable to point to a file in another location. If a configuration file can't be found, or if $FILE
is an empty string, then all Policies will be loaded with their default configuration. See "CONFIGURATION" for more information.
-severity is the minimum severity level. Only Policy modules that have a severity greater than $N
will be applied. Severity values are integers ranging from 1 (least severe violations) to 5 (most severe violations). The default is 5. For a given -profile
, decreasing the -severity
will usually reveal more Policy violations. You can set the default value for this option in your .perlcriticrc
file. Users can redefine the severity level for any Policy in their .perlcriticrc
file. See "CONFIGURATION" for more information.
If it is difficult for you to remember whether severity "5" is the most or least restrictive level, then you can use one of these named values:
SEVERITY NAME ...is equivalent to... SEVERITY NUMBER
--------------------------------------------------------
-severity => 'gentle' -severity => 5
-severity => 'stern' -severity => 4
-severity => 'harsh' -severity => 3
-severity => 'cruel' -severity => 2
-severity => 'brutal' -severity => 1
The names reflect how severely the code is criticized: a gentle
criticism reports only the most severe violations, and so on down to a brutal
criticism which reports even the most minor violations.
-theme is special expression that determines which Policies to apply based on their respective themes. For example, the following would load only Policies that have a 'bugs' AND 'pbp' theme:
my $critic = Perl::Critic->new( -theme => 'bugs && pbp' );
Unless the -severity
option is explicitly given, setting -theme
silently causes the -severity
to be set to 1. You can set the default value for this option in your .perlcriticrc
file. See the "POLICY THEMES" section for more information about themes.
-include is a reference to a list of string @PATTERNS
. Policy modules that match at least one m/$PATTERN/ixms
will always be loaded, irrespective of all other settings. For example:
my $critic = Perl::Critic->new(-include => ['layout'], -severity => 4);
This would cause Perl::Critic to apply all the CodeLayout::*
Policy modules even though they have a severity level that is less than 4. You can set the default value for this option in your .perlcriticrc
file. You can also use -include
in conjunction with the -exclude
option. Note that -exclude
takes precedence over -include
when a Policy matches both patterns.
-exclude is a reference to a list of string @PATTERNS
. Policy modules that match at least one m/$PATTERN/ixms
will not be loaded, irrespective of all other settings. For example:
my $critic = Perl::Critic->new(-exclude => ['strict'], -severity => 1);
This would cause Perl::Critic to not apply the RequireUseStrict
and ProhibitNoStrict
Policy modules even though they have a severity level that is greater than 1. You can set the default value for this option in your .perlcriticrc
file. You can also use -exclude
in conjunction with the -include
option. Note that -exclude
takes precedence over -include
when a Policy matches both patterns.
-single-policy is a string PATTERN
. Only one policy that matches m/$PATTERN/ixms
will be used. Policies that do not match will be excluded. This option has precedence over the -severity
, -theme
, -include
, -exclude
, and -only
options. You can set the default value for this option in your .perlcriticrc
file.
-top is the maximum number of Violations to return when ranked by their severity levels. This must be a positive integer. Violations are still returned in the order that they occur within the file. Unless the -severity
option is explicitly given, setting -top
silently causes the -severity
to be set to 1. You can set the default value for this option in your .perlcriticrc
file.
-only is a boolean value. If set to a true value, Perl::Critic will only choose from Policies that are mentioned in the user's profile. If set to a false value (which is the default), then Perl::Critic chooses from all the Policies that it finds at your site. You can set the default value for this option in your .perlcriticrc
file.
-profile-strictness is an enumerated value, one of "$PROFILE_STRICTNESS_WARN" in Perl::Critic::Utils::Constants (the default), "$PROFILE_STRICTNESS_FATAL" in Perl::Critic::Utils::Constants, and "$PROFILE_STRICTNESS_QUIET" in Perl::Critic::Utils::Constants. If set to "$PROFILE_STRICTNESS_FATAL" in Perl::Critic::Utils::Constants, Perl::Critic will make certain warnings about problems found in a .perlcriticrc
or file specified via the -profile option fatal. For example, Perl::Critic normally only warn
s about profiles referring to non-existent Policies, but this value makes this situation fatal. Correspondingly, "$PROFILE_STRICTNESS_QUIET" in Perl::Critic::Utils::Constants makes Perl::Critic shut up about these things.
-force is a boolean value that controls whether Perl::Critic observes the magical "## no critic"
annotations in your code. If set to a true value, Perl::Critic will analyze all code. If set to a false value (which is the default) Perl::Critic will ignore code that is tagged with these annotations. See "BENDING THE RULES" for more information. You can set the default value for this option in your .perlcriticrc
file.
-verbose can be a positive integer (from 1 to 11), or a literal format specification. See Perl::Critic::Violation for an explanation of format specifications. You can set the default value for this option in your .perlcriticrc
file.
-unsafe directs Perl::Critic to allow the use of Policies that are marked as "unsafe" by the author. Such policies may compile untrusted code or do other nefarious things.
-color and -pager are not used by Perl::Critic but is provided for the benefit of perlcritic.
-criticism-fatal is not used by Perl::Critic but is provided for the benefit of criticism.
-color-severity-highest, -color-severity-high, -color-severity- medium, -color-severity-low, and -color-severity-lowest are not used by Perl::Critic, but are provided for the benefit of perlcritic. Each is set to the Term::ANSIColor color specification to be used to display violations of the corresponding severity.
-files-with-violations and -files-without-violations are not used by Perl::Critic, but are provided for the benefit of perlcritic, to cause only the relevant filenames to be displayed.
METHODS
critique( $source_code )
Runs the $source_code
through the Perl::Critic engine using all the Policies that have been loaded into this engine. If $source_code
is a scalar reference, then it is treated as a string of actual Perl code. If $source_code
is a reference to an instance of PPI::Document, then that instance is used directly. Otherwise, it is treated as a path to a local file containing Perl code. This method returns a list of Perl::Critic::Violation objects for each violation of the loaded Policies. The list is sorted in the order that the Violations appear in the code. If there are no violations, this method returns an empty list.
add_policy( -policy => $policy_name, -params => \%param_hash )
Creates a Policy object and loads it into this Critic. If the object cannot be instantiated, it will throw a fatal exception. Otherwise, it returns a reference to this Critic.
-policy is the name of a Perl::Critic::Policy subclass module. The 'Perl::Critic::Policy'
portion of the name can be omitted for brevity. This argument is required.
-params is an optional reference to a hash of Policy parameters. The contents of this hash reference will be passed into to the constructor of the Policy module. See the documentation in the relevant Policy module for a description of the arguments it supports.
policies()
Returns a list containing references to all the Policy objects that have been loaded into this engine. Objects will be in the order that they were loaded.
config()
Returns the Perl::Critic::Config object that was created for or given to this Critic.
statistics()
Returns the Perl::Critic::Statistics object that was created for this Critic. The Statistics object accumulates data for all files that are analyzed by this Critic.
FUNCTIONAL INTERFACE
For those folks who prefer to have a functional interface, The critique
method can be exported on request and called as a static function. If the first argument is a hashref, its contents are used to construct a new Perl::Critic object internally. The keys of that hash should be the same as those supported by the Perl::Critic::new()
method. Here are some examples:
use Perl::Critic qw(critique);
# Use default parameters...
@violations = critique( $some_file );
# Use custom parameters...
@violations = critique( {-severity => 2}, $some_file );
# As a one-liner
%> perl -MPerl::Critic=critique -e 'print critique(shift)' some_file.pm
None of the other object-methods are currently supported as static functions. Sorry.
CONFIGURATION
Most of the settings for Perl::Critic and each of the Policy modules can be controlled by a configuration file. The default configuration file is called .perlcriticrc
. Perl::Critic will look for this file in the current directory first, and then in your home directory. Alternatively, you can set the PERLCRITIC
environment variable to explicitly point to a different file in another location. If none of these files exist, and the -profile
option is not given to the constructor, then all the modules that are found in the Perl::Critic::Policy namespace will be loaded with their default configuration.
The format of the configuration file is a series of INI-style blocks that contain key-value pairs separated by '='. Comments should start with '#' and can be placed on a separate line or after the name-value pairs if you desire.
Default settings for Perl::Critic itself can be set before the first named block. For example, putting any or all of these at the top of your configuration file will set the default value for the corresponding constructor argument.
severity = 3 #Integer or named level
only = 1 #Zero or One
force = 0 #Zero or One
verbose = 4 #Integer or format spec
top = 50 #A positive integer
theme = (pbp || security) && bugs #A theme expression
include = NamingConventions ClassHierarchies #Space-delimited list
exclude = Variables Modules::RequirePackage #Space-delimited list
criticism-fatal = 1 #Zero or One
color = 1 #Zero or One
allow-unsafe = 1 #Zero or One
pager = less #pager to pipe output to
The remainder of the configuration file is a series of blocks like this:
[Perl::Critic::Policy::Category::PolicyName]
severity = 1
set_themes = foo bar
add_themes = baz
maximum_violations_per_document = 57
arg1 = value1
arg2 = value2
Perl::Critic::Policy::Category::PolicyName
is the full name of a module that implements the policy. The Policy modules distributed with Perl::Critic have been grouped into categories according to the table of contents in Damian Conway's book Perl Best Practices. For brevity, you can omit the 'Perl::Critic::Policy'
part of the module name.
severity
is the level of importance you wish to assign to the Policy. All Policy modules are defined with a default severity value ranging from 1 (least severe) to 5 (most severe). However, you may disagree with the default severity and choose to give it a higher or lower severity, based on your own coding philosophy. You can set the severity
to an integer from 1 to 5, or use one of the equivalent names:
SEVERITY NAME ...is equivalent to... SEVERITY NUMBER
----------------------------------------------------
gentle 5
stern 4
harsh 3
cruel 2
brutal 1
The names reflect how severely the code is criticized: a gentle
criticism reports only the most severe violations, and so on down to a brutal
criticism which reports even the most minor violations.
set_themes
sets the theme for the Policy and overrides its default theme. The argument is a string of one or more whitespace-delimited alphanumeric words. Themes are case-insensitive. See "POLICY THEMES" for more information.
add_themes
appends to the default themes for this Policy. The argument is a string of one or more whitespace-delimited words. Themes are case- insensitive. See "POLICY THEMES" for more information.
maximum_violations_per_document
limits the number of Violations the Policy will return for a given document. Some Policies have a default limit; see the documentation for the individual Policies to see whether there is one. To force a Policy to not have a limit, specify "no_limit" or the empty string for the value of this parameter.
The remaining key-value pairs are configuration parameters that will be passed into the constructor for that Policy. The constructors for most Policy objects do not support arguments, and those that do should have reasonable defaults. See the documentation on the appropriate Policy module for more details.
Instead of redefining the severity for a given Policy, you can completely disable a Policy by prepending a '-' to the name of the module in your configuration file. In this manner, the Policy will never be loaded, regardless of the -severity
given to the Perl::Critic constructor.
A simple configuration might look like this:
#--------------------------------------------------------------
# I think these are really important, so always load them
[TestingAndDebugging::RequireUseStrict]
severity = 5
[TestingAndDebugging::RequireUseWarnings]
severity = 5
#--------------------------------------------------------------
# I think these are less important, so only load when asked
[Variables::ProhibitPackageVars]
severity = 2
[ControlStructures::ProhibitPostfixControls]
allow = if unless # My custom configuration
severity = cruel # Same as "severity = 2"
#--------------------------------------------------------------
# Give these policies a custom theme. I can activate just
# these policies by saying `perlcritic -theme larry`
[Modules::RequireFilenameMatchesPackage]
add_themes = larry
[TestingAndDebugging::RequireTestLables]
add_themes = larry curly moe
#--------------------------------------------------------------
# I do not agree with these at all, so never load them
[-NamingConventions::Capitalization]
[-ValuesAndExpressions::ProhibitMagicNumbers]
#--------------------------------------------------------------
# For all other Policies, I accept the default severity,
# so no additional configuration is required for them.
For additional configuration examples, see the perlcriticrc
file that is included in this examples
directory of this distribution.
Damian Conway's own Perl::Critic configuration is also included in this distribution as examples/perlcriticrc-conway
.
THE POLICIES
A large number of Policy modules are distributed with Perl::Critic. They are described briefly in the companion document Perl::Critic::PolicySummary and in more detail in the individual modules themselves. Say "perlcritic -doc PATTERN"
to see the perldoc for all Policy modules that match the regex m/PATTERN/ixms
There are a number of distributions of additional policies on CPAN. If Perl::Critic doesn't contain a policy that you want, some one may have already written it. See the "SEE ALSO" section below for a list of some of these distributions.
POLICY THEMES
Each Policy is defined with one or more "themes". Themes can be used to create arbitrary groups of Policies. They are intended to provide an alternative mechanism for selecting your preferred set of Policies. For example, you may wish disable a certain subset of Policies when analyzing test programs. Conversely, you may wish to enable only a specific subset of Policies when analyzing modules.
The Policies that ship with Perl::Critic have been broken into the following themes. This is just our attempt to provide some basic logical groupings. You are free to invent new themes that suit your needs.
THEME DESCRIPTION
--------------------------------------------------------------------------
core All policies that ship with Perl::Critic
pbp Policies that come directly from "Perl Best Practices"
bugs Policies that that prevent or reveal bugs
certrec Policies that CERT recommends
certrule Policies that CERT considers rules
maintenance Policies that affect the long-term health of the code
cosmetic Policies that only have a superficial effect
complexity Policies that specifically relate to code complexity
security Policies that relate to security issues
tests Policies that are specific to test programs
Any Policy may fit into multiple themes. Say "perlcritic -list"
to get a listing of all available Policies and the themes that are associated with each one. You can also change the theme for any Policy in your .perlcriticrc
file. See the "CONFIGURATION" section for more information about that.
Using the -theme
option, you can create an arbitrarily complex rule that determines which Policies will be loaded. Precedence is the same as regular Perl code, and you can use parentheses to enforce precedence as well. Supported operators are:
Operator Alternative Example
-----------------------------------------------------------------
&& and 'pbp && core'
|| or 'pbp || (bugs && security)'
! not 'pbp && ! (portability || complexity)'
Theme names are case-insensitive. If the -theme
is set to an empty string, then it evaluates as true all Policies.
BENDING THE RULES
Perl::Critic takes a hard-line approach to your code: either you comply or you don't. In the real world, it is not always practical (nor even possible) to fully comply with coding standards. In such cases, it is wise to show that you are knowingly violating the standards and that you have a Damn Good Reason (DGR) for doing so.
To help with those situations, you can direct Perl::Critic to ignore certain lines or blocks of code by using annotations:
require 'LegacyLibaray1.pl'; ## no critic
require 'LegacyLibrary2.pl'; ## no critic
for my $element (@list) {
## no critic
$foo = ""; #Violates 'ProhibitEmptyQuotes'
$barf = bar() if $foo; #Violates 'ProhibitPostfixControls'
#Some more evil code...
## use critic
#Some good code...
do_something($_);
}
The "## no critic"
annotations direct Perl::Critic to ignore the remaining lines of code until a "## use critic"
annotation is found. If the "## no critic"
annotation is on the same line as a code statement, then only that line of code is overlooked. To direct perlcritic to ignore the "## no critic"
annotations, use the --force
option.
A bare "## no critic"
annotation disables all the active Policies. If you wish to disable only specific Policies, add a list of Policy names as arguments, just as you would for the "no strict"
or "no warnings"
pragmas. For example, this would disable the ProhibitEmptyQuotes
and ProhibitPostfixControls
policies until the end of the block or until the next "## use critic"
annotation (whichever comes first):
## no critic (EmptyQuotes, PostfixControls)
# Now exempt from ValuesAndExpressions::ProhibitEmptyQuotes
$foo = "";
# Now exempt ControlStructures::ProhibitPostfixControls
$barf = bar() if $foo;
# Still subjected to ValuesAndExpression::RequireNumberSeparators
$long_int = 10000000000;
Since the Policy names are matched against the "## no critic"
arguments as regular expressions, you can abbreviate the Policy names or disable an entire family of Policies in one shot like this:
## no critic (NamingConventions)
# Now exempt from NamingConventions::Capitalization
my $camelHumpVar = 'foo';
# Now exempt from NamingConventions::Capitalization
sub camelHumpSub {}
The argument list must be enclosed in parentheses or brackets and must contain one or more comma-separated barewords (e.g. don't use quotes). The "## no critic"
annotations can be nested, and Policies named by an inner annotation will be disabled along with those already disabled an outer annotation.
Some Policies like Subroutines::ProhibitExcessComplexity
apply to an entire block of code. In those cases, the "## no critic"
annotation must appear on the line where the violation is reported. For example:
sub complicated_function { ## no critic (ProhibitExcessComplexity)
# Your code here...
}
Policies such as Documentation::RequirePodSections
apply to the entire document, in which case violations are reported at line 1.
Use this feature wisely. "## no critic"
annotations should be used in the smallest possible scope, or only on individual lines of code. And you should always be as specific as possible about which Policies you want to disable (i.e. never use a bare "## no critic"
). If Perl::Critic complains about your code, try and find a compliant solution before resorting to this feature.
THE Perl::Critic PHILOSOPHY
Coding standards are deeply personal and highly subjective. The goal of Perl::Critic is to help you write code that conforms with a set of best practices. Our primary goal is not to dictate what those practices are, but rather, to implement the practices discovered by others. Ultimately, you make the rules -- Perl::Critic is merely a tool for encouraging consistency. If there is a policy that you think is important or that we have overlooked, we would be very grateful for contributions, or you can simply load your own private set of policies into Perl::Critic.
EXTENDING THE CRITIC
The modular design of Perl::Critic is intended to facilitate the addition of new Policies. You'll need to have some understanding of PPI, but most Policy modules are pretty straightforward and only require about 20 lines of code. Please see the Perl::Critic::DEVELOPER file included in this distribution for a step-by-step demonstration of how to create new Policy modules.
If you develop any new Policy modules, feel free to send them to <team@perlcritic.com>
and I'll be happy to consider putting them into the Perl::Critic distribution. Or if you would like to work on the Perl::Critic project directly, you can fork our repository at https://github.com/Perl-Critic/Perl-Critic.git.
The Perl::Critic team is also available for hire. If your organization has its own coding standards, we can create custom Policies to enforce your local guidelines. Or if your code base is prone to a particular defect pattern, we can design Policies that will help you catch those costly defects before they go into production. To discuss your needs with the Perl::Critic team, just contact <team@perlcritic.com>
.
PREREQUISITES
Perl::Critic requires the following modules:
CONTACTING THE DEVELOPMENT TEAM
You are encouraged to subscribe to the public mailing list at https://groups.google.com/d/forum/perl-critic. At least one member of the development team is usually hanging around in irc://irc.perl.org/#perlcritic and you can follow Perl::Critic on Twitter, at https://twitter.com/perlcritic.
SEE ALSO
There are a number of distributions of additional Policies available. A few are listed here:
These distributions enable you to use Perl::Critic in your unit tests:
Test::Perl::Critic::Progressive
There is also a distribution that will install all the Perl::Critic related modules known to the development team:
BUGS
Scrutinizing Perl code is hard for humans, let alone machines. If you find any bugs, particularly false-positives or false-negatives from a Perl::Critic::Policy, please submit them at https://github.com/Perl-Critic/Perl-Critic/issues. Thanks.
CREDITS
Adam Kennedy - For creating PPI, the heart and soul of Perl::Critic.
Damian Conway - For writing Perl Best Practices, finally :)
Chris Dolan - For contributing the best features and Policy modules.
Andy Lester - Wise sage and master of all-things-testing.
Elliot Shank - The self-proclaimed quality freak.
Giuseppe Maxia - For all the great ideas and positive encouragement.
and Sharon, my wife - For putting up with my all-night code sessions.
Thanks also to the Perl Foundation for providing a grant to support Chris Dolan's project to implement twenty PBP policies. http://www.perlfoundation.org/april_1_2007_new_grant_awards
Thanks also to this incomplete laundry list of folks who have contributed to Perl::Critic in some way: Gregory Oschwald, Mike O'Regan, Tom Hukins, Omer Gazit, Evan Zacks, Paul Howarth, Sawyer X, Christian Walde, Dave Rolsky, Jakub Wilk, Roy Ivy III, Oliver Trosien, Glenn Fowler, Matt Creenan, Alex Balhatchet, Sebastian Paaske Tørholm, Stuart A Johnston, Dan Book, Steven Humphrey, James Raspass, Nick Tonkin, Harrison Katz, Douglas Sims, Mark Fowler, Alan Berndt, Neil Bowers, Sergey Romanov, Gabor Szabo, Graham Knop, Mike Eldridge, David Steinbrunner, Kirk Kimmel, Guillaume Aubert, Dave Cross, Anirvan Chatterjee, Todd Rinaldo, Graham Ollis, Karen Etheridge, Jonas Brømsø, Olaf Alders, Jim Keenan, Slaven Rezić, Szymon Nieznański.
AUTHOR
Jeffrey Ryan Thalhammer jeff@imaginative-software.com
COPYRIGHT
Copyright (c) 2005-2018 Imaginative Software Systems. All rights reserved.
This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. The full text of this license can be found in the LICENSE file included with this module.
Author: Perl-Critic
Source Code: https://github.com/Perl-Critic/Perl-Critic
License: View license
1659004860
Asset Sync
Synchronises Assets between Rails and S3.
Asset Sync is built to run with the new Rails Asset Pipeline feature introduced in Rails 3.1. After you run bundle exec rake assets:precompile your assets will be synchronised to your S3 bucket, optionally deleting unused files and only uploading the files it needs to.
This was initially built and is intended to work on Heroku but can work on any platform.
Upgraded from 1.x? Read UPGRADING.md
Since 2.x, Asset Sync depends on gem fog-core
instead of fog
.
This is due to fog
is including many unused storage provider gems as its dependencies.
Asset Sync has no idea about what provider will be used,
so you are responsible for bundling the right gem for the provider to be used.
In your Gemfile:
gem "asset_sync"
gem "fog-aws"
Or, to use Azure Blob storage, configure as this.
gem "asset_sync"
gem "gitlab-fog-azure-rm"
# This gem seems unmaintianed
# gem "fog-azure-rm"
To use Backblaze B2, insert these.
gem "asset_sync"
gem "fog-backblaze"
It's possible to improve asset:precompile time if you are using Rails 3.2.x the main source of which being compilation of non-digest assets.
turbo-sprockets-rails3 solves this by only compiling digest assets. Thus cutting compile time in half.
NOTE: It will be deprecated in Rails 4 as sprockets-rails has been extracted out of Rails and will only compile digest assets by default.
Configure config/environments/production.rb to use Amazon S3 as the asset host and ensure precompiling is enabled.
#config/environments/production.rb
config.action_controller.asset_host = "//#{ENV['FOG_DIRECTORY']}.s3.amazonaws.com"
Or, to use Google Storage Cloud, configure as this.
#config/environments/production.rb
config.action_controller.asset_host = "//#{ENV['FOG_DIRECTORY']}.storage.googleapis.com"
Or, to use Azure Blob storage, configure as this.
#config/environments/production.rb
config.action_controller.asset_host = "//#{ENV['AZURE_STORAGE_ACCOUNT_NAME']}.blob.core.windows.net/#{ENV['FOG_DIRECTORY']}"
Or, to use Backblaze B2, configure as this.
#config/environments/production.rb
config.action_controller.asset_host = "//f000.backblazeb2.com/file/#{ENV['FOG_DIRECTORY']}"
On HTTPS: the exclusion of any protocol in the asset host declaration above will allow browsers to choose the transport mechanism on the fly. So if your application is available under both HTTP and HTTPS the assets will be served to match.
The only caveat with this is that your S3 bucket name must not contain any periods so, mydomain.com.s3.amazonaws.com for example would not work under HTTPS as SSL certificates from Amazon would interpret our bucket name as not a subdomain of s3.amazonaws.com, but a multi level subdomain. To avoid this don't use a period in your subdomain or switch to the other style of S3 URL.
config.action_controller.asset_host = "//s3.amazonaws.com/#{ENV['FOG_DIRECTORY']}"
Or, to use Google Storage Cloud, configure as this.
config.action_controller.asset_host = "//storage.googleapis.com/#{ENV['FOG_DIRECTORY']}"
Or, to use Azure Blob storage, configure as this.
#config/environments/production.rb
config.action_controller.asset_host = "//#{ENV['AZURE_STORAGE_ACCOUNT_NAME']}.blob.core.windows.net/#{ENV['FOG_DIRECTORY']}"
On non default S3 bucket region: If your bucket is set to a region that is not the default US Standard (us-east-1) you must use the first style of url //#{ENV['FOG_DIRECTORY']}.s3.amazonaws.com
or amazon will return a 301 permanently moved when assets are requested. Note the caveat above about bucket names and periods.
If you wish to have your assets sync to a sub-folder of your bucket instead of into the root add the following to your production.rb
file
# store assets in a 'folder' instead of bucket root
config.assets.prefix = "/production/assets"
Also, ensure the following are defined (in production.rb or application.rb)
Additionally, if you depend on any configuration that is setup in your initializers
you will need to ensure that
AssetSync supports the following methods of configuration.
Using the Built-in Initializer is the default method and is supposed to be used with environment variables. It's the recommended approach for deployments on Heroku.
If you need more control over configuration you will want to use a custom rails initializer.
Configuration using a YAML file (a common strategy for Capistrano deployments) is also supported.
The recommend way to configure asset_sync is by using environment variables however it's up to you, it will work fine if you hard code them too. The main reason why using environment variables is recommended is so your access keys are not checked into version control.
The Built-in Initializer will configure AssetSync based on the contents of your environment variables.
Add your configuration details to heroku
heroku config:add AWS_ACCESS_KEY_ID=xxxx
heroku config:add AWS_SECRET_ACCESS_KEY=xxxx
heroku config:add FOG_DIRECTORY=xxxx
heroku config:add FOG_PROVIDER=AWS
# and optionally:
heroku config:add FOG_REGION=eu-west-1
heroku config:add ASSET_SYNC_GZIP_COMPRESSION=true
heroku config:add ASSET_SYNC_MANIFEST=true
heroku config:add ASSET_SYNC_EXISTING_REMOTE_FILES=keep
Or add to a traditional unix system
export AWS_ACCESS_KEY_ID=xxxx
export AWS_SECRET_ACCESS_KEY=xxxx
export FOG_DIRECTORY=xxxx
Rackspace configuration is also supported
heroku config:add RACKSPACE_USERNAME=xxxx
heroku config:add RACKSPACE_API_KEY=xxxx
heroku config:add FOG_DIRECTORY=xxxx
heroku config:add FOG_PROVIDER=Rackspace
Google Storage Cloud configuration is supported as well. The preferred option is using the GCS JSON API which requires that you create an appropriate service account, generate the signatures and make them accessible to asset sync at the prescribed location
heroku config:add FOG_PROVIDER=Google
heroku config:add GOOGLE_PROJECT=xxxx
heroku config:add GOOGLE_JSON_KEY_LOCATION=xxxx
heroku config:add FOG_DIRECTORY=xxxx
If using the S3 API the following config is required
heroku config:add FOG_PROVIDER=Google
heroku config:add GOOGLE_STORAGE_ACCESS_KEY_ID=xxxx
heroku config:add GOOGLE_STORAGE_SECRET_ACCESS_KEY=xxxx
heroku config:add FOG_DIRECTORY=xxxx
The Built-in Initializer also sets the AssetSync default for existing_remote_files to keep.
If you want to enable some of the advanced configuration options you will want to create your own initializer.
Run the included Rake task to generate a starting point.
rails g asset_sync:install --provider=Rackspace
rails g asset_sync:install --provider=AWS
rails g asset_sync:install --provider=AzureRM
rails g asset_sync:install --provider=Backblaze
The generator will create a Rails initializer at config/initializers/asset_sync.rb
.
AssetSync.configure do |config|
config.fog_provider = 'AWS'
config.fog_directory = ENV['FOG_DIRECTORY']
config.aws_access_key_id = ENV['AWS_ACCESS_KEY_ID']
config.aws_secret_access_key = ENV['AWS_SECRET_ACCESS_KEY']
config.aws_session_token = ENV['AWS_SESSION_TOKEN'] if ENV.key?('AWS_SESSION_TOKEN')
# Don't delete files from the store
# config.existing_remote_files = 'keep'
#
# Increase upload performance by configuring your region
# config.fog_region = 'eu-west-1'
#
# Set `public` option when uploading file depending on value,
# Setting to "default" makes asset sync skip setting the option
# Possible values: true, false, "default" (default: true)
# config.fog_public = true
#
# Change AWS signature version. Default is 4
# config.aws_signature_version = 4
#
# Change canned ACL of uploaded object. Default is unset. Will override fog_public if set.
# Choose from: private | public-read | public-read-write | aws-exec-read |
# authenticated-read | bucket-owner-read | bucket-owner-full-control
# config.aws_acl = nil
#
# Change host option in fog (only if you need to)
# config.fog_host = 's3.amazonaws.com'
#
# Change port option in fog (only if you need to)
# config.fog_port = "9000"
#
# Use http instead of https.
# config.fog_scheme = 'http'
#
# Automatically replace files with their equivalent gzip compressed version
# config.gzip_compression = true
#
# Use the Rails generated 'manifest.yml' file to produce the list of files to
# upload instead of searching the assets directory.
# config.manifest = true
#
# Upload the manifest file also.
# config.include_manifest = false
#
# Upload files concurrently
# config.concurrent_uploads = false
#
# Number of threads when concurrent_uploads is enabled
# config.concurrent_uploads_max_threads = 10
#
# Path to cache file to skip scanning remote
# config.remote_file_list_cache_file_path = './.asset_sync_remote_file_list_cache.json'
#
# Fail silently. Useful for environments such as Heroku
# config.fail_silently = true
#
# Log silently. Default is `true`. But you can set it to false if more logging message are preferred.
# Logging messages are sent to `STDOUT` when `log_silently` is falsy
# config.log_silently = true
#
# Allow custom assets to be cacheable. Note: The base filename will be matched
# If you have an asset with name `app.0b1a4cd3.js`, only `app.0b1a4cd3` will need to be matched
# only one of `cache_asset_regexp` or `cache_asset_regexps` is allowed.
# config.cache_asset_regexp = /\.[a-f0-9]{8}$/i
# config.cache_asset_regexps = [ /\.[a-f0-9]{8}$/i, /\.[a-f0-9]{20}$/i ]
end
Run the included Rake task to generate a starting point.
rails g asset_sync:install --use-yml --provider=Rackspace
rails g asset_sync:install --use-yml --provider=AWS
rails g asset_sync:install --use-yml --provider=AzureRM
rails g asset_sync:install --use-yml --provider=Backblaze
The generator will create a YAML file at config/asset_sync.yml
.
defaults: &defaults
fog_provider: "AWS"
fog_directory: "rails-app-assets"
aws_access_key_id: "<%= ENV['AWS_ACCESS_KEY_ID'] %>"
aws_secret_access_key: "<%= ENV['AWS_SECRET_ACCESS_KEY'] %>"
# To use AWS reduced redundancy storage.
# aws_reduced_redundancy: true
#
# You may need to specify what region your storage bucket is in
# fog_region: "eu-west-1"
#
# Change AWS signature version. Default is 4
# aws_signature_version: 4
#
# Change canned ACL of uploaded object. Default is unset. Will override fog_public if set.
# Choose from: private | public-read | public-read-write | aws-exec-read |
# authenticated-read | bucket-owner-read | bucket-owner-full-control
# aws_acl: null
#
# Change host option in fog (only if you need to)
# fog_host: "s3.amazonaws.com"
#
# Use http instead of https. Default should be "https" (at least for fog-aws)
# fog_scheme: "http"
existing_remote_files: keep # Existing pre-compiled assets on S3 will be kept
# To delete existing remote files.
# existing_remote_files: delete
# To ignore existing remote files and overwrite.
# existing_remote_files: ignore
# Automatically replace files with their equivalent gzip compressed version
# gzip_compression: true
# Fail silently. Useful for environments such as Heroku
# fail_silently: true
# Always upload. Useful if you want to overwrite specific remote assets regardless of their existence
# eg: Static files in public often reference non-fingerprinted application.css
# note: You will still need to expire them from the CDN's edge cache locations
# always_upload: ['application.js', 'application.css', !ruby/regexp '/application-/\d{32}\.css/']
# Ignored files. Useful if there are some files that are created dynamically on the server and you don't want to upload on deploy.
# ignored_files: ['ignore_me.js', !ruby/regexp '/ignore_some/\d{32}\.css/']
# Allow custom assets to be cacheable. Note: The base filename will be matched
# If you have an asset with name "app.0b1a4cd3.js", only "app.0b1a4cd3" will need to be matched
# cache_asset_regexps: ['cache_me.js', !ruby/regexp '/cache_some\.\d{8}\.css/']
development:
<<: *defaults
test:
<<: *defaults
production:
<<: *defaults
Most AssetSync configuration can be modified directly using environment variables with the Built-in initializer. e.g.
AssetSync.config.fog_provider == ENV['FOG_PROVIDER']
Simply upcase the ruby attribute names to get the equivalent environment variable to set. The only exception to that rule are the internal AssetSync config variables, they must be prepended with ASSET_SYNC_*
e.g.
AssetSync.config.gzip_compression == ENV['ASSET_SYNC_GZIP_COMPRESSION']
'keep', 'delete', 'ignore'
) what to do with previously precompiled files. default: 'keep'
true, false
) when enabled, will automatically replace files that have a gzip compressed equivalent with the compressed version. default: 'false'
true, false
) when enabled, will use the manifest.yml
generated by Rails to get the list of local files to upload. experimental. default: 'false'
true, false
) when enabled, will upload the manifest.yml
generated by Rails. default: 'false'
true, false
) when enabled, will upload the files in different Threads, this greatly improves the upload speed. default: 'false'
10
nil
true, false
) when false, will disable asset sync. default: 'true'
(enabled)['ignore_me.js', %r(ignore_some/\d{32}\.css)]
Useful if there are some files that are created dynamically on the server and you don't want to upload on deploy default: []
['cache_me.js', %r(cache_some\.\d{8}\.css)]
Useful if there are some files that are added to sprockets assets list and need to be set as 'Cacheable' on uploaded server. Only rails compiled regexp is matched internally default: []
Config Method add_local_file_paths
Adding local files by providing a block:
AssetSync.configure do |config|
# The block should return an array of file paths
config.add_local_file_paths do
# Any code that returns paths of local asset files to be uploaded
# Like Webpacker
public_root = Rails.root.join("public")
Dir.chdir(public_root) do
packs_dir = Webpacker.config.public_output_path.relative_path_from(public_root)
Dir[File.join(packs_dir, '/**/**')]
end
end
end
The blocks are run when local files are being scanned and uploaded
Config Method file_ext_to_mime_type_overrides
It's reported that mime-types
3.x returns application/ecmascript
instead of application/javascript
Such change of mime type might cause some CDN to disable asset compression
So this gem has defined a default override for file ext js
to be mapped to application/javascript
by default
To customize the overrides:
AssetSync.configure do |config|
# Clear the default overrides
config.file_ext_to_mime_type_overrides.clear
# Add/Edit overrides
# Will call `#to_s` for inputs
config.file_ext_to_mime_type_overrides.add(:js, :"application/x-javascript")
end
The blocks are run when local files are being scanned and uploaded
When using the JSON API
When using the S3 API
https://lon.identity.api.rackspacecloud.com/v2.0
If you are using anything other than the US buckets with S3 then you'll want to set the region. For example with an EU bucket you could set the following environment variable.
heroku config:add FOG_REGION=eu-west-1
Or via a custom initializer
AssetSync.configure do |config|
# ...
config.fog_region = 'eu-west-1'
end
Or via YAML
production: # ... fog_region: 'eu-west-1'
Amazon has switched to the more secure IAM User security policy model. When generating a user & policy for asset_sync you must ensure the policy has the following permissions, or you'll see the error:
Expected(200) <=> Actual(403 Forbidden)
IAM User Policy Example with minimum require permissions (replace bucket_name
with your bucket):
{
"Statement": [
{
"Action": "s3:ListBucket",
"Effect": "Allow",
"Resource": "arn:aws:s3:::bucket_name"
},
{
"Action": "s3:PutObject*",
"Effect": "Allow",
"Resource": "arn:aws:s3:::bucket_name/*"
}
]
}
If you want to use IAM roles you must set config.aws_iam_roles = true
in your initializers.
AssetSync.configure do |config|
# ...
config.aws_iam_roles = true
end
With the gzip_compression
option enabled, when uploading your assets. If a file has a gzip compressed equivalent we will replace that asset with the compressed version and sets the correct headers for S3 to serve it. For example, if you have a file master.css and it was compressed to master.css.gz we will upload the .gz file to S3 in place of the uncompressed file.
If the compressed file is actually larger than the uncompressed file we will ignore this rule and upload the standard uncompressed version.
With the fail_silently
option enabled, when running rake assets:precompile
AssetSync will never throw an error due to missing configuration variables.
With the new user_env_compile feature of Heroku (see above), this is no longer required or recommended. Yet was added for the following reasons:
With Rails 3.1 on the Heroku cedar stack, the deployment process automatically runs
rake assets:precompile
. If you are using ENV variable style configuration. Due to the methods with which Heroku compile slugs, there will be an error raised by asset_sync as the environment is not available. This causes heroku to install therails31_enable_runtime_asset_compilation
plugin which is not necessary when using asset_sync and also massively slows down the first incoming requests to your app.
To prevent this part of the deploy from failing (asset_sync raising a config error), but carry on as normal set
fail_silently
to true in your configuration and ensure to runheroku run rake assets:precompile
after deploy.
A rake task is included within the asset_sync gem to perform the sync:
namespace :assets do
desc "Synchronize assets to S3"
task :sync => :environment do
AssetSync.sync
end
end
If AssetSync.config.run_on_precompile
is true
(default), then assets will be uploaded to S3 automatically after the assets:precompile
rake task is invoked:
if Rake::Task.task_defined?("assets:precompile:nondigest")
Rake::Task["assets:precompile:nondigest"].enhance do
Rake::Task["assets:sync"].invoke if defined?(AssetSync) && AssetSync.config.run_on_precompile
end
else
Rake::Task["assets:precompile"].enhance do
Rake::Task["assets:sync"].invoke if defined?(AssetSync) && AssetSync.config.run_on_precompile
end
end
You can disable this behavior by setting AssetSync.config.run_on_precompile = false
.
You can use the gem with any Rack application, but you must specify two additional options; prefix
and public_path
.
AssetSync.configure do |config|
config.fog_provider = 'AWS'
config.fog_directory = ENV['FOG_DIRECTORY']
config.aws_access_key_id = ENV['AWS_ACCESS_KEY_ID']
config.aws_secret_access_key = ENV['AWS_SECRET_ACCESS_KEY']
config.prefix = 'assets'
# Can be a `Pathname` or `String`
# Will be converted into an `Pathname`
# If relative, will be converted into an absolute path
# via `::Rails.root` or `::Dir.pwd`
config.public_path = Pathname('./public')
end
Then manually call AssetSync.sync
at the end of your asset precompilation task.
namespace :assets do
desc 'Precompile assets'
task :precompile do
target = Pathname('./public/assets')
manifest = Sprockets::Manifest.new(sprockets, './public/assets/manifest.json')
sprockets.each_logical_path do |logical_path|
if (!File.extname(logical_path).in?(['.js', '.css']) || logical_path =~ /application\.(css|js)$/) && asset = sprockets.find_asset(logical_path)
filename = target.join(logical_path)
FileUtils.mkpath(filename.dirname)
puts "Write asset: #{filename}"
asset.write_to(filename)
manifest.compile(logical_path)
end
end
AssetSync.sync
end
end
run_on_precompile
:AssetSync.configure do |config|
# Disable automatic run on precompile in order to attach to webpacker rake task
config.run_on_precompile = false
# The block should return an array of file paths
config.add_local_file_paths do
# Support webpacker assets
public_root = Rails.root.join("public")
Dir.chdir(public_root) do
packs_dir = Webpacker.config.public_output_path.relative_path_from(public_root)
Dir[File.join(packs_dir, '/**/**')]
end
end
end
asset_sync.rake
in your lib/tasks
directory that enhances the correct task, otherwise asset_sync runs before webpacker:compile
does:if defined?(AssetSync)
Rake::Task['webpacker:compile'].enhance do
Rake::Task["assets:sync"].invoke
end
end
By adding local files outside the normal Rails assets
directory, the uploading part works, however checking that the asset was previously uploaded is not working because asset_sync is only fetching the files in the assets
directory on the remote bucket. This will mean additional time used to upload the same assets again on every precompilation.
Make sure you have a .env file with these details:-
# for AWS provider
AWS_ACCESS_KEY_ID=<yourkeyid>
AWS_SECRET_ACCESS_KEY=<yoursecretkey>
FOG_DIRECTORY=<yourbucket>
FOG_REGION=<youbucketregion>
# for AzureRM provider
AZURE_STORAGE_ACCOUNT_NAME=<youraccountname>
AZURE_STORAGE_ACCESS_KEY=<youraccesskey>
FOG_DIRECTORY=<yourcontainer>
FOG_REGION=<yourcontainerregion>
Make sure the bucket has read/write permissions. Then to run the tests:-
foreman run rake
Inspired by:
MIT License. Copyright 2011-2013 Rumble Labs Ltd. rumblelabs.com
Author: AssetSync
Source code: https://github.com/AssetSync/asset_sync
License:
1654588030
TypeScript Deep Dive
I've been looking at the issues that turn up commonly when people start using TypeScript. This is based on the lessons from Stack Overflow / DefinitelyTyped and general engagement with the TypeScript community. You can follow for updates and don't forget to ★ on GitHub 🌹
If you are here to read the book online get started.
Book is completely free so you can copy paste whatever you want without requiring permission. If you have a translation you want me to link here. Send a PR.
You can also download one of the Epub, Mobi, or PDF formats from the actions tab by clicking on the latest build run. You will find the files in the artifacts section.
All the amazing contributors 🌹
Share URL: https://basarat.gitbook.io/typescript/
Author: Basarat
Source Code: https://github.com/basarat/typescript-book/
License: View license
1624653660
A useful tool several businesses implement for answering questions that potential customers may have is a chatbot. Many programming languages give web designers several ways on how to make a chatbot for their websites. They are capable of answering basic questions for visitors and offer innovation for businesses.
With the help of programming languages, it is possible to create a chatbot from the ground up to satisfy someone’s needs.
Before building a chatbot, it is ideal for web designers to determine how it will function on a website. Several chatbot duties center around fulfilling customers’ needs and questions or compiling and optimizing data via transactions.
Some benefits of implementing chatbots include:
Some programmers may choose to design a chatbox to function through predefined answers based on the questions customers may input or function by adapting and learning via human input.
#chatbots #latest news #the best way to build a chatbot in 2021 #build #build a chatbot #best way to build a chatbot