abak-flow 0.3.2 → 1.0.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,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ MGU3ZjFmYjE3OWMyMDM4NTI1NWJjYzQxZDFjZTM5YmQ2YmQ0M2Q1ZQ==
5
+ data.tar.gz: !binary |-
6
+ NjViMDJhOWE1ZmRhMTU0ZjZkNjVkNjhlYTBiZmE0ZTM1NjgyYzlkZA==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ NWE0M2ZjYmJkMDQ0MWU4OWUxZDBiODk4NTU0N2Q2M2IyZTU4ZGIyZTgxZTBl
10
+ NGEyY2M4YTZjMjI4ZmZjY2FlZjJjMTZiMzg0YThmYTBkN2E1ODA2NzVjYjc2
11
+ MjFiZDlkZDdiMmU1ODExNzJiNzBhYzA0MDE1ZWNjMTIxMjViOWI=
12
+ data.tar.gz: !binary |-
13
+ MzZkYmQ0OThkMDcxYjFlNmI4MTdlYmRjOTY1NzBmNDYxNTI3Mjc5M2M5ZjVh
14
+ YmM2ZDJlM2ZhOTk0YjQ5MWJkZmVkNmVkY2I2MmMwOTYxMTQyOWZhOTBiMGEw
15
+ YzVmYjYzNjY4ZDZiOGZmYjEyMzFkOTM4MGFhYjI1YjgwZTQ1ZGU=
data/.gitignore CHANGED
@@ -1,8 +1,11 @@
1
1
  *.gem
2
+ .ruby-*
2
3
  .bundle
3
4
  Gemfile.lock
