hullapp 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.DS_Store +0 -0
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +66 -0
- data/Rakefile +1 -0
- data/bin/hull +15 -0
- data/hullapp.gemspec +27 -0
- data/lib/hull.rb +6 -0
- data/lib/hull/cli.rb +124 -0
- data/lib/hull/version.rb +3 -0
- data/templates/.DS_Store +0 -0
- data/templates/hullenv.tt +4 -0
- data/templates/ruby/.gitignore +7 -0
- data/templates/ruby/.powenv +8 -0
- data/templates/ruby/.powrc +5 -0
- data/templates/ruby/.rvmrc.tt +1 -0
- data/templates/ruby/Gemfile +50 -0
- data/templates/ruby/Guardfile +8 -0
- data/templates/ruby/Procfile +4 -0
- data/templates/ruby/README.md +198 -0
- data/templates/ruby/Rakefile +40 -0
- data/templates/ruby/application/assets.rb +7 -0
- data/templates/ruby/application/assets/images/icons/facebook.png +0 -0
- data/templates/ruby/application/assets/images/icons/twitter.png +0 -0
- data/templates/ruby/application/assets/images/socialmedia/app-store.png +0 -0
- data/templates/ruby/application/assets/images/socialmedia/dribbble.png +0 -0
- data/templates/ruby/application/assets/images/socialmedia/facebook.png +0 -0
- data/templates/ruby/application/assets/images/socialmedia/flickr.png +0 -0
- data/templates/ruby/application/assets/images/socialmedia/forrst.png +0 -0
- data/templates/ruby/application/assets/images/socialmedia/foursquare.png +0 -0
- data/templates/ruby/application/assets/images/socialmedia/github.png +0 -0
- data/templates/ruby/application/assets/images/socialmedia/google-plus.png +0 -0
- data/templates/ruby/application/assets/images/socialmedia/google.png +0 -0
- data/templates/ruby/application/assets/images/socialmedia/instagram.png +0 -0
- data/templates/ruby/application/assets/images/socialmedia/linkedin.png +0 -0
- data/templates/ruby/application/assets/images/socialmedia/skype.png +0 -0
- data/templates/ruby/application/assets/images/socialmedia/social-email.png +0 -0
- data/templates/ruby/application/assets/images/socialmedia/social-rss.png +0 -0
- data/templates/ruby/application/assets/images/socialmedia/spotify.png +0 -0
- data/templates/ruby/application/assets/images/socialmedia/tumblr.png +0 -0
- data/templates/ruby/application/assets/images/socialmedia/twitter-2.png +0 -0
- data/templates/ruby/application/assets/images/socialmedia/twitter.png +0 -0
- data/templates/ruby/application/assets/images/socialmedia/vimeo.png +0 -0
- data/templates/ruby/application/assets/images/socialmedia/youtube.png +0 -0
- data/templates/ruby/application/assets/javascripts/app.js +11 -0
- data/templates/ruby/application/assets/javascripts/main.coffee +17 -0
- data/templates/ruby/application/assets/javascripts/template.js.erb +1 -0
- data/templates/ruby/application/assets/stylesheets/partials/_base.scss +17 -0
- data/templates/ruby/application/assets/stylesheets/partials/_boilerplate.scss +291 -0
- data/templates/ruby/application/assets/stylesheets/partials/_colors.scss +0 -0
- data/templates/ruby/application/assets/stylesheets/partials/_fonts.scss +1 -0
- data/templates/ruby/application/assets/stylesheets/partials/_h5bp.scss +298 -0
- data/templates/ruby/application/assets/stylesheets/partials/_layout.scss +12 -0
- data/templates/ruby/application/assets/stylesheets/partials/_normalize.scss +504 -0
- data/templates/ruby/application/assets/stylesheets/partials/_variables.scss +28 -0
- data/templates/ruby/application/assets/stylesheets/style.scss +16 -0
- data/templates/ruby/application/assets/templates/hello.hbs +1 -0
- data/templates/ruby/application/compass.rb +27 -0
- data/templates/ruby/application/core.rb +15 -0
- data/templates/ruby/application/core_extensions/blank.rb +111 -0
- data/templates/ruby/application/core_extensions/hash.rb +34 -0
- data/templates/ruby/application/core_extensions/sprockets.rb +74 -0
- data/templates/ruby/application/core_extensions/try.rb +57 -0
- data/templates/ruby/application/helpers.rb +121 -0
- data/templates/ruby/application/helpers/form_tag_helpers.rb +127 -0
- data/templates/ruby/application/helpers/notification_helpers.rb +20 -0
- data/templates/ruby/application/helpers/run_later.rb +111 -0
- data/templates/ruby/application/settings.rb +8 -0
- data/templates/ruby/application/views/demo.erb +27 -0
- data/templates/ruby/application/views/index.erb +9 -0
- data/templates/ruby/application/views/layout.erb +45 -0
- data/templates/ruby/application/workers.rb +0 -0
- data/templates/ruby/config.ru +84 -0
- data/templates/ruby/config/settings.yml +53 -0
- data/templates/ruby/config/sidekiq.yml +11 -0
- data/templates/ruby/config/unicorn.rb +91 -0
- data/templates/ruby/public/.htaccess +538 -0
- data/templates/ruby/public/404.html +157 -0
- data/templates/ruby/public/apple-touch-icon-114x114-precomposed.png +0 -0
- data/templates/ruby/public/apple-touch-icon-144x144-precomposed.png +0 -0
- data/templates/ruby/public/apple-touch-icon-57x57-precomposed.png +0 -0
- data/templates/ruby/public/apple-touch-icon-72x72-precomposed.png +0 -0
- data/templates/ruby/public/apple-touch-icon-precomposed.png +0 -0
- data/templates/ruby/public/apple-touch-icon.png +0 -0
- data/templates/ruby/public/crossdomain.xml +15 -0
- data/templates/ruby/public/favicon.ico +0 -0
- data/templates/ruby/public/humans.txt +15 -0
- data/templates/ruby/public/robots.txt +5 -0
- data/templates/ruby/vendor/assets/images/glyphicons-halflings-white.png +0 -0
- data/templates/ruby/vendor/assets/images/glyphicons-halflings.png +0 -0
- data/templates/ruby/vendor/assets/javascripts/backbone.js +1431 -0
- data/templates/ruby/vendor/assets/javascripts/bootstrap.js +2027 -0
- data/templates/ruby/vendor/assets/javascripts/index.js +0 -0
- data/templates/ruby/vendor/assets/javascripts/jquery.js +9227 -0
- data/templates/ruby/vendor/assets/javascripts/modernizr.js +11 -0
- data/templates/ruby/vendor/assets/javascripts/underscore.js +1059 -0
- data/templates/ruby/vendor/assets/javascripts/vendor.js +2 -0
- data/templates/ruby/vendor/assets/stylesheets/bootstrap-responsive.css +1040 -0
- data/templates/ruby/vendor/assets/stylesheets/bootstrap.css +5624 -0
- data/templates/ruby/vendor/assets/stylesheets/vendor.scss +2 -0
- metadata +243 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/* susy config */
|
|
2
|
+
/* see http://susy.oddbird.net/guides/reference/ */
|
|
3
|
+
$total-columns: 12;
|
|
4
|
+
$column-width: 4.5em;
|
|
5
|
+
$gutter-width: 1em;
|
|
6
|
+
$grid-padding: $gutter-width;
|
|
7
|
+
$border-box-sizing: true;
|
|
8
|
+
$base-font-size: 13px;
|
|
9
|
+
$base-line-height: 20px;
|
|
10
|
+
$breakpoint: 0em 45em; /* min-max media query breakpoint */
|
|
11
|
+
$from-direction: left;
|
|
12
|
+
$omega-float: $from-direction;
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
/* column shortcuts */
|
|
16
|
+
$one-third: $total-columns / 3;
|
|
17
|
+
$two-thirds: $one-third * 2;
|
|
18
|
+
$half: $total-columns / 2;
|
|
19
|
+
$one-fourth: $total-columns / 4;
|
|
20
|
+
|
|
21
|
+
/* colors */
|
|
22
|
+
$black: #292724;
|
|
23
|
+
$bg-color: #f3f3f3;
|
|
24
|
+
|
|
25
|
+
/* others */
|
|
26
|
+
$font-size: $base-font-size;
|
|
27
|
+
$line-height: $base-line-height;
|
|
28
|
+
$container-padding: $base-line-height;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
@import 'compass';
|
|
2
|
+
|
|
3
|
+
@import 'partials/fonts';
|
|
4
|
+
@import 'partials/colors';
|
|
5
|
+
@import 'partials/variables';
|
|
6
|
+
@import 'partials/normalize';
|
|
7
|
+
@import 'partials/h5bp';
|
|
8
|
+
@import 'partials/base';
|
|
9
|
+
@import 'partials/layout';
|
|
10
|
+
|
|
11
|
+
@import 'icons/*.png';
|
|
12
|
+
@include all-icons-sprites;
|
|
13
|
+
|
|
14
|
+
$socialmedia_spacing:50px;
|
|
15
|
+
@import 'socialmedia/*.png';
|
|
16
|
+
@include all-socialmedia-sprites;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Hull-o, {{user}}. Welcome !
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Require any additional compass plugins here.
|
|
2
|
+
|
|
3
|
+
# Set this to the root of your project when deployed:
|
|
4
|
+
|
|
5
|
+
project_path = Settings.sprockets['application_dir']
|
|
6
|
+
|
|
7
|
+
images_dir = Settings.paths.images
|
|
8
|
+
sass_dir = Settings.paths.css
|
|
9
|
+
css_dir = Settings.paths.css
|
|
10
|
+
javascripts_dir = Settings.paths.js
|
|
11
|
+
fonts_dir = Settings.paths.fonts
|
|
12
|
+
|
|
13
|
+
# You can select your preferred output style here (can be overridden via the command line):
|
|
14
|
+
output_style = :compressed
|
|
15
|
+
|
|
16
|
+
# To enable relative paths to assets via compass helper functions. Uncomment:
|
|
17
|
+
relative_assets = true
|
|
18
|
+
|
|
19
|
+
# To disable debugging comments that display the original location of your selectors. Uncomment:
|
|
20
|
+
line_comments = false
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
# If you prefer the indented syntax, you might want to regenerate this
|
|
24
|
+
# project again passing --syntax sass, or you can uncomment this:
|
|
25
|
+
# preferred_syntax = :sass
|
|
26
|
+
# and then run:
|
|
27
|
+
# sass-convert -R --from scss --to sass sass scss && rm -rf sass && mv scss sass
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# further requires (models, helpers, core extensions etc. { but not 'middleware' because that should be grabbed up by Rack when appropriate })
|
|
2
|
+
Dir.glob('./application/**/*.rb') do |file|
|
|
3
|
+
require file
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
before do
|
|
7
|
+
# opt into the future
|
|
8
|
+
response['X-UA-Compatible'] = "IE=edge,chrome=1"
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
get '/' do
|
|
12
|
+
@title = Settings.app_title
|
|
13
|
+
@description = Settings.app_title
|
|
14
|
+
erb :index
|
|
15
|
+
end
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# thank you, rails
|
|
2
|
+
class Object
|
|
3
|
+
# An object is blank if it's false, empty, or a whitespace string.
|
|
4
|
+
# For example, "", " ", +nil+, [], and {} are all blank.
|
|
5
|
+
#
|
|
6
|
+
# This simplifies:
|
|
7
|
+
#
|
|
8
|
+
# if address.nil? || address.empty?
|
|
9
|
+
#
|
|
10
|
+
# ...to:
|
|
11
|
+
#
|
|
12
|
+
# if address.blank?
|
|
13
|
+
def blank?
|
|
14
|
+
respond_to?(:empty?) ? empty? : !self
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# An object is present if it's not <tt>blank?</tt>.
|
|
18
|
+
def present?
|
|
19
|
+
!blank?
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Returns object if it's <tt>present?</tt> otherwise returns +nil+.
|
|
23
|
+
# <tt>object.presence</tt> is equivalent to <tt>object.present? ? object : nil</tt>.
|
|
24
|
+
#
|
|
25
|
+
# This is handy for any representation of objects where blank is the same
|
|
26
|
+
# as not present at all. For example, this simplifies a common check for
|
|
27
|
+
# HTTP POST/query parameters:
|
|
28
|
+
#
|
|
29
|
+
# state = params[:state] if params[:state].present?
|
|
30
|
+
# country = params[:country] if params[:country].present?
|
|
31
|
+
# region = state || country || 'US'
|
|
32
|
+
#
|
|
33
|
+
# ...becomes:
|
|
34
|
+
#
|
|
35
|
+
# region = params[:state].presence || params[:country].presence || 'US'
|
|
36
|
+
def presence
|
|
37
|
+
self if present?
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
class NilClass
|
|
42
|
+
# +nil+ is blank:
|
|
43
|
+
#
|
|
44
|
+
# nil.blank? # => true
|
|
45
|
+
#
|
|
46
|
+
def blank?
|
|
47
|
+
true
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
class FalseClass
|
|
52
|
+
# +false+ is blank:
|
|
53
|
+
#
|
|
54
|
+
# false.blank? # => true
|
|
55
|
+
#
|
|
56
|
+
def blank?
|
|
57
|
+
true
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
class TrueClass
|
|
62
|
+
# +true+ is not blank:
|
|
63
|
+
#
|
|
64
|
+
# true.blank? # => false
|
|
65
|
+
#
|
|
66
|
+
def blank?
|
|
67
|
+
false
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
class Array
|
|
72
|
+
# An array is blank if it's empty:
|
|
73
|
+
#
|
|
74
|
+
# [].blank? # => true
|
|
75
|
+
# [1,2,3].blank? # => false
|
|
76
|
+
#
|
|
77
|
+
alias_method :blank?, :empty?
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
class Hash
|
|
81
|
+
# A hash is blank if it's empty:
|
|
82
|
+
#
|
|
83
|
+
# {}.blank? # => true
|
|
84
|
+
# {:key => 'value'}.blank? # => false
|
|
85
|
+
#
|
|
86
|
+
alias_method :blank?, :empty?
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
class String
|
|
90
|
+
# A string is blank if it's empty or contains whitespaces only:
|
|
91
|
+
#
|
|
92
|
+
# "".blank? # => true
|
|
93
|
+
# " ".blank? # => true
|
|
94
|
+
# " something here ".blank? # => false
|
|
95
|
+
#
|
|
96
|
+
def blank?
|
|
97
|
+
self !~ /\S/
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
class Numeric #:nodoc:
|
|
102
|
+
# No number is blank:
|
|
103
|
+
#
|
|
104
|
+
# 1.blank? # => false
|
|
105
|
+
# 0.blank? # => false
|
|
106
|
+
#
|
|
107
|
+
def blank?
|
|
108
|
+
false
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
class Hash
|
|
2
|
+
# converts a Hash to a key value pair for use in a querystring (qs is short for querystring)
|
|
3
|
+
# Also, it uses CGI to escape the strings
|
|
4
|
+
#
|
|
5
|
+
# { :id => 22, :me => 'you sucka!' }.to_qs
|
|
6
|
+
#
|
|
7
|
+
# yields
|
|
8
|
+
#
|
|
9
|
+
# id=22&me=you+sucka%21
|
|
10
|
+
#
|
|
11
|
+
def to_qs
|
|
12
|
+
collect do |key, value|
|
|
13
|
+
"#{ CGI.escape(key.to_s) }=#{ CGI.escape(value.to_s) }"
|
|
14
|
+
end.sort * '&'
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# converts a Hash into an HTML attribute where the key is the attribute and the value is the value.
|
|
18
|
+
# { :id => 'two', :class => 'me', :required => nil }.to_attr
|
|
19
|
+
# yields
|
|
20
|
+
# id="two" class="me" required
|
|
21
|
+
#
|
|
22
|
+
# Really handy for generating markup
|
|
23
|
+
def to_attr
|
|
24
|
+
collect do |key, value|
|
|
25
|
+
if value.is_a? Hash
|
|
26
|
+
value.collect do |k, v|
|
|
27
|
+
"#{key}-#{k}='#{v}'"
|
|
28
|
+
end
|
|
29
|
+
else
|
|
30
|
+
value.nil? ? key.to_s : "#{key}='#{value}'"
|
|
31
|
+
end
|
|
32
|
+
end.join(' ').chomp
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
require 'uglifier'
|
|
2
|
+
require 'handlebars_assets'
|
|
3
|
+
require 'sprockets-sass'
|
|
4
|
+
require 'sprockets-helpers'
|
|
5
|
+
require 'compass'
|
|
6
|
+
|
|
7
|
+
SPROCKETS = Sprockets::Environment.new
|
|
8
|
+
Settings.sprockets['root'] = File.expand_path('../', __FILE__)
|
|
9
|
+
Settings.paths['assets'] = Settings.paths.static
|
|
10
|
+
Settings.paths['assets'].push Settings.paths.js
|
|
11
|
+
Settings.paths['assets'].push Settings.paths.css
|
|
12
|
+
Settings.paths['assets'].push Settings.paths.templates
|
|
13
|
+
Settings.paths['assets'].push Settings.paths.images
|
|
14
|
+
Settings.paths['assets'].push Settings.paths.fonts
|
|
15
|
+
|
|
16
|
+
# Sprockets.register_engine '.hbs', HandlebarsAssets::TiltHandlebars
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def configure_sprockets(opts={})
|
|
20
|
+
searchpaths = []
|
|
21
|
+
%w{ application vendor lib}.each do |dir|
|
|
22
|
+
Settings.sprockets["#{dir}_dir"] = File.join PROJECT_ROOT, dir, '/', Settings.sprockets.assets_prefix
|
|
23
|
+
searchpaths.push Settings.sprockets["#{dir}_dir"]
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# SPROCKETS.css_compressor = Sprockets::Sass::Compressor.new
|
|
27
|
+
SPROCKETS.js_compressor = Uglifier.new(:mangle => true)
|
|
28
|
+
|
|
29
|
+
# setup our paths
|
|
30
|
+
searchpaths.each do |sp|
|
|
31
|
+
Settings.paths['assets'].each do |path|
|
|
32
|
+
SPROCKETS.append_path File.join(sp, path)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
SPROCKETS.append_path HandlebarsAssets.path
|
|
36
|
+
|
|
37
|
+
# configure Compass so it can find images
|
|
38
|
+
Compass.add_project_configuration File.expand_path('compass.rb', File.dirname(File.dirname(__FILE__)))
|
|
39
|
+
|
|
40
|
+
# configure Sprockets::Helpers
|
|
41
|
+
Sprockets::Helpers.configure do |config|
|
|
42
|
+
config.environment = SPROCKETS
|
|
43
|
+
config.prefix = Settings.sprockets.assets_prefix
|
|
44
|
+
config.digest = Settings.sprockets.digest # digests are great for cache busting
|
|
45
|
+
config.manifest = Sprockets::Manifest.new(
|
|
46
|
+
SPROCKETS,
|
|
47
|
+
File.join(PROJECT_ROOT, "public", Settings.sprockets.assets_prefix, 'manifest.json')
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
# clean that thang out
|
|
51
|
+
config.manifest.clean
|
|
52
|
+
|
|
53
|
+
static_files = []
|
|
54
|
+
|
|
55
|
+
searchpaths.each do |sp|
|
|
56
|
+
# scoop up the static assets so they can come along for the party
|
|
57
|
+
Settings.paths.static.each do |asset_dir|
|
|
58
|
+
Dir.glob(File.join(sp, asset_dir, '**', '*')).map do |filepath|
|
|
59
|
+
static_files.push filepath.split('/').last
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# write the digested files out to public/assets (makes it so Nginx can serve them directly)
|
|
65
|
+
if opts[:precompile]==true
|
|
66
|
+
config.manifest.clean(0)
|
|
67
|
+
manifest_contents = Settings.sprockets.precompile.concat(static_files)
|
|
68
|
+
config.manifest.compile(manifest_contents)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# http://www.ruby-doc.org/gems/docs/s/sprockets-2.4.0/Sprockets/Manifest.html
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# thank you again, Rails
|
|
2
|
+
class Object
|
|
3
|
+
# Invokes the method identified by the symbol +method+, passing it any arguments
|
|
4
|
+
# and/or the block specified, just like the regular Ruby <tt>Object#send</tt> does.
|
|
5
|
+
#
|
|
6
|
+
# *Unlike* that method however, a +NoMethodError+ exception will *not* be raised
|
|
7
|
+
# and +nil+ will be returned instead, if the receiving object is a +nil+ object or NilClass.
|
|
8
|
+
#
|
|
9
|
+
# If try is called without a method to call, it will yield any given block with the object.
|
|
10
|
+
#
|
|
11
|
+
# ==== Examples
|
|
12
|
+
#
|
|
13
|
+
# Without +try+
|
|
14
|
+
# @person && @person.name
|
|
15
|
+
# or
|
|
16
|
+
# @person ? @person.name : nil
|
|
17
|
+
#
|
|
18
|
+
# With +try+
|
|
19
|
+
# @person.try(:name)
|
|
20
|
+
#
|
|
21
|
+
# +try+ also accepts arguments and/or a block, for the method it is trying
|
|
22
|
+
# Person.try(:find, 1)
|
|
23
|
+
# @people.try(:collect) {|p| p.name}
|
|
24
|
+
#
|
|
25
|
+
# Without a method argument try will yield to the block unless the receiver is nil.
|
|
26
|
+
# @person.try { |p| "#{p.first_name} #{p.last_name}" }
|
|
27
|
+
#--
|
|
28
|
+
# +try+ behaves like +Object#send+, unless called on +NilClass+.
|
|
29
|
+
def try(*a, &b)
|
|
30
|
+
if a.empty? && block_given?
|
|
31
|
+
yield self
|
|
32
|
+
elsif !a.empty? && !respond_to?(a.first)
|
|
33
|
+
nil
|
|
34
|
+
else
|
|
35
|
+
__send__(*a, &b)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
class NilClass
|
|
41
|
+
# Calling +try+ on +nil+ always returns +nil+.
|
|
42
|
+
# It becomes specially helpful when navigating through associations that may return +nil+.
|
|
43
|
+
#
|
|
44
|
+
# === Examples
|
|
45
|
+
#
|
|
46
|
+
# nil.try(:name) # => nil
|
|
47
|
+
#
|
|
48
|
+
# Without +try+
|
|
49
|
+
# @person && !@person.children.blank? && @person.children.first.name
|
|
50
|
+
#
|
|
51
|
+
# With +try+
|
|
52
|
+
# @person.try(:children).try(:first).try(:name)
|
|
53
|
+
def try(*args)
|
|
54
|
+
nil
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# = Helpers =
|
|
2
|
+
helpers do
|
|
3
|
+
# helpers
|
|
4
|
+
include Sprockets::Helpers
|
|
5
|
+
|
|
6
|
+
alias_method :h, :escape_html
|
|
7
|
+
alias_method :e, :escape
|
|
8
|
+
|
|
9
|
+
# overrides Sinatra's defaults to allow calling like this:
|
|
10
|
+
# erb 'partials/flash'
|
|
11
|
+
#
|
|
12
|
+
# instead of
|
|
13
|
+
# erb 'partials/flash'.to_sym
|
|
14
|
+
#
|
|
15
|
+
# or
|
|
16
|
+
# erb :"partials/flash"
|
|
17
|
+
#
|
|
18
|
+
# which is just weird and ugly.
|
|
19
|
+
#
|
|
20
|
+
# also, defaults to not use a layout file when the request is made of XHR
|
|
21
|
+
|
|
22
|
+
def erb(template, options = {}, locals = {})
|
|
23
|
+
template = template.to_sym
|
|
24
|
+
options[:layout] = (options[:layout].present? || options[:layout] == false) ? options[:layout] : !request.xhr?
|
|
25
|
+
|
|
26
|
+
super
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# link helper
|
|
30
|
+
#
|
|
31
|
+
# <%= link_to 'click here to get awesome hawtness', '/hawtness' %>
|
|
32
|
+
#
|
|
33
|
+
# with HTML attributes:
|
|
34
|
+
#
|
|
35
|
+
# <%= link_to 'Home', '/', :class => 'home-link', :title => 'Click here to go home', :data => { :to => '#home' } %>
|
|
36
|
+
#
|
|
37
|
+
def link_to(text, link, attributes = {})
|
|
38
|
+
if link == (request.url.include?('?') ? "#{ request.path_info }?#{ request.query_string }" : request.path_info)
|
|
39
|
+
attributes[:class] = "#{ attributes[:class] } current"
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
attributes.merge!({ :href => link })
|
|
43
|
+
|
|
44
|
+
"<a #{ attributes.to_attr }>#{ text }</a>"
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Returns the url of the referer along with the params posted to that page
|
|
48
|
+
# Lets you hand back invalid params for correction in the previous page.
|
|
49
|
+
# You can also add extra params in to send back.
|
|
50
|
+
#
|
|
51
|
+
# redirect to(back_with_params(:my_extra_param => 'my extra value'))
|
|
52
|
+
#
|
|
53
|
+
def back_with_params(o = {})
|
|
54
|
+
rejected_keys = [:password] # these won't be passed back to the page
|
|
55
|
+
back_to = request.referer ? request.referer : '/'
|
|
56
|
+
params_string = params.blank? ? '' : "?#{ build_query(o.merge(params).delete_if { |k, v| rejected_keys.include?(k.to_sym) }) }"
|
|
57
|
+
|
|
58
|
+
back_to + params_string
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Handles an unruly `back` method call with an alternate route
|
|
62
|
+
def back_or(new_path)
|
|
63
|
+
if back == '/' || back == request.path_info
|
|
64
|
+
new_path
|
|
65
|
+
else
|
|
66
|
+
back
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Cookie getter / setter
|
|
71
|
+
#
|
|
72
|
+
# Setter (sets the 'my-cookie' cookie to 'this here is a value'):
|
|
73
|
+
#
|
|
74
|
+
# cookie 'my-cookie', 'this here is a value'
|
|
75
|
+
#
|
|
76
|
+
# Getter
|
|
77
|
+
#
|
|
78
|
+
# cookie 'my-cookie' # => 'this here is a value'
|
|
79
|
+
#
|
|
80
|
+
def cookie(name, value = nil, duration = 15)
|
|
81
|
+
if value
|
|
82
|
+
response.set_cookie name, {
|
|
83
|
+
:value => value,
|
|
84
|
+
:expires => Time.now + (60 * duration),
|
|
85
|
+
:path => "/",
|
|
86
|
+
:httponly => true,
|
|
87
|
+
:secure => production?
|
|
88
|
+
}
|
|
89
|
+
else
|
|
90
|
+
request.cookies[name]
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# checks the params hash for a single argument as both !nil and !empty
|
|
95
|
+
def ensure_param(arg)
|
|
96
|
+
params[arg.to_sym].present?
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# checks an array of params from the params hash
|
|
100
|
+
def ensure_params(*args)
|
|
101
|
+
return catch(:truthy) {
|
|
102
|
+
args.each do |arg|
|
|
103
|
+
throw(:truthy, false) unless ensure_param(arg)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
throw(:truthy, true)
|
|
107
|
+
}
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# debug log to server log if development
|
|
111
|
+
# else outputs nothing (for production)
|
|
112
|
+
def dlog(*args)
|
|
113
|
+
if development?
|
|
114
|
+
$stdout.puts "\n================================================\n"
|
|
115
|
+
for arg in args
|
|
116
|
+
$stdout.puts arg
|
|
117
|
+
$stdout.puts "================================================\n"
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|