twirly 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +4 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +122 -0
- data/LICENSE +20 -0
- data/README.md +56 -0
- data/bin/twirly +6 -0
- data/config/initializers/trello.rb +4 -0
- data/lib/twirly/cli.rb +22 -0
- data/lib/twirly/commands/base.rb +14 -0
- data/lib/twirly/commands/fetch_user.rb +9 -0
- data/lib/twirly/commands/pick.rb +9 -0
- data/lib/twirly/commands/pull.rb +9 -0
- data/lib/twirly/commands.rb +6 -0
- data/lib/twirly/compiler.rb +26 -0
- data/lib/twirly/helpers/youtube.rb +37 -0
- data/lib/twirly/helpers.rb +3 -0
- data/lib/twirly/post.rb +81 -0
- data/lib/twirly/serializers/post.rb +21 -0
- data/lib/twirly/serializers/user.rb +20 -0
- data/lib/twirly/serializers.rb +6 -0
- data/lib/twirly/user.rb +31 -0
- data/lib/twirly/version.rb +3 -0
- data/lib/twirly.rb +45 -0
- data/spec/cli_spec.rb +24 -0
- data/spec/commands/fetch_user_spec.rb +16 -0
- data/spec/commands/pick_spec.rb +16 -0
- data/spec/commands/pull_spec.rb +10 -0
- data/spec/dummy/.bowerrc +3 -0
- data/spec/dummy/.gitignore +1 -0
- data/spec/dummy/Gemfile +12 -0
- data/spec/dummy/Gemfile.lock +116 -0
- data/spec/dummy/Guardfile +10 -0
- data/spec/dummy/assets/javascripts/app.coffee +3 -0
- data/spec/dummy/assets/javascripts/router.coffee +27 -0
- data/spec/dummy/assets/stylesheets/index.css.scss +17 -0
- data/spec/dummy/assets/stylesheets/partials/_header.css.scss +20 -0
- data/spec/dummy/assets/stylesheets/partials/_post.css.scss +19 -0
- data/spec/dummy/assets/stylesheets/partials/_reset.css.scss +425 -0
- data/spec/dummy/source/.gitkeep +0 -0
- data/spec/dummy/vendor/assets/bower_components/backbone/backbone.js +1608 -0
- data/spec/dummy/vendor/assets/bower_components/backbone/bower.json +9 -0
- data/spec/dummy/vendor/assets/bower_components/backbone/index.js +1 -0
- data/spec/dummy/vendor/assets/bower_components/jquery/bower.json +27 -0
- data/spec/dummy/vendor/assets/bower_components/jquery/dist/jquery.min.js +5 -0
- data/spec/dummy/vendor/assets/bower_components/underscore/bower.json +8 -0
- data/spec/dummy/vendor/assets/bower_components/underscore/underscore.js +1343 -0
- data/spec/factories/post.rb +9 -0
- data/spec/factories/trello/attachment.rb +17 -0
- data/spec/factories/trello/board.rb +20 -0
- data/spec/factories/trello/card.rb +56 -0
- data/spec/factories/trello/label.rb +19 -0
- data/spec/factories/trello/member.rb +16 -0
- data/spec/factories/user.rb +9 -0
- data/spec/post_spec.rb +155 -0
- data/spec/serializers/post_spec.rb +41 -0
- data/spec/serializers/user_spec.rb +34 -0
- data/spec/spec_helper.rb +19 -0
- data/spec/user_spec.rb +43 -0
- data/twirly.gemspec +38 -0
- data/twirly.yml.sample +4 -0
- metadata +324 -0
@@ -0,0 +1,17 @@
|
|
1
|
+
FactoryGirl.define do
|
2
|
+
factory :trello_attachment, class: Trello::Attachment do
|
3
|
+
skip_create
|
4
|
+
|
5
|
+
name { Faker::Lorem.word << '.png' }
|
6
|
+
id { SecureRandom.hex }
|
7
|
+
url 'https://trello-attachments.s3.amazonws.com/koko.png'
|
8
|
+
bytes { Random.new.rand(100..100_100) }
|
9
|
+
date { Time.now.to_s }
|
10
|
+
is_upload true
|
11
|
+
|
12
|
+
initialize_with do
|
13
|
+
attachment = Trello::Attachment.new attributes.stringify_keys
|
14
|
+
attachment
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
FactoryGirl.define do
|
2
|
+
factory :trello_board, class: Trello::Board do
|
3
|
+
skip_create
|
4
|
+
|
5
|
+
id { SecureRandom.hex }
|
6
|
+
short_id
|
7
|
+
name { "some board - #{short_id}" }
|
8
|
+
description 'this board is so great'
|
9
|
+
closed false
|
10
|
+
url "https://trello.com/b/NrYMTajk/foo-bar"
|
11
|
+
short_url "https://trello.com/b/NrYMTajk"
|
12
|
+
organization_id "53779c553c97bc8a506f83df"
|
13
|
+
|
14
|
+
initialize_with do
|
15
|
+
board = Trello::Board.new
|
16
|
+
attributes.each_pair { |k, v| board.attributes[k] = v }
|
17
|
+
board
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
FactoryGirl.define do
|
2
|
+
sequence :short_id
|
3
|
+
end
|
4
|
+
|
5
|
+
FactoryGirl.define do
|
6
|
+
factory :trello_card, class: Trello::Card do
|
7
|
+
skip_create
|
8
|
+
|
9
|
+
id { SecureRandom.hex }
|
10
|
+
short_id
|
11
|
+
name { "some card - #{short_id}" }
|
12
|
+
desc "---\ntags: pathway to [_], wesser\n---\n\n{% youtube 6TncafSqfyo %}"
|
13
|
+
due { Time.now }
|
14
|
+
closed false
|
15
|
+
url "https://trello.com/c/NrYMTajk/6-the-mushrooms-yard-of-my-head"
|
16
|
+
short_url "https://trello.com/c/NrYMTajk"
|
17
|
+
board_id "53779c553c97bc8a506f83df"
|
18
|
+
member_ids ["51597b21213b313631005042"]
|
19
|
+
list_id "53779c553c97bc8a506f83e0"
|
20
|
+
pos nil
|
21
|
+
last_activity_date { Time.now }
|
22
|
+
card_labels []
|
23
|
+
labels []
|
24
|
+
cover_image_id nil
|
25
|
+
|
26
|
+
association :attachments, factory: :trello_attachment
|
27
|
+
|
28
|
+
trait :published do
|
29
|
+
due { (DateTime.now - 1).to_time }
|
30
|
+
|
31
|
+
card_labels do
|
32
|
+
[ { name: 'published' } ]
|
33
|
+
end
|
34
|
+
|
35
|
+
labels do
|
36
|
+
[ { name: 'published' } ]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
trait :unpublished do
|
41
|
+
due nil
|
42
|
+
end
|
43
|
+
|
44
|
+
trait :with_attachments do
|
45
|
+
after(:create) do |card|
|
46
|
+
card.stub(:attachments).and_return create_list(:trello_attachment, 5)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
initialize_with do
|
51
|
+
card = Trello::Card.new
|
52
|
+
attributes.each_pair { |k, v| card.attributes[k] = v }
|
53
|
+
card
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
FactoryGirl.define do
|
2
|
+
factory :trello_label, class: Trello::Label do
|
3
|
+
skip_create
|
4
|
+
|
5
|
+
name { "some label - #{short_id}" }
|
6
|
+
color { %w(red green purple).sample }
|
7
|
+
|
8
|
+
trait :published do
|
9
|
+
name 'published'
|
10
|
+
color 'green'
|
11
|
+
end
|
12
|
+
|
13
|
+
initialize_with do
|
14
|
+
label = Trello::Label.new
|
15
|
+
attributes.each_pair { |k, v| card.attributes[k] = v }
|
16
|
+
label
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
FactoryGirl.define do
|
2
|
+
factory :trello_member, class: Trello::Member do
|
3
|
+
skip_create
|
4
|
+
|
5
|
+
id { SecureRandom.hex }
|
6
|
+
username { Faker::Internet.user_name }
|
7
|
+
email { Faker::Internet.free_email }
|
8
|
+
bio { Faker::Lorem.sentence }
|
9
|
+
|
10
|
+
initialize_with do
|
11
|
+
member = Trello::Member.new
|
12
|
+
attributes.each_pair { |k, v| member.attributes[k] = v }
|
13
|
+
member
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/spec/post_spec.rb
ADDED
@@ -0,0 +1,155 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Twirly::Post do
|
4
|
+
let(:trello_board) { create(:trello_board) }
|
5
|
+
let(:trello_card) { create(:trello_card) }
|
6
|
+
let(:front_matter_content) do
|
7
|
+
<<-YAML.strip_heredoc.strip
|
8
|
+
---
|
9
|
+
important: true
|
10
|
+
tags: idm, punk, electro
|
11
|
+
---
|
12
|
+
YAML
|
13
|
+
end
|
14
|
+
|
15
|
+
let(:markdown_content) do
|
16
|
+
<<-MDN.strip_heredoc.strip
|
17
|
+
# A post about cats
|
18
|
+
> Everybody loves cats
|
19
|
+
{% youtube 320 280 4-IpnaqBhT4 %}
|
20
|
+
MDN
|
21
|
+
end
|
22
|
+
|
23
|
+
let(:post) { Twirly::Post.new(trello_card) }
|
24
|
+
subject { post }
|
25
|
+
|
26
|
+
describe '#card' do
|
27
|
+
it 'returns a Trello::Card' do
|
28
|
+
expect(subject.card.class).to eq(Trello::Card)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe '#title' do
|
33
|
+
it "is delegated to the card's name" do
|
34
|
+
expect(subject.title).to eq(subject.card.name)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe '#updated_at' do
|
39
|
+
it "is delegated to the card's last_activity_date" do
|
40
|
+
expect(subject.updated_at).to eq(subject.card.last_activity_date)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe '#created_at' do
|
45
|
+
it "is delegated to the card's due" do
|
46
|
+
expect(subject.created_at).to eq(subject.card.due)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe '#published_at' do
|
51
|
+
it "is delegated to the card's due" do
|
52
|
+
expect(subject.published_at).to eq(subject.card.due)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe '#card_id' do
|
57
|
+
it "is delegated to the card's id" do
|
58
|
+
expect(subject.card_id).to eq(subject.card.short_id)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe '#short_published_at' do
|
63
|
+
subject { post.short_published_at }
|
64
|
+
|
65
|
+
it { expect(subject).to eq(trello_card.due.strftime('%Y-%m-%d')) }
|
66
|
+
end
|
67
|
+
|
68
|
+
describe '#slug' do
|
69
|
+
subject { post.slug }
|
70
|
+
let(:slug) {"#{post.short_published_at}-#{post.title.parameterize}-#{post.card_id}" }
|
71
|
+
|
72
|
+
it { expect(subject).to eq(slug) }
|
73
|
+
end
|
74
|
+
|
75
|
+
describe '#authors' do
|
76
|
+
before do
|
77
|
+
subject.card.stub(:members).and_return(create_list(:trello_member, 3))
|
78
|
+
end
|
79
|
+
|
80
|
+
it "returns the decorated as Twirly::User(s) card members" do
|
81
|
+
expect(subject.authors.map(&:username))
|
82
|
+
.to match_array(subject.card.members.map(&:username))
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
describe '#tags' do
|
87
|
+
pending
|
88
|
+
end
|
89
|
+
|
90
|
+
describe '#body' do
|
91
|
+
pending
|
92
|
+
end
|
93
|
+
|
94
|
+
describe '#published?' do
|
95
|
+
context 'card is published (has published_at and the "published" label' do
|
96
|
+
let(:subject) do
|
97
|
+
post = Twirly::Post.new(create(:trello_card, :published))
|
98
|
+
post.card.stub(:labels).and_return([double(name: 'published')])
|
99
|
+
post
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'returns true' do
|
103
|
+
expect(subject).to be_published
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
context 'card is not published (has published_at and the "published" label' do
|
108
|
+
let(:subject) { Twirly::Post.new(create(:trello_card, :unpublished)) }
|
109
|
+
|
110
|
+
it 'returns false' do
|
111
|
+
expect(subject).to_not be_published
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
describe '.published' do
|
117
|
+
let(:unpublished_cards) do
|
118
|
+
create_list(:trello_card, 3, :unpublished).map do |card|
|
119
|
+
card.stub(:labels).and_return([])
|
120
|
+
card
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
let(:published_cards) do
|
125
|
+
create_list(:trello_card, 4, :published).map do |card|
|
126
|
+
card.stub(:labels).and_return([double(name: 'published')])
|
127
|
+
card
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
before do
|
132
|
+
Trello::Board.stub(:find).and_return(trello_board)
|
133
|
+
Twirly.board.stub(:cards).and_return(unpublished_cards + published_cards)
|
134
|
+
end
|
135
|
+
|
136
|
+
it 'returns only posts decorating published cards' do
|
137
|
+
expect(Twirly::Post.published.map(&:card_id)).
|
138
|
+
to match_array(published_cards.map(&:short_id))
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
describe '.find' do
|
143
|
+
let(:matching_card) { create(:trello_card, short_id: 42) }
|
144
|
+
let(:non_matching_card) { create(:trello_card, short_id: 404) }
|
145
|
+
|
146
|
+
before do
|
147
|
+
Trello::Board.stub(:find).and_return(trello_board)
|
148
|
+
Twirly.board.stub(:cards).and_return([matching_card, non_matching_card])
|
149
|
+
end
|
150
|
+
|
151
|
+
it 'returns a card from the registered board with a matching trello short_id' do
|
152
|
+
expect(Twirly::Post.find(42).card_id).to eq(42)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Twirly::Serializers::Post do
|
4
|
+
let(:trello_board) { create(:trello_board) }
|
5
|
+
let(:trello_card) { create(:trello_card, :with_attachments) }
|
6
|
+
|
7
|
+
before do
|
8
|
+
trello_card.stub_chain(:list, :name).and_return 'music'
|
9
|
+
trello_card.stub(:labels).and_return([double(name: 'post-punk')])
|
10
|
+
end
|
11
|
+
|
12
|
+
let(:post) { Twirly::Post.new(trello_card) }
|
13
|
+
|
14
|
+
describe '#as_json' do
|
15
|
+
subject { post.as_json }
|
16
|
+
|
17
|
+
it 'is a Hash' do
|
18
|
+
expect(subject.as_json).to be_a(Hash)
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'has a root key' do
|
22
|
+
expect(subject[:post]).to be
|
23
|
+
end
|
24
|
+
|
25
|
+
describe 'representation attributes' do
|
26
|
+
subject { post.as_json[:post] }
|
27
|
+
|
28
|
+
its(:keys) { should match_array(%w[card_id title category tags
|
29
|
+
updated_at published_at].
|
30
|
+
map(&:to_sym)) }
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe '#to_json' do
|
35
|
+
subject { post.to_json }
|
36
|
+
|
37
|
+
it 'is a String' do
|
38
|
+
expect(subject.to_json).to be_a(String)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Twirly::Serializers::User do
|
4
|
+
let(:trello_member) { create(:trello_member) }
|
5
|
+
|
6
|
+
let(:user) { Twirly::User.new(trello_member) }
|
7
|
+
|
8
|
+
describe '#as_json' do
|
9
|
+
subject { user.as_json }
|
10
|
+
|
11
|
+
it 'is a Hash' do
|
12
|
+
expect(subject.as_json).to be_a(Hash)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'has a root key' do
|
16
|
+
expect(subject[:user]).to be
|
17
|
+
end
|
18
|
+
|
19
|
+
describe 'representation attributes' do
|
20
|
+
subject { user.as_json[:user] }
|
21
|
+
|
22
|
+
its(:keys) { should match_array(%w[id username full_name bio avatar_url].
|
23
|
+
map(&:to_sym)) }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe '#to_json' do
|
28
|
+
subject { user.to_json }
|
29
|
+
|
30
|
+
it 'is a String' do
|
31
|
+
expect(subject.to_json).to be_a(String)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'twirly'
|
2
|
+
require 'factory_girl'
|
3
|
+
require 'faker'
|
4
|
+
|
5
|
+
RSpec.configure do |config|
|
6
|
+
# Formatting
|
7
|
+
config.formatter = :documentation
|
8
|
+
config.color_enabled = true
|
9
|
+
|
10
|
+
# Filtering
|
11
|
+
config.run_all_when_everything_filtered = true
|
12
|
+
config.filter_run focus: true
|
13
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
14
|
+
|
15
|
+
Dir['./spec/support/**/*.rb'].each(&method(:require))
|
16
|
+
Dir['./spec/factories/**/*.rb'].each(&method(:require))
|
17
|
+
|
18
|
+
config.include FactoryGirl::Syntax::Methods
|
19
|
+
end
|
data/spec/user_spec.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Twirly::User do
|
4
|
+
let(:trello_member) { create(:trello_member) }
|
5
|
+
|
6
|
+
subject { Twirly::User.new(trello_member) }
|
7
|
+
|
8
|
+
describe '#member' do
|
9
|
+
it 'returns a Trello::Member' do
|
10
|
+
expect(subject.member.class).to eq(Trello::Member)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe '.all' do
|
15
|
+
let(:board_members) { create_list(:trello_member, 3) }
|
16
|
+
let(:trello_board) { create(:trello_board) }
|
17
|
+
|
18
|
+
before do
|
19
|
+
Trello::Board.stub(:find).and_return(trello_board)
|
20
|
+
Twirly.board.stub(:members).and_return(board_members)
|
21
|
+
Twirly::User.any_instance.stub(:refresh!)
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'returns only users decorating board members' do
|
25
|
+
expect(Twirly::User.all.map(&:username)).
|
26
|
+
to match_array(board_members.map(&:username))
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe '.find_by_username' do
|
31
|
+
let(:matching_member) { create(:trello_member, username: 'zorbash') }
|
32
|
+
let(:non_matching_member) { create(:trello_member, username: 'zoidberg') }
|
33
|
+
|
34
|
+
before do
|
35
|
+
Twirly.board.stub(:members).and_return([matching_member, non_matching_member])
|
36
|
+
Twirly::User.any_instance.stub(:refresh!)
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'returns a user from the registered board with a matching trello username' do
|
40
|
+
expect(Twirly::User.find_by_username('zorbash').username).to eq('zorbash')
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/twirly.gemspec
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'twirly/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'twirly'
|
8
|
+
spec.version = Twirly::VERSION
|
9
|
+
spec.authors = ['Dimitris Zorbas']
|
10
|
+
spec.email = ['zorbash@skroutz.gr']
|
11
|
+
spec.description = <<-DESC
|
12
|
+
Publishing platform using trello
|
13
|
+
DESC
|
14
|
+
|
15
|
+
spec.summary = %q{Publishing platform using trello}
|
16
|
+
spec.homepage = 'https://github.com/Zorbash/twirly'
|
17
|
+
spec.license = 'MIT'
|
18
|
+
|
19
|
+
spec.files = `git ls-files`.split($/)
|
20
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
21
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
22
|
+
spec.require_paths = ['lib']
|
23
|
+
|
24
|
+
spec.add_development_dependency 'bundler', '~> 1.7'
|
25
|
+
spec.add_development_dependency 'rake'
|
26
|
+
spec.add_development_dependency 'pry'
|
27
|
+
spec.add_development_dependency 'pry-nav'
|
28
|
+
spec.add_development_dependency 'rspec', '~> 2.14.1'
|
29
|
+
spec.add_development_dependency 'guard-rspec'
|
30
|
+
spec.add_development_dependency 'rubocop'
|
31
|
+
spec.add_development_dependency 'faker'
|
32
|
+
spec.add_development_dependency 'factory_girl'
|
33
|
+
|
34
|
+
spec.add_dependency 'thor', '~> 1.19'
|
35
|
+
spec.add_dependency 'ruby-trello', '~> 1.1'
|
36
|
+
spec.add_dependency 'liquid', '~> 3.0'
|
37
|
+
spec.add_dependency 'json', '>= 1.8.1'
|
38
|
+
end
|
data/twirly.yml.sample
ADDED