4
5
  pkg/*
5
6
  tmp/
6
7
  .idea/
8
+ coverage/
7
9
  .rvmrc
8
10
  .DS_Store
11
+ tmtags*
data/.travis.yml ADDED
@@ -0,0 +1,7 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ branches:
5
+ only:
6
+ - release-1.0
7
+ bundler_args: --without linux mac
data/Gemfile CHANGED
@@ -1,3 +1,12 @@
1
1
  source "https://rubygems.org"
2
2
 
3
- gemspec
3
+ gemspec
4
+
5
+ group :linux do
6
+ gem "libnotify"
7
+ gem "rb-inotify"
8
+ end
9
+
10
+ group :mac do
11
+ gem "terminal-notifier-guard"
12
+ end
data/README.md CHANGED
@@ -2,7 +2,9 @@ Abak-flow
2
2
  =========
3
3
  Нет, это не новая идеология ведения проекта, это всего лишь набор утилит которые помогают связать использование [git-flow](https://github.com/nvie/gitflow) и [github flow](http://scottchacon.com/2011/08/31/github-flow.html)
4
4
 
5
- **Начиная с версии v0.2.1 используется авторизация OAuth2. [Как ей пользоваться](https://github.com/Strech/abak-flow/wiki/How-start-work-with-new-abak-flow)**
5
+ **Начиная с версии v0.2.1 используется авторизация OAuth2. [Как ей пользоваться?](https://github.com/Strech/abak-flow/wiki/How-start-work-with-new-abak-flow)**
6
+
7
+ **Начиная с версии v1.0.0 используется новый формат конфигурации. [Как мигрировать старую?](https://github.com/Strech/abak-flow/wiki/How-start-work-with-abak-flow-v1.0.0)**
6
8
 
7
9
  # Концепция
8
10
  Идеология git-flow использует следующий набор веток:
@@ -25,10 +27,10 @@ Github-flow же наоборот ведет основную разработк
25
27
 
26
28
  # Установка
27
29
 
28
- $ gem install abak-flow
30
+ $ gem install abak-flow -v 1.0.0
29
31
  $ git config --global alias.request '!request'
30
- $ git config --global abak.apiuser YOUR_GITHUB_MAIL@gmail.com
31
- $ git config --global abak.apitoken 0123456789YOUR_GITHUB_API_TOKEN
32
+ $ git config --global abak-flow.oauth-user YOUR_GITHUB_MAIL@gmail.com
33
+ $ git config --global abak-flow.oauth-token 0123456789YOUR_GITHUB_API_TOKEN
32
34
  $ git remote add upstream git://github.com/GITHUB_PROJECT_USER/GITHUB_PROJECT_NAME.git
33
35
 
34
36
  ### А если я использую прокси, как быть?
@@ -40,13 +42,13 @@ Github-flow же наоборот ведет основную разработк
40
42
 
41
43
  ---
42
44
 
43
- **Заметьте:** В конфиге git, значением *abak.apiuser* должен являться тот email адрес, под которым вы заходите на github
45
+ **Заметьте:** В конфиге git, значением *abak.oauth-user* должен являться тот email адрес, под которым вы заходите на github
44
46
 
45
47
  **Обратите внимание:** В данном контексте под **upstream** подразумевается адрес репозитория в который будут оформляться pull request. А репозиторием **origin** будет являться ваш форк
46
48
 
47
49
  # С чего начать?
48
50
 
49
- $ git request readycheck
51
+ $ git request checkup
50
52
 
51
53
  или
52
54
 
@@ -58,7 +60,7 @@ Github-flow же наоборот ведет основную разработк
58
60
  ### Самый простой способ начать новую задачу:
59
61
 
60
62
  $ git checkout develop
61
- $ git request feature 'TASK-001'
63
+ $ git flow feature start 'TASK-001'
62
64
  $ touch 'hello.txt' && echo 'Hello world!' > hello.txt
63
65
  $ git commit -a -m 'Hello world commit'
64
66
  $ git request publish
@@ -68,7 +70,7 @@ Github-flow же наоборот ведет основную разработк
68
70
  Теперь то же самое, только словами:
69
71
 
70
72
  * Переключимся в ветку develop
71
- * Abak-flow создаст ветку, пригодную для оформления pull request (правила именования и правила самого реквеста)
73
+ * git-flow создаст ветку, пригодную для оформления pull request (правила именования и правила самого реквеста)
72
74
  * Простое создание нового файла
73
75
  * Git процедуры добавления своих изменений в репозиторий
74
76
  * Затем публикация вашей ветки на вашем форке (если таковая уже есть, то просто обновление), затем оформление pull request из этой ветки в соответствующую правилам ветку на upstream (в данном случае это будет ветка develop)
@@ -76,36 +78,17 @@ Github-flow же наоборот ведет основную разработк
76
78
  Для задач, которые должны быть выполнены в виде hotfix принцип тот же:
77
79
 
78
80
  $ git checkout master
79
- $ git request hotfix 'TASK-001'
81
+ $ git flow hotfix start 'TASK-001'
80
82
  $ …
81
83
  $ git request publish
82
84
 
83
85
  *На самом деле переключаться на master или develop в самом начале вовсе не обязательно, этот шаг был приведен для пущей ясности*
84
86
 
85
- ### Обновление ветки на удаленном репозитории:
86
-
87
- $ git checkout feature/TASK-001
88
- $ git request update
89
-
90
- ### Завершение текущей задачи:
91
- Вообще, завершать задачу лучше только после того, как ваш pull request был принят. Почему? На самом деле по ряду причин. По умолчанию эта команда удаляет как вашу текущую ветку с задачей в локальном репозитории и в добавок ко всему - на вашем удаленном репозитории (форке)
92
-
93
- $ git checkout feature/TASK-001
94
- $ git request done
95
-
96
- Чтобы оставить какую либо ветку в живых возможно напрямую указать, какую копию ветки **удалить**, локальную или же удаленную (на origin)
97
-
98
- $ git checkout feature/TASK-001
99
- $ git request done --origin
100
-
101
- Или же так
102
-
103
- $ git checkout feature/TASK-001
104
- $ git request done --local
105
-
106
87
  ## Маленькие хитрости
107
88
  Если сразу правильно именовать ветки, т.е ветку с задачей создавать с именем, такого формата TASK-001, то, в описание pull request автоматически вставится ссылка на задачу в jira, а в имя pull request сразу вставится название, состоящее из имени задачи, т.е TASK-001
108
89
 
90
+ Если делать реквест из ветки не соответствующей формату TASK-001, то в название подставится последний commit message. Если вы считаете, что нужно указать, что-то другое - всегда можно воспользоваться опцией `--title`
91
+
109
92
  ## А помощь?
110
93
  Многие команды имеют какие-то дополнительные опции. Но они нужны только в экзотических случаях. Но при любом раскладе подсказку и тонкий намек всегда можно получить воспользовавших такой командой:
111
94
 
data/Rakefile CHANGED
@@ -1 +1,26 @@
1
1
  require "bundler/gem_tasks"
2
+
3
+ require "yard"
4
+ require "yard-tomdoc"
5
+ require "cane/rake_task"
6
+ require "rspec/core/rake_task"
7
+
8
+ desc "Ready check"
9
+ task default: [:quality, :coverage, :doc]
10
+
11
+ RSpec::Core::RakeTask.new(:coverage) do |rspec|
12
+ ENV["COVERAGE"] = "true"
13
+ end
14
+
15
+ Cane::RakeTask.new(:quality) do |cane|
16
+ cane.abc_max = 15
17
+ cane.abc_glob = cane.style_glob = cane.doc_glob = "{lib}/abak-flow/*.rb"
18
+ cane.style_exclude = %w({lib}/abak-flow/request.rb)
19
+ cane.style_measure = 120
20
+ cane.parallel = false
21
+ end
22
+
23
+ YARD::Rake::YardocTask.new(:doc) do |yard|
24
+ yard.files = %w({apps,models,lib}/**/*.rb)
25
+ yard.options = %w(--embed-mixins --protected --plugin tomdoc)
26
+ end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.2
1
+ 1.0
data/abak-flow.gemspec CHANGED
@@ -1,24 +1,28 @@
1
- # -*- encoding: utf-8 -*-
2
- $:.push File.expand_path('../lib', __FILE__)
3
- require 'abak-flow/version'
1
+ # coding: utf-8
2
+ $:.push File.expand_path("../lib", __FILE__)
4
3
 
5
- Gem::Specification.new do |s|
6
- s.name = 'abak-flow'
7
- s.version = Abak::Flow::VERSION
8
- s.authors = ['Strech (aka Sergey Fedorov)']
9
- s.email = ['oni.strech@gmail.com']
10
- s.homepage = 'https://github.com/Strech/abak-flow'
11
- s.summary = %q{Совмещение 2-х подходов разработки Git-flow & Github-flow}
12
- s.description = %q{Простой набор правил и комманд, заточеных для работы в git-flow с использование в качестве удаленного репозитория github}
4
+ require "abak-flow/version"
13
5
 
14
- s.rubyforge_project = 'abak-flow'
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "abak-flow"
8
+ gem.version = Abak::Flow::VERSION
9
+ gem.authors = ["Strech (aka Sergey Fedorov)"]
10
+ gem.email = ["oni.strech@gmail.com"]
11
+ gem.homepage = "https://github.com/Strech/abak-flow"
12
+ gem.summary = "Совмещение 2-х подходов разработки Git-flow & Github-flow"
13
+ gem.description = "Простой набор правил и комманд, заточеных для работы в git-flow с использование в качестве удаленного репозитория github"
15
14
 
16
- s.files = `git ls-files`.split("\n")
17
- s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
- s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
- s.require_paths = ['lib']
15
+ gem.rubyforge_project = "abak-flow"
20
16
 
21
- s.add_runtime_dependency 'hub', '~> 1.10.3'
22
- s.add_runtime_dependency 'commander', '~> 4.1.2'
23
- s.add_runtime_dependency 'octokit', '~> 1.19.0'
17
+ gem.files = `git ls-files`.split("\n")
18
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ gem.require_paths = ["lib"]
21
+
22
+ gem.add_runtime_dependency "octokit", "~> 1.19.0"
23
+ gem.add_runtime_dependency "git", "~> 1.2.5"
24
+ gem.add_runtime_dependency "commander", ">= 4.1.3"
25
+ gem.add_runtime_dependency "ruler", ">= 1.4.2"
26
+ gem.add_runtime_dependency "i18n", ">= 0.6.1"
27
+ gem.add_runtime_dependency "ansi", ">= 1.4.3"
24
28
  end
data/bin/request CHANGED
@@ -1,4 +1,3 @@
1
1
  #!/usr/bin/env ruby
2
- # -*- encoding: utf-8 -*-
2
+ # coding: utf-8
3
3
  require 'abak-flow'
