Upgrade Rails to 5.2.3 (#1408)
This commit is contained in:
parent
509c11e86f
commit
3a53d5797e
31 changed files with 345 additions and 210 deletions
5
Gemfile
5
Gemfile
|
|
@ -14,7 +14,7 @@ end
|
|||
|
||||
gem "actionpack-action_caching", "~> 1.2"
|
||||
gem "active_record_union", "~> 1.3"
|
||||
gem "acts-as-taggable-on", "~> 5.0"
|
||||
gem "acts-as-taggable-on", "~> 6.0"
|
||||
gem "acts_as_follower", github: "thepracticaldev/acts_as_follower", branch: "master"
|
||||
gem "addressable", "~> 2.5", ">= 2.5.2"
|
||||
gem "administrate", "~> 0.11"
|
||||
|
|
@ -25,6 +25,7 @@ gem "algorithmia", "~> 1.0"
|
|||
gem "ancestry", "~> 3.0"
|
||||
gem "autoprefixer-rails", "~> 9.4"
|
||||
gem "aws-sdk-lambda", "~> 1.16" # Just Lambda. For more, install aws-sdk gem
|
||||
gem "bootsnap", ">= 1.1.0", require: false
|
||||
gem "bourbon", "~> 5.1"
|
||||
gem "buffer", "~> 0.1"
|
||||
gem "carrierwave", "~> 1.3"
|
||||
|
|
@ -73,7 +74,7 @@ gem "pusher", "~> 1.3"
|
|||
gem "pusher-push-notifications", "~> 1.0"
|
||||
gem "rack-host-redirect", "~> 1.3"
|
||||
gem "rack-timeout", "~> 0.5"
|
||||
gem "rails", "~> 5.1.6"
|
||||
gem "rails", "~> 5.2", ">= 5.2.3"
|
||||
gem "rails-assets-airbrake-js-client", "~> 1.5", source: "https://rails-assets.org"
|
||||
gem "rails-observers", "~> 0.1"
|
||||
gem "recaptcha", "~> 4.13", require: "recaptcha/rails"
|
||||
|
|
|
|||
97
Gemfile.lock
97
Gemfile.lock
|
|
@ -19,53 +19,57 @@ GEM
|
|||
remote: https://rails-assets.org/
|
||||
specs:
|
||||
CFPropertyList (2.3.6)
|
||||
actioncable (5.1.6.2)
|
||||
actionpack (= 5.1.6.2)
|
||||
actioncable (5.2.3)
|
||||
actionpack (= 5.2.3)
|
||||
nio4r (~> 2.0)
|
||||
websocket-driver (~> 0.6.1)
|
||||
actionmailer (5.1.6.2)
|
||||
actionpack (= 5.1.6.2)
|
||||
actionview (= 5.1.6.2)
|
||||
activejob (= 5.1.6.2)
|
||||
websocket-driver (>= 0.6.1)
|
||||
actionmailer (5.2.3)
|
||||
actionpack (= 5.2.3)
|
||||
actionview (= 5.2.3)
|
||||
activejob (= 5.2.3)
|
||||
mail (~> 2.5, >= 2.5.4)
|
||||
rails-dom-testing (~> 2.0)
|
||||
actionpack (5.1.6.2)
|
||||
actionview (= 5.1.6.2)
|
||||
activesupport (= 5.1.6.2)
|
||||
actionpack (5.2.3)
|
||||
actionview (= 5.2.3)
|
||||
activesupport (= 5.2.3)
|
||||
rack (~> 2.0)
|
||||
rack-test (>= 0.6.3)
|
||||
rails-dom-testing (~> 2.0)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
||||
actionpack-action_caching (1.2.0)
|
||||
actionpack (>= 4.0.0, < 6)
|
||||
actionview (5.1.6.2)
|
||||
activesupport (= 5.1.6.2)
|
||||
actionview (5.2.3)
|
||||
activesupport (= 5.2.3)
|
||||
builder (~> 3.1)
|
||||
erubi (~> 1.4)
|
||||
rails-dom-testing (~> 2.0)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.0.3)
|
||||
active_record_union (1.3.0)
|
||||
activerecord (>= 4.0)
|
||||
activejob (5.1.6.2)
|
||||
activesupport (= 5.1.6.2)
|
||||
activejob (5.2.3)
|
||||
activesupport (= 5.2.3)
|
||||
globalid (>= 0.3.6)
|
||||
activemodel (5.1.6.2)
|
||||
activesupport (= 5.1.6.2)
|
||||
activemodel (5.2.3)
|
||||
activesupport (= 5.2.3)
|
||||
activemodel-serializers-xml (1.0.2)
|
||||
activemodel (> 5.x)
|
||||
activesupport (> 5.x)
|
||||
builder (~> 3.1)
|
||||
activerecord (5.1.6.2)
|
||||
activemodel (= 5.1.6.2)
|
||||
activesupport (= 5.1.6.2)
|
||||
arel (~> 8.0)
|
||||
activesupport (5.1.6.2)
|
||||
activerecord (5.2.3)
|
||||
activemodel (= 5.2.3)
|
||||
activesupport (= 5.2.3)
|
||||
arel (>= 9.0)
|
||||
activestorage (5.2.3)
|
||||
actionpack (= 5.2.3)
|
||||
activerecord (= 5.2.3)
|
||||
marcel (~> 0.3.1)
|
||||
activesupport (5.2.3)
|
||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||
i18n (>= 0.7, < 2)
|
||||
minitest (~> 5.1)
|
||||
tzinfo (~> 1.1)
|
||||
acts-as-taggable-on (5.0.0)
|
||||
activerecord (>= 4.2.8)
|
||||
acts-as-taggable-on (6.0.0)
|
||||
activerecord (~> 5.0)
|
||||
addressable (2.5.2)
|
||||
public_suffix (>= 2.0.2, < 4.0)
|
||||
administrate (0.11.0)
|
||||
|
|
@ -96,7 +100,7 @@ GEM
|
|||
algoliasearch (1.26.0)
|
||||
httpclient (~> 2.8, >= 2.8.3)
|
||||
json (>= 1.5.1)
|
||||
algoliasearch-rails (1.21.0)
|
||||
algoliasearch-rails (1.22.0)
|
||||
algoliasearch (>= 1.17.0, < 2.0.0)
|
||||
json (>= 1.5.1)
|
||||
algorithmia (1.0.1)
|
||||
|
|
@ -109,7 +113,7 @@ GEM
|
|||
thor (~> 0.18)
|
||||
archive-zip (0.11.0)
|
||||
io-like (~> 0.3.0)
|
||||
arel (8.0.0)
|
||||
arel (9.0.0)
|
||||
ast (2.4.0)
|
||||
autoprefixer-rails (9.4.3)
|
||||
execjs
|
||||
|
|
@ -146,6 +150,8 @@ GEM
|
|||
bindex (0.5.0)
|
||||
binding_of_caller (0.8.0)
|
||||
debug_inspector (>= 0.0.1)
|
||||
bootsnap (1.4.2)
|
||||
msgpack (~> 1.0)
|
||||
bourbon (5.1.0)
|
||||
sass (~> 3.4)
|
||||
thor (~> 0.19)
|
||||
|
|
@ -610,6 +616,8 @@ GEM
|
|||
lumberjack (1.0.13)
|
||||
mail (2.7.1)
|
||||
mini_mime (>= 0.1.1)
|
||||
marcel (0.3.3)
|
||||
mimemagic (~> 0.3.2)
|
||||
memoist (0.16.0)
|
||||
memoizable (0.4.2)
|
||||
thread_safe (~> 0.3, >= 0.3.1)
|
||||
|
|
@ -618,6 +626,7 @@ GEM
|
|||
mime-types (3.2.2)
|
||||
mime-types-data (~> 3.2015)
|
||||
mime-types-data (3.2018.0812)
|
||||
mimemagic (0.3.3)
|
||||
mini_mime (1.0.1)
|
||||
mini_portile2 (2.4.0)
|
||||
minitest (5.11.3)
|
||||
|
|
@ -635,7 +644,7 @@ GEM
|
|||
connection_pool (~> 2.2)
|
||||
netrc (0.11.0)
|
||||
nio4r (2.3.1)
|
||||
nokogiri (1.10.1)
|
||||
nokogiri (1.10.2)
|
||||
mini_portile2 (~> 2.4.0)
|
||||
notiffany (0.1.1)
|
||||
nenv (~> 0.1)
|
||||
|
|
@ -706,17 +715,18 @@ GEM
|
|||
rack-test (1.1.0)
|
||||
rack (>= 1.0, < 3)
|
||||
rack-timeout (0.5.1)
|
||||
rails (5.1.6.2)
|
||||
actioncable (= 5.1.6.2)
|
||||
actionmailer (= 5.1.6.2)
|
||||
actionpack (= 5.1.6.2)
|
||||
actionview (= 5.1.6.2)
|
||||
activejob (= 5.1.6.2)
|
||||
activemodel (= 5.1.6.2)
|
||||
activerecord (= 5.1.6.2)
|
||||
activesupport (= 5.1.6.2)
|
||||
rails (5.2.3)
|
||||
actioncable (= 5.2.3)
|
||||
actionmailer (= 5.2.3)
|
||||
actionpack (= 5.2.3)
|
||||
actionview (= 5.2.3)
|
||||
activejob (= 5.2.3)
|
||||
activemodel (= 5.2.3)
|
||||
activerecord (= 5.2.3)
|
||||
activestorage (= 5.2.3)
|
||||
activesupport (= 5.2.3)
|
||||
bundler (>= 1.3.0)
|
||||
railties (= 5.1.6.2)
|
||||
railties (= 5.2.3)
|
||||
sprockets-rails (>= 2.0.0)
|
||||
rails-assets-airbrake-js-client (1.5.0)
|
||||
rails-dom-testing (2.0.3)
|
||||
|
|
@ -726,12 +736,12 @@ GEM
|
|||
loofah (~> 2.2, >= 2.2.2)
|
||||
rails-observers (0.1.5)
|
||||
activemodel (>= 4.0)
|
||||
railties (5.1.6.2)
|
||||
actionpack (= 5.1.6.2)
|
||||
activesupport (= 5.1.6.2)
|
||||
railties (5.2.3)
|
||||
actionpack (= 5.2.3)
|
||||
activesupport (= 5.2.3)
|
||||
method_source
|
||||
rake (>= 0.8.7)
|
||||
thor (>= 0.18.1, < 2.0)
|
||||
thor (>= 0.19.0, < 2.0)
|
||||
rainbow (3.0.0)
|
||||
rake (12.3.2)
|
||||
rb-fsevent (0.10.3)
|
||||
|
|
@ -951,7 +961,7 @@ GEM
|
|||
webpush (0.3.7)
|
||||
hkdf (~> 0.2)
|
||||
jwt (~> 2.0)
|
||||
websocket-driver (0.6.5)
|
||||
websocket-driver (0.7.0)
|
||||
websocket-extensions (>= 0.1.0)
|
||||
websocket-extensions (0.1.3)
|
||||
xml-simple (1.1.5)
|
||||
|
|
@ -966,7 +976,7 @@ PLATFORMS
|
|||
DEPENDENCIES
|
||||
actionpack-action_caching (~> 1.2)
|
||||
active_record_union (~> 1.3)
|
||||
acts-as-taggable-on (~> 5.0)
|
||||
acts-as-taggable-on (~> 6.0)
|
||||
acts_as_follower!
|
||||
addressable (~> 2.5, >= 2.5.2)
|
||||
administrate (~> 0.11)
|
||||
|
|
@ -980,6 +990,7 @@ DEPENDENCIES
|
|||
aws-sdk-lambda (~> 1.16)
|
||||
better_errors (~> 2.5)
|
||||
binding_of_caller (~> 0.8)
|
||||
bootsnap (>= 1.1.0)
|
||||
bourbon (~> 5.1)
|
||||
brakeman (~> 4.4)
|
||||
buffer (~> 0.1)
|
||||
|
|
@ -1051,7 +1062,7 @@ DEPENDENCIES
|
|||
pusher-push-notifications (~> 1.0)
|
||||
rack-host-redirect (~> 1.3)
|
||||
rack-timeout (~> 0.5)
|
||||
rails (~> 5.1.6)
|
||||
rails (~> 5.2, >= 5.2.3)
|
||||
rails-assets-airbrake-js-client (~> 1.5)!
|
||||
rails-observers (~> 0.1)
|
||||
rb-fsevent (~> 0.10)
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ class Internal::UsersController < Internal::ApplicationController
|
|||
|
||||
def show
|
||||
@user = if params[:id] == "unmatched_mentee"
|
||||
MentorRelationship.unmatched_mentees.order("RANDOM()").first
|
||||
MentorRelationship.unmatched_mentees.order(Arel.sql("RANDOM()")).first
|
||||
else
|
||||
User.find(params[:id])
|
||||
end
|
||||
|
|
|
|||
|
|
@ -62,10 +62,12 @@ class PagesController < ApplicationController
|
|||
|
||||
def shecoded
|
||||
@top_articles = Article.tagged_with(%w[shecoded shecodedally theycoded], any: true).
|
||||
where(published: true, approved: true).where("published_at > ? AND score > ?", 3.weeks.ago, 28).order("RANDOM()").
|
||||
where(published: true, approved: true).where("published_at > ? AND score > ?", 3.weeks.ago, 28).
|
||||
order(Arel.sql("RANDOM()")).
|
||||
includes(:user).decorate
|
||||
@articles = Article.tagged_with(%w[shecoded shecodedally theycoded], any: true).
|
||||
where(published: true, approved: true).where("published_at > ? AND score > ?", 3.weeks.ago, -8).order("RANDOM()").
|
||||
where(published: true, approved: true).where("published_at > ? AND score > ?", 3.weeks.ago, -8).
|
||||
order(Arel.sql("RANDOM()")).
|
||||
where.not(id: @top_articles.pluck(:id)).
|
||||
includes(:user).decorate
|
||||
render layout: false
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ class StickyArticleCollection
|
|||
where(published: true).
|
||||
where.not(id: article.id, user_id: article.user_id).
|
||||
where("featured_number > ?", 5.days.ago.to_i).
|
||||
order("RANDOM()").
|
||||
order(Arel.sql("RANDOM()")).
|
||||
limit(8)
|
||||
end
|
||||
|
||||
|
|
@ -40,7 +40,7 @@ class StickyArticleCollection
|
|||
where(published: true).
|
||||
where.not(id: article.id, user_id: article.user_id).
|
||||
where("featured_number > ?", 5.days.ago.to_i).
|
||||
order("RANDOM()").
|
||||
order(Arel.sql("RANDOM()")).
|
||||
limit(10 - tag_articles.size)
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ class UnreadNotificationsEmailer
|
|||
# This will run once a day (defined outside the app)
|
||||
# only to users who have made at least one comment or article.
|
||||
# We can change this up later.
|
||||
users = User.where("comments_count > ? OR reactions_count > ?", 0, 0).order("RANDOM()").limit(num)
|
||||
users = User.where("comments_count > ? OR reactions_count > ?", 0, 0).order(Arel.sql("RANDOM()")).limit(num)
|
||||
users.find_each do |user|
|
||||
UnreadNotificationsEmailer.new(user).send_email_if_appropriate
|
||||
rescue StandardError => e
|
||||
|
|
|
|||
|
|
@ -11,10 +11,11 @@ class TweetTag < LiquidTagBase
|
|||
def render(_context)
|
||||
media_div = ""
|
||||
quote_div = ""
|
||||
|
||||
if @tweet.extended_entities_serialized.present? && @tweet.extended_entities_serialized[:media] && @tweet.extended_entities_serialized[:media].size == 1
|
||||
media_item = @tweet.extended_entities_serialized[:media].first
|
||||
if media_item[:type] == "animated_gif" || media_item[:type] == "video"
|
||||
play_butt = image_tag("/assets/play-butt.svg", class: "ltag__twitter-tweet__play-butt")
|
||||
play_butt = image_tag("/assets/play-butt.svg", class: "ltag__twitter-tweet__play-butt", alt: "Play butt")
|
||||
preview_div = "<div class='ltag__twitter-tweet__media--video-preview'><img src='#{media_item[:media_url_https]}'/>#{play_butt}</div>"
|
||||
video_div = "<div class='ltag__twitter-tweet__video'><video loop><source src='#{media_item[:video_info][:variants].last[:url]}' type='#{media_item[:video_info][:variants].last[:content_type]}' /></video></div>"
|
||||
media_div = "<div class='ltag__twitter-tweet__media ltag__twitter-tweet__media__video-wrapper'>#{preview_div}#{video_div}</div>"
|
||||
|
|
@ -31,6 +32,7 @@ class TweetTag < LiquidTagBase
|
|||
quoted_status = @tweet.full_fetched_object_serialized[:quoted_status]
|
||||
quote_div = "<div class='ltag__twitter-tweet__quote'><div class='ltag__twitter-tweet__quote__header'><span class='ltag__twitter-tweet__quote__header__name'>#{quoted_status[:user][:name]}</span> @#{quoted_status[:user][:screen_name]}</div>#{quoted_status[:full_text]}</div>"
|
||||
end
|
||||
|
||||
"<blockquote "\
|
||||
'class="ltag__twitter-tweet" data-url="https://twitter.com/' + @tweet.twitter_username + "/status/" + @id + '">'\
|
||||
+media_div + \
|
||||
|
|
@ -47,9 +49,9 @@ class TweetTag < LiquidTagBase
|
|||
'<div class="ltag__twitter-tweet__date">' + @tweet.tweeted_at.strftime("%H:%M %p - %d %b %Y") + "</div>"\
|
||||
+quote_div + \
|
||||
'<div class="ltag__twitter-tweet__actions">'\
|
||||
'<a href= "https://twitter.com/intent/tweet?in_reply_to=' + @id + '" class="ltag__twitter-tweet__actions__button">' + image_tag("/assets/twitter-reply-action.svg") + "</a>"\
|
||||
'<a href= "https://twitter.com/intent/retweet?tweet_id=' + @id + '" class="ltag__twitter-tweet__actions__button">' + image_tag("/assets/twitter-retweet-action.svg") + "</a>" + @tweet.retweet_count.to_s + \
|
||||
'<a href= "https://twitter.com/intent/like?tweet_id=' + @id + '" class="ltag__twitter-tweet__actions__button">' + image_tag("/assets/twitter-like-action.svg") + "</a>" + @tweet.favorite_count.to_s + \
|
||||
'<a href= "https://twitter.com/intent/tweet?in_reply_to=' + @id + '" class="ltag__twitter-tweet__actions__button">' + image_tag("/assets/twitter-reply-action.svg", alt: "Twitter reply action") + "</a>"\
|
||||
'<a href= "https://twitter.com/intent/retweet?tweet_id=' + @id + '" class="ltag__twitter-tweet__actions__button">' + image_tag("/assets/twitter-retweet-action.svg", alt: "Twitter retweet action") + "</a>" + @tweet.retweet_count.to_s + \
|
||||
'<a href= "https://twitter.com/intent/like?tweet_id=' + @id + '" class="ltag__twitter-tweet__actions__button">' + image_tag("/assets/twitter-like-action.svg", alt: "Twitter like action") + "</a>" + @tweet.favorite_count.to_s + \
|
||||
"</div>"\
|
||||
"</div>"\
|
||||
"</blockquote>"
|
||||
|
|
|
|||
|
|
@ -143,10 +143,6 @@ class ChatChannel < ApplicationRecord
|
|||
obj
|
||||
end
|
||||
|
||||
def pending_users_select_fields
|
||||
pending_users.select(:id, :username, :name)
|
||||
end
|
||||
|
||||
def channel_mod_ids
|
||||
mod_users.pluck(:id)
|
||||
end
|
||||
|
|
@ -161,4 +157,10 @@ class ChatChannel < ApplicationRecord
|
|||
id: membership.user_id
|
||||
}
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def pending_users_select_fields
|
||||
pending_users.select(:id, :username, :name, :updated_at)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ class HtmlVariant < ApplicationRecord
|
|||
end
|
||||
|
||||
def self.find_random_for_test(tags_array, group)
|
||||
where(group: group, approved: true, published: true, target_tag: tags_array).order("RANDOM()").first
|
||||
where(group: group, approved: true, published: true, target_tag: tags_array).order(Arel.sql("RANDOM()")).first
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ module Suggester
|
|||
where(published: true, featured: true).
|
||||
where("positive_reactions_count > ?", MIN_REACTION_COUNT).
|
||||
where("published_at > ?", 10.months.ago).
|
||||
order("RANDOM()")
|
||||
order(Arel.sql("RANDOM()"))
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ module Suggester
|
|||
Article.where(published: true, featured: true).
|
||||
includes(:user).
|
||||
where("positive_reactions_count > ?", MIN_HQ_REACTION_COUNT).
|
||||
order("RANDOM()").
|
||||
order(Arel.sql("RANDOM()")).
|
||||
limited_column_select.
|
||||
where.not(id: @not_ids).
|
||||
limit(num)
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ module Suggester
|
|||
group_one = User.select(:id, :name, :username, :profile_image, :summary).where(id: user_ids).
|
||||
order("reputation_modifier DESC").limit(20).to_a
|
||||
group_two = User.select(:id, :name, :username, :profile_image, :summary).where(id: user_ids).
|
||||
order("RANDOM()").limit(20).to_a
|
||||
order(Arel.sql("RANDOM()")).limit(20).to_a
|
||||
(group_one + group_two).uniq
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@
|
|||
</div>
|
||||
<% end %>
|
||||
<% cache("display-area-left-#{rand(5)}", expires_in: 5.minutes) do %>
|
||||
<% @left_sidebar_ad = DisplayAd.where(approved: true, published: true, placement_area: "sidebar_left").order("RANDOM()").first %>
|
||||
<% @left_sidebar_ad = DisplayAd.where(approved: true, published: true, placement_area: "sidebar_left").order(Arel.sql("RANDOM()")).first %>
|
||||
<% if @left_sidebar_ad %>
|
||||
<div class="widget">
|
||||
<div class="widget-body" style="margin-top:-6px">
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
</div>
|
||||
<% end %>
|
||||
<% cache("main-article-right-sidebar-discussions-#{params[:timeframe]}", expires_in: (params[:timeframe].blank? ? 120 : 360).seconds) do %>
|
||||
<% @sidebar_ad = DisplayAd.where(approved: true, published: true, placement_area: "sidebar_right").order("RANDOM()").first %>
|
||||
<% @sidebar_ad = DisplayAd.where(approved: true, published: true, placement_area: "sidebar_right").order(Arel.sql("RANDOM()")).first %>
|
||||
<% if @sidebar_ad %>
|
||||
<div class="widget">
|
||||
<div class="widget-body" style="margin-top:-6px">
|
||||
|
|
|
|||
150
bin/bundle
150
bin/bundle
|
|
@ -11,91 +11,91 @@
|
|||
require "rubygems"
|
||||
|
||||
m = Module.new do
|
||||
module_function
|
||||
module_function
|
||||
|
||||
def invoked_as_script?
|
||||
File.expand_path($0) == File.expand_path(__FILE__)
|
||||
def invoked_as_script?
|
||||
File.expand_path($0) == File.expand_path(__FILE__)
|
||||
end
|
||||
|
||||
def env_var_version
|
||||
ENV["BUNDLER_VERSION"]
|
||||
end
|
||||
|
||||
def cli_arg_version
|
||||
return unless invoked_as_script? # don't want to hijack other binstubs
|
||||
return unless "update".start_with?(ARGV.first || " ") # must be running `bundle update`
|
||||
bundler_version = nil
|
||||
update_index = nil
|
||||
ARGV.each_with_index do |a, i|
|
||||
if update_index && update_index.succ == i && a =~ Gem::Version::ANCHORED_VERSION_PATTERN
|
||||
bundler_version = a
|
||||
end
|
||||
next unless a =~ /\A--bundler(?:[= ](#{Gem::Version::VERSION_PATTERN}))?\z/
|
||||
bundler_version = $1 || ">= 0.a"
|
||||
update_index = i
|
||||
end
|
||||
bundler_version
|
||||
end
|
||||
|
||||
def env_var_version
|
||||
ENV["BUNDLER_VERSION"]
|
||||
def gemfile
|
||||
gemfile = ENV["BUNDLE_GEMFILE"]
|
||||
return gemfile if gemfile && !gemfile.empty?
|
||||
|
||||
File.expand_path("../../Gemfile", __FILE__)
|
||||
end
|
||||
|
||||
def lockfile
|
||||
lockfile =
|
||||
case File.basename(gemfile)
|
||||
when "gems.rb" then gemfile.sub(/\.rb$/, gemfile)
|
||||
else "#{gemfile}.lock"
|
||||
end
|
||||
File.expand_path(lockfile)
|
||||
end
|
||||
|
||||
def cli_arg_version
|
||||
return unless invoked_as_script? # don't want to hijack other binstubs
|
||||
return unless "update".start_with?(ARGV.first || " ") # must be running `bundle update`
|
||||
bundler_version = nil
|
||||
update_index = nil
|
||||
ARGV.each_with_index do |a, i|
|
||||
if update_index && update_index.succ == i && a =~ Gem::Version::ANCHORED_VERSION_PATTERN
|
||||
bundler_version = a
|
||||
end
|
||||
next unless a =~ /\A--bundler(?:[= ](#{Gem::Version::VERSION_PATTERN}))?\z/
|
||||
bundler_version = $1 || ">= 0.a"
|
||||
update_index = i
|
||||
end
|
||||
bundler_version
|
||||
end
|
||||
def lockfile_version
|
||||
return unless File.file?(lockfile)
|
||||
lockfile_contents = File.read(lockfile)
|
||||
return unless lockfile_contents =~ /\n\nBUNDLED WITH\n\s{2,}(#{Gem::Version::VERSION_PATTERN})\n/
|
||||
Regexp.last_match(1)
|
||||
end
|
||||
|
||||
def gemfile
|
||||
gemfile = ENV["BUNDLE_GEMFILE"]
|
||||
return gemfile if gemfile && !gemfile.empty?
|
||||
def bundler_version
|
||||
@bundler_version ||= begin
|
||||
env_var_version || cli_arg_version ||
|
||||
lockfile_version || "#{Gem::Requirement.default}.a"
|
||||
end
|
||||
end
|
||||
|
||||
File.expand_path("../Gemfile", __dir__)
|
||||
end
|
||||
def load_bundler!
|
||||
ENV["BUNDLE_GEMFILE"] ||= gemfile
|
||||
|
||||
def lockfile
|
||||
lockfile =
|
||||
case File.basename(gemfile)
|
||||
when "gems.rb" then gemfile.sub(/\.rb$/, gemfile)
|
||||
else "#{gemfile}.lock"
|
||||
end
|
||||
File.expand_path(lockfile)
|
||||
end
|
||||
# must dup string for RG < 1.8 compatibility
|
||||
activate_bundler(bundler_version.dup)
|
||||
end
|
||||
|
||||
def lockfile_version
|
||||
return unless File.file?(lockfile)
|
||||
lockfile_contents = File.read(lockfile)
|
||||
return unless lockfile_contents =~ /\n\nBUNDLED WITH\n\s{2,}(#{Gem::Version::VERSION_PATTERN})\n/
|
||||
Regexp.last_match(1)
|
||||
end
|
||||
def activate_bundler(bundler_version)
|
||||
if Gem::Version.correct?(bundler_version) && Gem::Version.new(bundler_version).release < Gem::Version.new("2.0")
|
||||
bundler_version = "< 2"
|
||||
end
|
||||
gem_error = activation_error_handling do
|
||||
gem "bundler", bundler_version
|
||||
end
|
||||
return if gem_error.nil?
|
||||
require_error = activation_error_handling do
|
||||
require "bundler/version"
|
||||
end
|
||||
return if require_error.nil? && Gem::Requirement.new(bundler_version).satisfied_by?(Gem::Version.new(Bundler::VERSION))
|
||||
warn "Activating bundler (#{bundler_version}) failed:\n#{gem_error.message}\n\nTo install the version of bundler this project requires, run `gem install bundler -v '#{bundler_version}'`"
|
||||
exit 42
|
||||
end
|
||||
|
||||
def bundler_version
|
||||
@bundler_version ||= begin
|
||||
env_var_version || cli_arg_version ||
|
||||
lockfile_version || "#{Gem::Requirement.default}.a"
|
||||
end
|
||||
end
|
||||
|
||||
def load_bundler!
|
||||
ENV["BUNDLE_GEMFILE"] ||= gemfile
|
||||
|
||||
# must dup string for RG < 1.8 compatibility
|
||||
activate_bundler(bundler_version.dup)
|
||||
end
|
||||
|
||||
def activate_bundler(bundler_version)
|
||||
if Gem::Version.correct?(bundler_version) && Gem::Version.new(bundler_version).release < Gem::Version.new("2.0")
|
||||
bundler_version = "< 2"
|
||||
end
|
||||
gem_error = activation_error_handling do
|
||||
gem "bundler", bundler_version
|
||||
end
|
||||
return if gem_error.nil?
|
||||
require_error = activation_error_handling do
|
||||
require "bundler/version"
|
||||
end
|
||||
return if require_error.nil? && Gem::Requirement.new(bundler_version).satisfied_by?(Gem::Version.new(Bundler::VERSION))
|
||||
warn "Activating bundler (#{bundler_version}) failed:\n#{gem_error.message}\n\nTo install the version of bundler this project requires, run `gem install bundler -v '#{bundler_version}'`"
|
||||
exit 42
|
||||
end
|
||||
|
||||
def activation_error_handling
|
||||
yield
|
||||
nil
|
||||
rescue StandardError, LoadError => e
|
||||
e
|
||||
end
|
||||
def activation_error_handling
|
||||
yield
|
||||
nil
|
||||
rescue StandardError, LoadError => e
|
||||
e
|
||||
end
|
||||
end
|
||||
|
||||
m.load_bundler!
|
||||
|
|
|
|||
11
bin/rails
11
bin/rails
|
|
@ -1,9 +1,4 @@
|
|||
#!/usr/bin/env ruby
|
||||
begin
|
||||
load File.expand_path("spring", __dir__)
|
||||
rescue LoadError => e
|
||||
raise unless e.message.include?("spring")
|
||||
end
|
||||
APP_PATH = File.expand_path("../config/application", __dir__)
|
||||
require_relative "../config/boot"
|
||||
require "rails/commands"
|
||||
APP_PATH = File.expand_path('../config/application', __dir__)
|
||||
require_relative '../config/boot'
|
||||
require 'rails/commands'
|
||||
|
|
|
|||
9
bin/rake
9
bin/rake
|
|
@ -1,9 +1,4 @@
|
|||
#!/usr/bin/env ruby
|
||||
begin
|
||||
load File.expand_path("spring", __dir__)
|
||||
rescue LoadError => e
|
||||
raise unless e.message.include?("spring")
|
||||
end
|
||||
require_relative "../config/boot"
|
||||
require "rake"
|
||||
require_relative '../config/boot'
|
||||
require 'rake'
|
||||
Rake.application.run
|
||||
|
|
|
|||
32
bin/setup
32
bin/setup
|
|
@ -1,10 +1,9 @@
|
|||
#!/usr/bin/env ruby
|
||||
require "pathname"
|
||||
require "fileutils"
|
||||
require 'fileutils'
|
||||
include FileUtils
|
||||
|
||||
# path to your application root.
|
||||
APP_ROOT = Pathname.new File.expand_path("..", __dir__)
|
||||
APP_ROOT = File.expand_path('..', __dir__)
|
||||
|
||||
def system!(*args)
|
||||
system(*args) || abort("\n== Command #{args} failed ==")
|
||||
|
|
@ -14,29 +13,24 @@ chdir APP_ROOT do
|
|||
# This script is a starting point to setup your application.
|
||||
# Add necessary setup steps to this file.
|
||||
|
||||
puts "== Installing dependencies =="
|
||||
system! "gem install bundler --conservative"
|
||||
system("bundle check") || system!("bundle install")
|
||||
puts '== Installing dependencies =='
|
||||
system! 'gem install bundler --conservative'
|
||||
system('bundle check') || system!('bundle install')
|
||||
|
||||
# Install JavaScript dependencies if using Yarn
|
||||
system("bin/yarn")
|
||||
system('bin/yarn')
|
||||
|
||||
# puts "\n== Copying sample files =="
|
||||
# unless File.exist?('config/database.yml')
|
||||
# cp 'config/database.yml.sample', 'config/database.yml'
|
||||
# end
|
||||
puts "\n== Copying sample files =="
|
||||
unless File.exist?('config/database.yml')
|
||||
cp 'config/database.yml.sample', 'config/database.yml'
|
||||
end
|
||||
|
||||
puts "\n== Preparing database =="
|
||||
system! "bin/rails db:setup"
|
||||
|
||||
puts "\n== Resolve Rails 5.0 & 5.1 specfic issue (open bin/setup for more info) =="
|
||||
# This solution was found here https://github.com/rails/rails/issues/26731#issuecomment-302446525
|
||||
# This line is to remove manual need to run a separate manual migration upon calling rspec
|
||||
system! "RAILS_ENV=test bin/rails db:environment:set"
|
||||
system! 'bin/rails db:setup'
|
||||
|
||||
puts "\n== Removing old logs and tempfiles =="
|
||||
system! "bin/rails log:clear tmp:clear"
|
||||
system! 'bin/rails log:clear tmp:clear'
|
||||
|
||||
puts "\n== Restarting application server =="
|
||||
system! "bin/rails restart"
|
||||
system! 'bin/rails restart'
|
||||
end
|
||||
|
|
|
|||
20
bin/update
20
bin/update
|
|
@ -1,10 +1,9 @@
|
|||
#!/usr/bin/env ruby
|
||||
require "pathname"
|
||||
require "fileutils"
|
||||
require 'fileutils'
|
||||
include FileUtils
|
||||
|
||||
# path to your application root.
|
||||
APP_ROOT = Pathname.new File.expand_path("..", __dir__)
|
||||
APP_ROOT = File.expand_path('..', __dir__)
|
||||
|
||||
def system!(*args)
|
||||
system(*args) || abort("\n== Command #{args} failed ==")
|
||||
|
|
@ -14,16 +13,19 @@ chdir APP_ROOT do
|
|||
# This script is a way to update your development environment automatically.
|
||||
# Add necessary update steps to this file.
|
||||
|
||||
puts "== Installing dependencies =="
|
||||
system! "gem install bundler --conservative"
|
||||
system("bundle check") || system!("bundle install")
|
||||
puts '== Installing dependencies =='
|
||||
system! 'gem install bundler --conservative'
|
||||
system('bundle check') || system!('bundle install')
|
||||
|
||||
# Install JavaScript dependencies if using Yarn
|
||||
# system('bin/yarn')
|
||||
|
||||
puts "\n== Updating database =="
|
||||
system! "bin/rails db:migrate"
|
||||
system! 'bin/rails db:migrate'
|
||||
|
||||
puts "\n== Removing old logs and tempfiles =="
|
||||
system! "bin/rails log:clear tmp:clear"
|
||||
system! 'bin/rails log:clear tmp:clear'
|
||||
|
||||
puts "\n== Restarting application server =="
|
||||
system! "bin/rails restart"
|
||||
system! 'bin/rails restart'
|
||||
end
|
||||
|
|
|
|||
16
bin/yarn
16
bin/yarn
|
|
@ -1,9 +1,11 @@
|
|||
#!/usr/bin/env ruby
|
||||
VENDOR_PATH = File.expand_path("..", __dir__)
|
||||
Dir.chdir(VENDOR_PATH) do
|
||||
exec "yarnpkg #{ARGV.join(' ')}"
|
||||
rescue Errno::ENOENT
|
||||
warn "Yarn executable was not detected in the system."
|
||||
warn "Download Yarn at https://yarnpkg.com/en/docs/install"
|
||||
exit 1
|
||||
APP_ROOT = File.expand_path('..', __dir__)
|
||||
Dir.chdir(APP_ROOT) do
|
||||
begin
|
||||
exec "yarnpkg", *ARGV
|
||||
rescue Errno::ENOENT
|
||||
$stderr.puts "Yarn executable was not detected in the system."
|
||||
$stderr.puts "Download Yarn at https://yarnpkg.com/en/docs/install"
|
||||
exit 1
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
|
||||
|
||||
require "bundler/setup" # Set up gems listed in the Gemfile.
|
||||
require "bootsnap/setup" # Speed up boot time by caching expensive operations.
|
||||
|
|
|
|||
|
|
@ -6,5 +6,5 @@ test:
|
|||
|
||||
production:
|
||||
adapter: redis
|
||||
url: redis://localhost:6379/1
|
||||
url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %>
|
||||
channel_prefix: practical_developer_production
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ Rails.application.configure do
|
|||
|
||||
config.cache_store = :memory_store
|
||||
config.public_file_server.headers = {
|
||||
"Cache-Control" => "public, max-age=172800"
|
||||
"Cache-Control" => "public, max-age=#{2.days.to_i}"
|
||||
}
|
||||
else
|
||||
config.action_controller.perform_caching = false
|
||||
|
|
@ -42,6 +42,9 @@ Rails.application.configure do
|
|||
# Raise an error on page load if there are pending migrations.
|
||||
config.active_record.migration_error = :page_load
|
||||
|
||||
# Highlight code that triggered database queries in logs.
|
||||
config.active_record.verbose_query_logs = true
|
||||
|
||||
# Debug mode disables concatenation and preprocessing of assets.
|
||||
# This option may cause significant delays in view rendering with a large
|
||||
# number of complex assets.
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ Rails.application.configure do
|
|||
# Configure static file server for tests with Cache-Control for performance.
|
||||
config.public_file_server.enabled = true
|
||||
config.public_file_server.headers = {
|
||||
"Cache-Control" => "public, max-age=3600"
|
||||
"Cache-Control" => "public, max-age=#{1.hour.to_i}"
|
||||
}
|
||||
|
||||
# Show full error reports and disable caching.
|
||||
|
|
@ -29,6 +29,10 @@ Rails.application.configure do
|
|||
|
||||
# Disable request forgery protection in test environment.
|
||||
config.action_controller.allow_forgery_protection = false
|
||||
|
||||
# Store uploaded files on the local file system in a temporary directory
|
||||
config.active_storage.service = :test
|
||||
|
||||
config.action_mailer.perform_caching = false
|
||||
|
||||
# Tell Action Mailer not to deliver emails to the real world.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
# Be sure to restart your server when you modify this file.
|
||||
|
||||
# ApplicationController.renderer.defaults.merge!(
|
||||
# http_host: 'example.org',
|
||||
# https: false
|
||||
# )
|
||||
# ActiveSupport::Reloader.to_prepare do
|
||||
# ApplicationController.renderer.defaults.merge!(
|
||||
# http_host: 'example.org',
|
||||
# https: false
|
||||
# )
|
||||
# end
|
||||
|
|
|
|||
25
config/initializers/content_security_policy.rb
Normal file
25
config/initializers/content_security_policy.rb
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
# Be sure to restart your server when you modify this file.
|
||||
|
||||
# Define an application-wide content security policy
|
||||
# For further information see the following documentation
|
||||
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy
|
||||
|
||||
# Rails.application.config.content_security_policy do |policy|
|
||||
# policy.default_src :self, :https
|
||||
# policy.font_src :self, :https, :data
|
||||
# policy.img_src :self, :https, :data
|
||||
# policy.object_src :none
|
||||
# policy.script_src :self, :https
|
||||
# policy.style_src :self, :https
|
||||
|
||||
# # Specify URI for violation reports
|
||||
# # policy.report_uri "/csp-violation-report-endpoint"
|
||||
# end
|
||||
|
||||
# If you are using UJS then enable automatic nonce generation
|
||||
# Rails.application.config.content_security_policy_nonce_generator = -> request { SecureRandom.base64(16) }
|
||||
|
||||
# Report CSP violations to a specified URI
|
||||
# For further information see the following documentation:
|
||||
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy-Report-Only
|
||||
# Rails.application.config.content_security_policy_report_only = true
|
||||
38
config/initializers/new_framework_defaults_5_2.rb
Normal file
38
config/initializers/new_framework_defaults_5_2.rb
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
# Be sure to restart your server when you modify this file.
|
||||
#
|
||||
# This file contains migration options to ease your Rails 5.2 upgrade.
|
||||
#
|
||||
# Once upgraded flip defaults one by one to migrate to the new default.
|
||||
#
|
||||
# Read the Guide for Upgrading Ruby on Rails for more info on each option.
|
||||
|
||||
# Make Active Record use stable #cache_key alongside new #cache_version method.
|
||||
# This is needed for recyclable cache keys.
|
||||
# Rails.application.config.active_record.cache_versioning = true
|
||||
|
||||
# Use AES-256-GCM authenticated encryption for encrypted cookies.
|
||||
# Also, embed cookie expiry in signed or encrypted cookies for increased security.
|
||||
#
|
||||
# This option is not backwards compatible with earlier Rails versions.
|
||||
# It's best enabled when your entire app is migrated and stable on 5.2.
|
||||
#
|
||||
# Existing cookies will be converted on read then written with the new scheme.
|
||||
# Rails.application.config.action_dispatch.use_authenticated_cookie_encryption = true
|
||||
|
||||
# Use AES-256-GCM authenticated encryption as default cipher for encrypting messages
|
||||
# instead of AES-256-CBC, when use_authenticated_message_encryption is set to true.
|
||||
# Rails.application.config.active_support.use_authenticated_message_encryption = true
|
||||
|
||||
# Add default protection from forgery to ActionController::Base instead of in
|
||||
# ApplicationController.
|
||||
# Rails.application.config.action_controller.default_protect_from_forgery = true
|
||||
|
||||
# Store boolean values are in sqlite3 databases as 1 and 0 instead of 't' and
|
||||
# 'f' after migrating old data.
|
||||
# Rails.application.config.active_record.sqlite3.represent_boolean_as_integer = true
|
||||
|
||||
# Use SHA-1 instead of MD5 to generate non-sensitive digests, such as the ETag header.
|
||||
# Rails.application.config.active_support.use_sha1_digests = true
|
||||
|
||||
# Make `form_with` generate id attributes for any generated HTML tags.
|
||||
# Rails.application.config.action_view.form_with_generates_ids = true
|
||||
|
|
@ -1,15 +1,37 @@
|
|||
workers Integer(ENV["WEB_CONCURRENCY"] || 2)
|
||||
threads_count = Integer(ENV["MAX_THREADS"] || 5)
|
||||
# Puma can serve each request in a thread from an internal thread pool.
|
||||
# The `threads` method setting takes two numbers: a minimum and maximum.
|
||||
# Any libraries that use thread pools should be configured to match
|
||||
# the maximum value specified for Puma. Default is set to 5 threads for minimum
|
||||
# and maximum; this matches the default thread size of Active Record.
|
||||
#
|
||||
threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }
|
||||
threads threads_count, threads_count
|
||||
|
||||
worker_timeout 15
|
||||
worker_shutdown_timeout 8
|
||||
# Specifies the `port` that Puma will listen on to receive requests; default is 3000.
|
||||
#
|
||||
port ENV.fetch("PORT") { 3000 }
|
||||
|
||||
# Specifies the `environment` that Puma will run in.
|
||||
#
|
||||
environment ENV.fetch("RAILS_ENV") { "development" }
|
||||
|
||||
# Specifies the number of `workers` to boot in clustered mode.
|
||||
# Workers are forked webserver processes. If using threads and workers together
|
||||
# the concurrency of the application would be max `threads` * `workers`.
|
||||
# Workers do not work on JRuby or Windows (both of which do not support
|
||||
# processes).
|
||||
#
|
||||
workers ENV.fetch("WEB_CONCURRENCY") { 2 }
|
||||
|
||||
# Use the `preload_app!` method when specifying a `workers` number.
|
||||
# This directive tells Puma to first boot the application and load code
|
||||
# before forking the application. This takes advantage of Copy On Write
|
||||
# process behavior so workers use less memory.
|
||||
#
|
||||
preload_app!
|
||||
|
||||
rackup DefaultRackup
|
||||
port ENV["PORT"] || 3000
|
||||
environment ENV["RACK_ENV"] || "development"
|
||||
# Allow puma to be restarted by `rails restart` command.
|
||||
plugin :tmp_restart
|
||||
|
||||
on_worker_boot do
|
||||
# Worker specific setup for Rails 4.1+
|
||||
|
|
|
|||
34
config/storage.yml
Normal file
34
config/storage.yml
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
test:
|
||||
service: Disk
|
||||
root: <%= Rails.root.join("tmp/storage") %>
|
||||
|
||||
local:
|
||||
service: Disk
|
||||
root: <%= Rails.root.join("storage") %>
|
||||
|
||||
# Use rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key)
|
||||
# amazon:
|
||||
# service: S3
|
||||
# access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %>
|
||||
# secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %>
|
||||
# region: us-east-1
|
||||
# bucket: your_own_bucket
|
||||
|
||||
# Remember not to checkin your GCS keyfile to a repository
|
||||
# google:
|
||||
# service: GCS
|
||||
# project: your_project
|
||||
# credentials: <%= Rails.root.join("path/to/gcs.keyfile") %>
|
||||
# bucket: your_own_bucket
|
||||
|
||||
# Use rails credentials:edit to set the Azure Storage secret (as azure_storage:storage_access_key)
|
||||
# microsoft:
|
||||
# service: AzureStorage
|
||||
# storage_account_name: your_account_name
|
||||
# storage_access_key: <%= Rails.application.credentials.dig(:azure_storage, :storage_access_key) %>
|
||||
# container: your_container_name
|
||||
|
||||
# mirror:
|
||||
# service: Mirror
|
||||
# primary: local
|
||||
# mirrors: [ amazon, google, microsoft ]
|
||||
|
|
@ -72,7 +72,7 @@ Article.clear_index!
|
|||
25.times do |i|
|
||||
tags = []
|
||||
tags << "discuss" if (i % 3).zero?
|
||||
tags.concat Tag.order("RANDOM()").select("name").first(3).map(&:name)
|
||||
tags.concat Tag.order(Arel.sql("RANDOM()")).select("name").first(3).map(&:name)
|
||||
|
||||
markdown = <<~MARKDOWN
|
||||
---
|
||||
|
|
@ -91,7 +91,7 @@ Article.clear_index!
|
|||
body_markdown: markdown,
|
||||
featured: true,
|
||||
show_comments: true,
|
||||
user_id: User.order("RANDOM()").first.id,
|
||||
user_id: User.order(Arel.sql("RANDOM()")).first.id,
|
||||
)
|
||||
end
|
||||
|
||||
|
|
@ -103,8 +103,8 @@ Comment.clear_index!
|
|||
30.times do
|
||||
attributes = {
|
||||
body_markdown: Faker::Hipster.paragraph(1),
|
||||
user_id: User.order("RANDOM()").first.id,
|
||||
commentable_id: Article.order("RANDOM()").first.id,
|
||||
user_id: User.order(Arel.sql("RANDOM()")).first.id,
|
||||
commentable_id: Article.order(Arel.sql("RANDOM()")).first.id,
|
||||
commentable_type: "Article"
|
||||
}
|
||||
Comment.create!(attributes)
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
<div class="ltag__twitter-tweet__media ltag__twitter-tweet__media__video-wrapper">
|
||||
<div class="ltag__twitter-tweet__media--video-preview">
|
||||
<img src="https://pbs.twimg.com/tweet_video_thumb/DiPm8-WXcAI3_qS.jpg" />
|
||||
<img class="ltag__twitter-tweet__play-butt" src="/assets/play-butt.svg" alt="Play butt" />
|
||||
<img class="ltag__twitter-tweet__play-butt" alt="Play butt" src="/assets/play-butt.svg" />
|
||||
</div>
|
||||
<div class="ltag__twitter-tweet__video">
|
||||
<video loop="">
|
||||
|
|
@ -24,7 +24,7 @@
|
|||
</div>
|
||||
<div class="ltag__twitter-tweet__body">When GitHub goes down </div>
|
||||
<div class="ltag__twitter-tweet__date">02:34 AM - 17 Jul 2018</div>
|
||||
<div class="ltag__twitter-tweet__actions"><a href="https://twitter.com/intent/tweet?in_reply_to=1018911886862057472" class="ltag__twitter-tweet__actions__button"><img src="/assets/twitter-reply-action.svg" alt="Twitter reply action" /></a><a href="https://twitter.com/intent/retweet?tweet_id=1018911886862057472" class="ltag__twitter-tweet__actions__button"><img src="/assets/twitter-retweet-action.svg" alt="Twitter retweet action" /></a>91<a href="https://twitter.com/intent/like?tweet_id=1018911886862057472" class="ltag__twitter-tweet__actions__button"><img src="/assets/twitter-like-action.svg" alt="Twitter like action" /></a>276</div>
|
||||
<div class="ltag__twitter-tweet__actions"><a href="https://twitter.com/intent/tweet?in_reply_to=1018911886862057472" class="ltag__twitter-tweet__actions__button"><img alt="Twitter reply action" src="/assets/twitter-reply-action.svg" /></a><a href="https://twitter.com/intent/retweet?tweet_id=1018911886862057472" class="ltag__twitter-tweet__actions__button"><img alt="Twitter retweet action" src="/assets/twitter-retweet-action.svg" /></a>91<a href="https://twitter.com/intent/like?tweet_id=1018911886862057472" class="ltag__twitter-tweet__actions__button"><img alt="Twitter like action" src="/assets/twitter-like-action.svg" /></a>276</div>
|
||||
</div>
|
||||
</blockquote>
|
||||
</body>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue