status_tag 0.1.0

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e40ce1236e635e3ebe7e29aa9894a3058958041b
4
+ data.tar.gz: a50a76c6ddac86762f4609bb91812b5291672132
5
+ SHA512:
6
+ metadata.gz: 595707bd6f6597902fae0f2f42ef16aec5af4b3c3a9afecc6d26c0c4d5de069615890e4af848e77fdf43d9059e7483f4fae8c9799134bc97838fc534ee6a0a93
7
+ data.tar.gz: a9da7ece09d57c4da07f8d7a6ce9dd6902460d48c9cbcfeeca5eed42ac4fd79e11a90a5cd0e6552b5082852589368e6c69c49d1bf5caeefc38222526b8fc2bee
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.2.3
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2.3
4
+ before_install: gem install bundler -v 1.10.6
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in status_tag.gemspec
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1,46 @@
1
+ # StatusTag
2
+
3
+ SRP: Provides a method signature that can be splatted to Rails' `content_tag_for` to create labels.
4
+ Flexible: not explicitly dependent on bootstrap or any other style framework.
5
+
6
+ ## Installation
7
+
8
+ Add this line to your application's Gemfile:
9
+
10
+ ```ruby
11
+ gem 'status_tag'
12
+ ```
13
+
14
+ And then execute:
15
+
16
+ $ bundle
17
+
18
+ Or install it yourself as:
19
+
20
+ $ gem install status_tag
21
+
22
+ ## Usage
23
+
24
+ Example:
25
+
26
+ ```ruby
27
+ # Recommend putting the following in a helper method.
28
+ # signature may be nil, which is an indication that the chosen label was marked as a noop.
29
+ text, signature = StatusTag::Presenter.status_tag_signature_for(:span, user, "state")
30
+ if signature
31
+ content_tag_for(*signature) do
32
+ text
33
+ end
34
+ end
35
+ ```
36
+
37
+ ## Development
38
+
39
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
40
+
41
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
42
+
43
+ ## Contributing
44
+
45
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/status_tag.
46
+
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "status_tag"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
data/lib/status_tag.rb ADDED
@@ -0,0 +1,51 @@
1
+ require "status_tag/version"
2
+ require "status_tag/utils"
3
+ require "status_tag/choice"
4
+ require "status_tag/decider"
5
+ require "status_tag/presenter"
6
+ require "status_tag/null_presenter"
7
+
8
+ module StatusTag
9
+
10
+ extend StatusTag::Utils
11
+
12
+ def self.status_tag_presenter(object:, aspect: nil)
13
+ # Support for STI and namespaced Objects is accomplished by
14
+ # first checking for a Presenter definition at the STI class level
15
+ # and then checking for a definition at the super class (generic) level.
16
+ namespaces = namespaces_from_class(object.class)
17
+ presenter = nil
18
+ namespaces.inject(object.class) do |namespace, memo|
19
+ if aspect.nil?
20
+ # recommend locating class definition at app/presenters/status_tag/<klass>_presenter.rb
21
+ presenter_class = class_from_string("StatusTag::#{memo}Presenter")
22
+ presenter = presenter_class.new(object: object) if presenter_class
23
+ else
24
+ presenter_class = class_from_string("StatusTag::#{memo}Presenters::#{camelize_underscored(aspect.to_s)}Presenter")
25
+ # recommend locating class definition at app/presenters/status_tag/<klass>_presenters/<aspect>_presenter.rb
26
+ presenter = presenter_class.new(object: object, aspect: aspect) if presenter_class
27
+ end
28
+ break if presenter
29
+ last_namespace = memo.rindex("::")
30
+ memo = memo[0..(last_namespace-1)] if last_namespace # level up!
31
+ memo
32
+ end
33
+ presenter = NullPresenter.new(object: object) unless presenter
34
+ presenter
35
+ end
36
+
37
+ # Same signature as Rails' `content_tag_for`.
38
+ # However, does not currently support object being multiple records like Rails' `content_tag_for` does
39
+ def self.status_tag_signature_for(tag, object, prefix = false, options = nil)
40
+ presenter = status_tag_presenter(object: object, aspect: prefix)
41
+ choice = presenter.decide
42
+ return choice.text, nil if choice.noop?
43
+ options ||= {}
44
+ options[:class] = Array(options[:class])
45
+ options[:class].concat(Array(presenter.class.css_class(object, prefix)))
46
+ options[:class] << choice.klass
47
+ options[:class] = options[:class].join(" ")
48
+ return choice.text, [tag, presenter.object, presenter.aspect, options]
49
+ end
50
+
51
+ end
@@ -0,0 +1,26 @@
1
+ module StatusTag
2
+ class Choice
3
+
4
+ attr_accessor :name, # the method that will be called on the object to determine if this is the correct choice
5
+ # when nil, indicates this choice is the catch-all, naked `else`
6
+ :klass, # klass is for the CSS class that will differentiate each specific label type (color, size, etc)
7
+ :text, # text is the what the label says in the view port
8
+ :noop # designates a `name` as taking up space, but not rendering a tag, in the ordered set to tumble the results.
9
+
10
+ def initialize(name: nil, klass: "", text: "", noop: false)
11
+ @name = name
12
+ @klass = klass
13
+ @text = text
14
+ @noop = !!noop
15
+ end
16
+
17
+ def catch_all?
18
+ name.nil?
19
+ end
20
+
21
+ def noop?
22
+ noop
23
+ end
24
+
25
+ end
26
+ end
@@ -0,0 +1,21 @@
1
+ module StatusTag
2
+ class Decider
3
+
4
+ attr_accessor :ordered_choices
5
+
6
+ def initialize(ordered_choices:)
7
+ @ordered_choices = ordered_choices
8
+ end
9
+
10
+ def decide(object)
11
+ ordered_choices.detect do |choice|
12
+ if choice.catch_all?
13
+ true
14
+ else
15
+ object.send(choice.name)
16
+ end
17
+ end
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,6 @@
1
+ # An example of what a Presenter would look like.
2
+ module StatusTag
3
+ class NullPresenter < Presenter
4
+ ORDERED_CHOICES = [StatusTag::Choice.new(text: "null presenter")]
5
+ end
6
+ end
@@ -0,0 +1,52 @@
1
+ # SRP: Provides a method signature that can be splatted to content_tag_for to create labels
2
+ #
3
+ # This base class can be used to instantiate a label for anything.
4
+ # Subclasses will address specific needs, like a label for user status, order status, job state, etc.
5
+ # Flexible: not explicitly dependent on bootstrap or any other style framework.
6
+ #
7
+ # Example:
8
+ #
9
+ # text, signature = StatusTag::Presenter.status_tag_signature_for(:span, mtm_profile, "fit_status")
10
+ # content_tag_for(*signature) do
11
+ # text
12
+ # end
13
+
14
+ module StatusTag
15
+ class Presenter
16
+
17
+ # Override constants in subclasses
18
+ ORDERED_CHOICES = [StatusTag::Choice.new]
19
+ CSS_CLASS = [] # A CSS class or classes to assign to all tags generated with the presenter
20
+
21
+ attr_accessor :object, # e.g. an instance of the User class
22
+ :aspect # e.g. "state", "status" or some other descriptive name for this particular status tag
23
+ # Defaults to nil, so by default there is only one StatusTag presenter allowed per object class,
24
+ # as the aspect provides a namespace for additional presenters.
25
+ attr_reader :decider
26
+
27
+ def initialize(object:, aspect: nil)
28
+ @object = object
29
+ @aspect = aspect
30
+ @decider = StatusTag::Decider.new(ordered_choices: self.class.ordered_choices(object, aspect))
31
+ end
32
+
33
+ def decide
34
+ decider.decide(object)
35
+ end
36
+
37
+ # An alternative to overriding the constant in subclasses is to override this method.
38
+ # If you override, do not change the signature.
39
+ # The params enable the ordered choices to be derived dynamically for your needs, but are not used by default.
40
+ def self.ordered_choices(object, aspect)
41
+ self::ORDERED_CHOICES
42
+ end
43
+
44
+ # An alternative to overriding the CSS_CLASS constant in subclasses is to override this method.
45
+ # If you override, do not change the signature.
46
+ # The params enable the ordered choices to be derived dynamically for your needs, but are not used by default.
47
+ def self.css_class(object, aspect)
48
+ self::CSS_CLASS
49
+ end
50
+
51
+ end
52
+ end
@@ -0,0 +1,23 @@
1
+ module StatusTag
2
+ module Utils
3
+
4
+ MOD_SEPARATOR = "::"
5
+
6
+ def class_from_string(str)
7
+ str.split(MOD_SEPARATOR).inject(Object) do |mod, class_name|
8
+ mod.const_get(class_name)
9
+ end
10
+ rescue
11
+ nil
12
+ end
13
+
14
+ def namespaces_from_class(klass)
15
+ klass.to_s.split(MOD_SEPARATOR)
16
+ end
17
+
18
+ def camelize_underscored(str)
19
+ str.split('_').map {|w| w.capitalize}.join
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,3 @@
1
+ module StatusTag
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,17 @@
1
+ module StatusTag
2
+ module MtmProfilePresenters
3
+ class FitStatusPresenter < Presenter
4
+ ORDERED_CHOICES = [
5
+ StatusTag::Choice.new(name: "new?", klass: "label-default-important", text: "B New"),
6
+ StatusTag::Choice.new(name: "bad_fit?", klass: "label-default-warning", text: "B Bad Fit"),
7
+ StatusTag::Choice.new(name: "confirmed?", klass: "label-default-success", text: "B Fit Confirmed"),
8
+ StatusTag::Choice.new(name: "pending?", noop: true), # TODO: Why do we not want pending to display?
9
+ StatusTag::Choice.new(name: nil, klass: "label-default-warning", text: "B Fit Unknown"),
10
+ ]
11
+ CSS_CLASS = [
12
+ "label",
13
+ "label-default"
14
+ ]
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,18 @@
1
+ module StatusTag
2
+ module MtmProfilePresenters
3
+ class MeasurementStatusPresenter < Presenter
4
+ ORDERED_CHOICES = [
5
+ StatusTag::Choice.new(name: "bad?", klass: "label-default-warning", text: "B Bad Measure"),
6
+ StatusTag::Choice.new(name: "good?", klass: "label-default-success", text: "B Good Measure"),
7
+ StatusTag::Choice.new(name: "waiting_approval?", klass: "label-default-important", text: "B Pending Measure"),
8
+ StatusTag::Choice.new(name: "on_hold?", klass: "label-default-warning", text: "B On Hold"),
9
+ StatusTag::Choice.new(name: "not_measured?", klass: "label-default-important", text: "B Not Measured"),
10
+ StatusTag::Choice.new(name: nil, klass: "label-default-warning", text: "B Measure Unknown"),
11
+ ]
12
+ CSS_CLASS = [
13
+ "label",
14
+ "label-default"
15
+ ]
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,17 @@
1
+ module StatusTag
2
+ module MtmProfilePresenters
3
+ class FitStatusPresenter < Presenter
4
+ ORDERED_CHOICES = [
5
+ StatusTag::Choice.new(name: "new?", klass: "label-default-important", text: "New"),
6
+ StatusTag::Choice.new(name: "bad_fit?", klass: "label-default-warning", text: "Bad Fit"),
7
+ StatusTag::Choice.new(name: "confirmed?", klass: "label-default-success", text: "Fit Confirmed"),
8
+ StatusTag::Choice.new(name: "pending?", noop: true), # TODO: Why do we not want pending to display?
9
+ StatusTag::Choice.new(name: nil, klass: "label-default-warning", text: "Fit Unknown"),
10
+ ]
11
+ CSS_CLASS = [
12
+ "label",
13
+ "label-default"
14
+ ]
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,18 @@
1
+ module StatusTag
2
+ module MtmProfilePresenters
3
+ class MeasurementStatusPresenter < Presenter
4
+ ORDERED_CHOICES = [
5
+ StatusTag::Choice.new(name: "bad?", klass: "label-default-warning", text: "Bad Measure"),
6
+ StatusTag::Choice.new(name: "good?", klass: "label-default-success", text: "Good Measure"),
7
+ StatusTag::Choice.new(name: "waiting_approval?", klass: "label-default-important", text: "Pending Measure"),
8
+ StatusTag::Choice.new(name: "on_hold?", klass: "label-default-warning", text: "On Hold"),
9
+ StatusTag::Choice.new(name: "not_measured?", klass: "label-default-important", text: "Not Measured"),
10
+ StatusTag::Choice.new(name: nil, klass: "label-default-warning", text: "Measure Unknown"),
11
+ ]
12
+ CSS_CLASS = [
13
+ "label",
14
+ "label-default"
15
+ ]
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'status_tag/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "status_tag"
8
+ spec.version = StatusTag::VERSION
9
+ spec.authors = ["Peter Boling"]
10
+ spec.email = ["peter.boling@gmail.com"]
11
+
12
+ spec.summary = %q{Provides content_tag_for method signature to create labels from Ruby objects}
13
+ spec.description = %q{Provides content_tag_for method signature to create customizable and logic-gated labels from objects.
14
+ Also includes a presenter base class to allow any Ruby web framework to create logic around HTML tags}
15
+ spec.homepage = "http://github.com/pboling/status_tag"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ spec.bindir = "exe"
19
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_development_dependency "bundler", "~> 1.10"
23
+ spec.add_development_dependency "rake", "~> 10.0"
24
+ spec.add_development_dependency "rspec"
25
+ spec.add_development_dependency "pry"
26
+ end
metadata ADDED
@@ -0,0 +1,122 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: status_tag
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Peter Boling
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2015-08-24 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.10'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.10'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: pry
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: |-
70
+ Provides content_tag_for method signature to create customizable and logic-gated labels from objects.
71
+ Also includes a presenter base class to allow any Ruby web framework to create logic around HTML tags
72
+ email:
73
+ - peter.boling@gmail.com
74
+ executables: []
75
+ extensions: []
76
+ extra_rdoc_files: []
77
+ files:
78
+ - ".gitignore"
79
+ - ".rspec"
80
+ - ".ruby-version"
81
+ - ".travis.yml"
82
+ - Gemfile
83
+ - README.md
84
+ - Rakefile
85
+ - bin/console
86
+ - bin/setup
87
+ - lib/status_tag.rb
88
+ - lib/status_tag/choice.rb
89
+ - lib/status_tag/decider.rb
90
+ - lib/status_tag/null_presenter.rb
91
+ - lib/status_tag/presenter.rb
92
+ - lib/status_tag/utils.rb
93
+ - lib/status_tag/version.rb
94
+ - mtm_profile/blazer_presenters/fit_status_presenter.rb
95
+ - mtm_profile/blazer_presenters/measurement_status_presenter.rb
96
+ - mtm_profile_presenters/fit_status_presenter.rb
97
+ - mtm_profile_presenters/measurement_status_presenter.rb
98
+ - status_tag.gemspec
99
+ homepage: http://github.com/pboling/status_tag
100
+ licenses: []
101
+ metadata: {}
102
+ post_install_message:
103
+ rdoc_options: []
104
+ require_paths:
105
+ - lib
106
+ required_ruby_version: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ required_rubygems_version: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - ">="
114
+ - !ruby/object:Gem::Version
115
+ version: '0'
116
+ requirements: []
117
+ rubyforge_project:
118
+ rubygems_version: 2.4.5.1
119
+ signing_key:
120
+ specification_version: 4
121
+ summary: Provides content_tag_for method signature to create labels from Ruby objects
122
+ test_files: []