4
- require "abak-flow/request"
@@ -0,0 +1,108 @@
1
+ # coding: utf-8
2
+
3
+ module Abak::Flow
4
+ class Branch
5
+ FOLDER_HOTFIX = "hotfix".freeze
6
+ FOLDER_FEATURE = "feature".freeze
7
+ TASK_FORMAT = /^\w+\-\d{1,}$/.freeze
8
+
9
+ DEVELOPMENT = "develop".freeze
10
+ MASTER = "master".freeze
11
+
12
+ MAPPING = {
13
+ FOLDER_HOTFIX => MASTER,
14
+ FOLDER_FEATURE => DEVELOPMENT
15
+ }.freeze
16
+
17
+ def initialize(branch, manager)
18
+ @manager = manager
19
+ @branch = branch.is_a?(Git::Branch) ? branch
20
+ : manager.git.branch(branch)
21
+ end
22
+
23
+ def name
24
+ @branch.full
25
+ end
26
+
27
+ def message
28
+ @branch.gcommit.message
29
+ end
30
+
31
+ def folder
32
+ split_prefix_and_task.first
33
+ end
34
+
35
+ def task
36
+ split_prefix_and_task.last
37
+ end
38
+
39
+ def compare_link(branch)
40
+ diff = "#{@manager.repository.upstream.owner}:#{branch}...#{@branch}"
41
+
42
+ File.join [
43
+ @manager.github.web_endpoint,
44
+ @manager.repository.origin.to_s,
45
+ "compare", diff
46
+ ]
47
+ end
48
+
49
+ def update
50
+ origin = @manager.repository.origin.repo
51
+ @manager.git.push(origin, @branch)
52
+ end
53
+
54
+ def pick_up_base_name
55
+ mappable? ? MAPPING[folder]
56
+ : name
57
+ end
58
+
59
+ def pick_up_title
60
+ tracker_task? ? task
61
+ : message
62
+ end
63
+
64
+ # TODO : Вынести в i18n
65
+ def pick_up_body
66
+ tracker_task? ? "http://jira.railsc.ru/browse/#{task}"
67
+ : nil
68
+ end
69
+
70
+ def hotfix?
71
+ folder == FOLDER_HOTFIX
72
+ end
73
+
74
+ def feature?
75
+ folder == FOLDER_FEATURE
76
+ end
77
+
78
+ def tracker_task?
79
+ !(task =~ TASK_FORMAT).nil?
80
+ end
81
+
82
+ def mappable?
83
+ hotfix? || feature?
84
+ end
85
+
86
+ def current?
87
+ @branch.current
88
+ end
89
+
90
+ def valid?
91
+ !@branch.name.empty?
92
+ end
93
+
94
+ def to_s
95
+ @branch.to_s
96
+ end
97
+
98
+ private
99
+ def split_prefix_and_task
100
+ return @folder_and_task if defined? @folder_and_task
101
+
102
+ matches = name.match(/^(?<prefix>.+)\/(?<task>.+)$/)
103
+
104
+ @folder_and_task = matches.nil? ? [nil, nil]
105
+ : [matches[:prefix], matches[:task]]
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,68 @@
1
+ # coding: utf-8
2
+ #
3
+ # Wrapper class for git branches.
4
+ # Provides access to git branches and also defines current_branch
5
+ module Abak::Flow
6
+ module Branches
7
+ extend Forwardable
8
+
9
+ def_delegator "Abak::Flow::Git.instance", :git
10
+
11
+ def self.current_branch
12
+ Branch.new git.branches[git.current_branch]
13
+ end
14
+
15
+ # ==========================================================================
16
+ # TODO : Refactor
17
+ # 3. Statistics & Cleaning
18
+ #
19
+ # => PullRequest.garbage
20
+ # => PullRequest.clean
21
+ # => PullRequest.clean(hard: true)
22
+ def self.garbage
23
+ Project.init
24
+ [Project.upstream.repo, Project.origin.repo].map(&:fetch)
25
+
26
+ branches = GithubClient.connection.branches(Project.origin.to_s)
27
+ .reject { |branch| %w(master develop).include? branch.name }
28
+
29
+ messages = Messages.new "pull_request.garbage"
30
+ messages << [:collected_branches, {count: branches.count}]
31
+
32
+ branches.each_with_index do |branch, index|
33
+
34
+ # WRONG PREFIX
35
+ upstream_branch = Git.command_lines("branch", ["-r", "--contain", branch.commit.sha])
36
+ .select { |branches| branches.include? "upstream/#{branch.prefix}" }
37
+
38
+ local_sha = git.branches[branch.name] ? git.branches[branch.name].gcommit.sha : ""
39
+
40
+ statuses = {
41
+ branch_unused: upstream_branch.empty?,
42
+ branch_differ: !local_sha.empty? && local_sha != branch.commit.sha,
43
+ branch_missing: local_sha.empty?
44
+ }
45
+
46
+ unless statuses.values.inject &:|
47
+ messages << [:deletion_allowed, {index: index, branch_name: branch.name}]
48
+ next
49
+ end
50
+
51
+ diagnoses = statuses.select { |_, bool| bool }.
52
+ map { |name, _| messages.t name }.
53
+ map { |msg| " ↪ #{msg}" }.
54
+ join("\n")
55
+
56
+ if statuses.select { |_, bool| bool }.keys == [:missing]
57
+ messages << [:deletion_possibly, {index: index, branch_name: branch.name, diagnoses: diagnoses}]
58
+ else
59
+ messages << [:deletion_restricted, {index: index, branch_name: branch.name, diagnoses: diagnoses}]
60
+ end
61
+ end
62
+
63
+ messages
64
+ end
65
+
66
+
67
+ end
68
+ end
@@ -0,0 +1,67 @@
1
+ # coding: utf-8
2
+ require "i18n"
3
+ require "ruler"
4
+
5
+ module Abak::Flow
6
+ class Configuration
7
+ include Ruler
8
+
9
+ OPTIONS = [:oauth_user, :oauth_token, :locale, :http_proxy].freeze
10
+ LOCALE_FILES = File.join(File.dirname(__FILE__), "locales/*.{rb,yml}").freeze
11
+
12
+ attr_reader :errors
13
+
14
+ def initialize(manager)
15
+ @manager = manager
16
+ @errors = []
17
+
18
+ configure!
19
+ end
20
+
21
+ def ready?
22
+ @errors = []
23
+
24
+ multi_ruleset do
25
+ fact(:oauth_user_not_setup) { oauth_user.nil? }
26
+ fact(:oauth_token_not_setup) { oauth_token.nil? }
27
+
28
+ rule([:oauth_user_not_setup]) { @errors << I18n.t("configuration.errors.oauth_user_not_setup") }
29
+ rule([:oauth_token_not_setup]) { @errors << I18n.t("configuration.errors.oauth_token_not_setup") }
30
+ end
31
+
32
+ @errors.empty? ? true : false
33
+ end
34
+
35
+ def display_name
36
+ I18n.t("configuration.name")
37
+ end
38
+
39
+ private
40
+ def configure!
41
+ load_gitconfig
42
+ setup_locale
43
+ end
44
+
45
+ def setup_locale
46
+ I18n.load_path += Dir.glob(LOCALE_FILES)
47
+ I18n.locale = locale
48
+ end
49
+
50
+ def load_gitconfig
51
+ git_config = @manager.git.config.select { |k, _| k.include? "abak-flow." }
52
+ .map { |k,v| [to_method_name(k), v] }
53
+
54
+ config = Hash[git_config]
55
+ config[:locale] ||= "en"
56
+ config[:http_proxy] ||= ENV["http_proxy"] || ENV["HTTP_PROXY"]
57
+
58
+ OPTIONS.each do |name|
59
+ define_singleton_method(name) { config[name] }
60
+ end
61
+ end
62
+
63
+ def to_method_name(name)
64
+ name.sub(/abak-flow./, "").gsub(/\W/, "_").to_sym
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,32 @@
1
+ en:
2
+ configuration:
3
+ name: Configuration
4
+ errors:
5
+ oauth_user_not_setup: Options oauth_user not setted
6
+ oauth_token_not_setup: Options oauth_token not setted
7
+ recommendations: "Check [abak-flow] section in ~/.gitcofig file"
8
+
9
+ repository:
10
+ name: Repository
11
+ errors:
12
+ origin_not_setup: Repository with name 'origin' not found
13
+ upstream_not_setup: Repository with name 'upstream' not found
14
+ recommendations: "Check .git/cofig file"
15
+
16
+ pull_request:
17
+ name: Pull Request
18
+
19
+ commands:
20
+ checkup:
21
+ fail: You are not prepared!
22
+ success: "Congratulations, you are ready to ROCK :)"
23
+ compare:
24
+ fail: Something goes wrong!
25
+ updating: "Updating %{branch} → %{upstream}"
26
+ diverging: "Branches may diverging\nAdvice: switch to branch '%{branch}' and retry operation"
27
+ publish:
28
+ fail: Something goes wrong!
29
+ success: "Pull request successfuly created %{link}"
30
+ requesting: "Creating pull request %{branch} → %{upstream}"
31
+ updating: "Updating %{branch} → %{upstream}"
32
+ nothing: I have nothing to say ...
@@ -0,0 +1,32 @@
1
+ ru:
2
+ configuration:
3
+ name: Корфигурация
4
+ errors:
5
+ oauth_user_not_setup: Не установлена опция oauth_user
6
+ oauth_token_not_setup: Не установлена опция oauth_token
7
+ recommendations: "Проверьте секцию [abak-flow] в файле ~/.gitcofig"
8
+
9
+ repository:
10
+ name: Репозиторий
11
+ errors:
12
+ origin_not_setup: Репозиторий с именем 'origin' не найден
13
+ upstream_not_setup: Репозиторий с именем 'upstream' не найден
14
+ recommendations: Проверьте файл .git/cofig
15
+
16
+ pull_request:
17
+ name: Пулл реквест
18
+
19
+ commands:
20
+ checkup:
21
+ fail: "Вы не готовы!"
22
+ success: "Поздравляем, вы готовы чтобы жечь :)"
23
+ compare:
24
+ fail: Что-то пошло не так!
25
+ updating: "Обновление %{branch} → %{upstream}"
26
+ diverging: "Ветки могут расходиться.\nСовет: переключитесь в ветку '%{branch}' и повторите операцию"
27
+ publish:
28
+ fail: Что-то пошло не так!
29
+ success: "Пулл реквест успешно создан %{link}"
30
+ requesting: "Создание пулл реквеста %{branch} → %{upstream}"
31
+ updating: "Обновление %{branch} → %{upstream}"
32
+ nothing: Мне нечего добавить ...
@@ -0,0 +1,35 @@
1
+ # coding: utf-8
2
+ require "git"
3
+ require "octokit"
4
+
5
+ module Abak::Flow
6
+ class Manager
7
+
8
+ def initialize
9
+ # preload dependencies
10
+ configuration
11
+ repository
12
+
13
+ yield self if block_given?
14
+ end
15
+
16
+ def configuration
17
+ @configuration ||= Configuration.new(self)
18
+ end
19
+
20
+ def repository
21
+ @repository ||= Repository.new(self)
22
+ end
23
+
24
+ def github
25
+ @github ||= Octokit::Client.new(login: configuration.oauth_user,
26
+ oauth_token: configuration.oauth_token,
27
+ proxy: configuration.http_proxy)
28
+ end
29
+
30
+ def git
31
+ @git ||= Git.open(".")
32
+ end
33
+
34
+ end
35
+ end
@@ -0,0 +1,86 @@
1
+ # coding : utf-8
2
+ require "i18n"
3
+
4
+ # TODO : Нужен простой метод, для перевода без скоупа
5
+ module Abak::Flow
6
+ class Messages
7
+ extend Forwardable
8
+
9
+ attr_reader :scope, :elements
10
+
11
+ def initialize(scope)
12
+ Configuration.instance
13
+
14
+ @scope = scope
15
+ @elements = []
16
+ end
17
+
18
+ # Iterate elements from locale scope (translating online)
19
+ #
20
+ # Returns nothing
21
+ def each
22
+ raise ArgumentError, "No block given" unless block_given?
23
+
24
+ elements.each do |key|
25
+ yield translate(key)
26
+ end
27
+ end
28
+
29
+ # Put item to elements
30
+ #
31
+ # Returns Symbol
32
+ def push(element)
33
+ @elements << element
34
+ end
35
+ alias :<< :push
36
+
37
+ # section header from locale scope
38
+ #
39
+ # Returns String
40
+ def header
41
+ translate :header
42
+ end
43
+
44
+ # Print all elements from locale scope without header
45
+ #
46
+ # Returns Symbol
47
+ def to_s
48
+ return "" if elements.empty?
49
+
50
+ elements.collect { |element| translate *element } * "\n"
51
+ end
52
+
53
+ def print
54
+ return "" if elements.empty?
55
+
56
+ all_elements = []
57
+ elements.each_with_index do |element, index|
58
+ all_elements << "#{index + 1}. #{translate(*element)}"
59
+ end
60
+
61
+ all_elements * "\n"
62
+ end
63
+
64
+ # Print section header from locale scope and all elements from scope
65
+ #
66
+ # Returns String
67
+ def pretty_print
68
+ return "" if elements.empty?
69
+
70
+ [header, print] * "\n\n"
71
+ end
72
+ alias :pp :pretty_print
73
+
74
+ def translate(key, options = {})
75
+ I18n.t key, {scope: scope}.merge!(options)
76
+ end
77
+ alias :t :translate
78
+
79
+ def purge!
80
+ @elements = []
81
+ end
82
+
83
+ private
84
+ def_delegator :elements, :empty?
85
+ end
86
+ end