Runet me causa una impresión extremadamente contradictoria (y no solo en el contexto de la programación web). ¿Quizás así debería ser, como "Nueva York es una ciudad de contrastes"? - al menos ese encuentro de Internet semiprofesional y colorido, al que suelen acudir los principiantes que sueñan con aprender a ser programadores web. En palabras del héroe de la obra, Yevgeny Schwartz, "será muy difícil desentrañar todo esto, desmontarlo y ponerlo en orden para no dañar nada vivo" ... sí, pero aún hay que intentarlo. "El mundo se apoya en esto", en palabras del mismo personaje (Científico de "Shadow").
, , " "; , - , Ruby in Rails - , " "... , -. , , " API , ", , " CMS - , ", "" . Ruby, , dead, " - " - , . " , Artificial Intelligence Neural Network middle- senior- PHP-" .
, Google , PHP?
- , " Google" , ... - - , , , . , ...
Ruby on Rails , CMS, . "Joomla on Rails" - , , " "; -, Ruby on Rails.
/ , , . , , , , ... , , . ( ) :
AJAX
AJAX
-
base64, Active Storage ( AWS S3)
(various preview options can be passed to the Active Storage variant method)
-
IP Google
RSS
User-Friendly URLs
Sitemap
SlideShow
Lightbox
JavaScript Time Greeting
, step-by-step , . , ... - , . .
. Bootstrap 4, FontAwesome5, jQuery (- Ruby on Rails 6) Webpacker:
# package.json
{
"name": "blog",
"private": true,
"dependencies": {
"@rails/actioncable": "^6.1.3-1",
"@rails/activestorage": "^6.1.3-1",
"@rails/ujs": "^6.1.3-1",
"@rails/webpacker": "5.4.0",
"bootstrap": "^4.6.0",
"jquery": "^3.6.0",
"popper.js": "^1.16.1",
"turbolinks": "^5.2.0"
},
"version": "0.1.0",
"devDependencies": {
"webpack-dev-server": "^3.11.2"
}
}
: 5 -, ( ) , . kaminari:
# config/initializers/kaminari_config.rb
Kaminari.configure do |config|
config.default_per_page = 5
# config.max_per_page = nil
# config.window = 4
# config.outer_window = 0
# config.left = 0
# config.right = 0
# config.page_method_name = :page
# config.param_name = :page
# config.max_pages = nil
# config.params_on_first_page = false
end
, , . - SEO:
. , . , description keywords , description . , ; , , - , . title, , < > | < >, application.html.erb:
# app/views/layouts/application.html.erb
<head>
<%= display_meta_tags site: 'My Blog on Rails' %>
</head>
, ( , ) title description (keywords , , , ) , :
# app/controllers/application_controller.rb
def metatags
set_meta_tags title: 'Building a Blog with Ruby on Rails',
description: 'Your Guide To Content Management System For Ruby on Rails'
end
, @page_title @page_description (), , HTML ... , , Ruby on Rails.
:
<% title 'Member Login' %>
<% description 'Member login page.' %>
<% keywords 'Site, Login, Members' %>
<% nofollow %>
<% noindex %>
<% refresh 3 %>
, ; :canonical, :og (Open Graph), :twitter . kpumuk/meta-tags.
Sitemap, . public sitemap.xml.gz ( , ), :
rails sitemap:refresh
Google Bing . ping , . gem 'sitemap_generator', sitemap . , , , ; Whenever :
# config/schedule.rb
every 1.day, :at => '5:00 am' do
rake "-s sitemap:refresh"
end
, ( Analytics Contacts):
# config/sitemap.rb
SitemapGenerator::Sitemap.default_host = ENV['DOMAIN_NAME']
SitemapGenerator::Sitemap.create do
Post.find_each do |content|
add post_path(content), :lastmod => content.updated_at
end
add analytics_path, :priority => 0.5, :changefreq => 'weekly'
add contacts_path, :priority => 0.5, :changefreq => 'weekly'
end
robots.txt. , - :
# public/robots.txt
User-agent: *
Disallow:
Sitemap: http://mstp.herokuapp.com/sitemap.xml.gz
, . , Active Storage variants , , kuwahara / monochrome :
def preview_post(i)
if i.images.attached? && !current_page?(root_path)
tag.div class: 'preview' do
link_to i.images.first, 'data-lightbox' => 'preview' do
image_tag i.images.first.variant(
resize_to_fill: [400, 300], kuwahara: '3%'
)
end
end
end
end
. ( . ) , .
, acts-as-taggable-on . , : Active Admin Tags ( / ), , , , . , .
:
# posts_controller
def show
@post = Post.find(params[:id])
end
# app/views/posts/show.html.erb
<% @post.tag_list.each do |tag| %>
<%= tags(tag) %>
<% end %>
# helper
def tags(tag)
link_to (tag.to_s +
' (' +
Post.tagged_with(tag).count.to_s +
')'),
tag_url(tag),
class: 'badge badge-secondary'
end
:
# tags_controller.rb
def show
@posts = Post.tagged_with(params[:id])
end
# app/views/tags/show.html.erb
<% @posts.each do |i| %>
<%= link_to i.title, {controller: "posts", action: "show", id: i.id} %>
<% end %>
. , - :
# routes.rb
resources :posts do
resources :comments
end
resources :tags, only: [:show]
, , ? , , , ... , , .
SEO-Friendly URLs, / . Url , . :
# Gemfile
gem 'friendly_id', '~> 5.4.0'
gem 'babosa'
RSS. Blog on Rails RSS-, ( bootstrap 4) . , base64. , CMS ( PaaS-) Heroku, , base64. , , - Quill Editor - , - ImageUploader plugin. , , Amazon S3? .
, ( ) . ActiveAdmin, :
ActiveAdmin.register Slider do
permit_params :published_at, :name, images: []
scope :all
scope :published
scope :unpublished
action_item :publish, only: :show do
link_to 'Publish', publish_admin_slider_path(slider), method: :put unless slider.published_at?
end
action_item :unpublish, only: :show do
link_to 'Unpublish', unpublish_admin_slider_path(slider), method: :put if slider.published_at?
end
action_item :delete_images, only: :show do
link_to 'Delete Images', delete_images_admin_slider_path(slider), method: :delete if slider.images.attached?
end
member_action :publish, method: :put do
slider = Slider.find(params[:id])
slider.update(published_at: Time.zone.now)
redirect_to admin_slider_path(slider)
end
member_action :unpublish, method: :put do
slider = Slider.find(params[:id])
slider.update(published_at: nil)
redirect_to admin_slider_path(slider)
end
member_action :delete_images, method: :delete do
slider = Slider.find(params[:id])
slider.images.purge_later
redirect_to admin_slider_path(slider)
end
form do |f|
f.inputs 'Slider' do
f.input :name
f.input :images, as: :file, input_html: { multiple: true }
end
f.actions
end
show do |t|
attributes_table do
if t.images.attached?
t.images.each do |img|
span do
image_tag img.variant(resize_to_limit: [100, 100])
end
end
end
row :name
row :created_at
row :updated_at
row :published_at
end
end
end
, , ; - ? - , , - .
- , . , . , :
member_action :delete_image, method: :delete do
slider = Slider.find_by(params[:name])
slider.images[params[:id].to_i].purge_later
redirect_to admin_slider_path(slider)
end
if t.images.attached?
t.images.each_with_index do |img, index|
span do
link_to delete_image_admin_slider_path(index), method: :delete do
image_tag img.variant(resize_to_limit: [100, 100])
end
end
end
end
Quill Rich Text Editor (gem 'activeadmin_quill_editor'), ( ):
form do |f|
f.inputs 'Article' do
f.input :category
f.input :tag_list, input_html: { value: f.object.tag_list.join(', ') }, label: 'Tags (separated by commas)'
f.input :title, label: 'Title (70 characters maximum)'
f.input :description, label: 'Description (160 characters maximum)'
f.input :keywords, label: 'Keywords (5 - 10 words)'
f.input :text, as: :quill_editor, input_html: { data:
{ options:
{ modules:
{ toolbar:
[%w[bold italic underline strike],
%w[blockquote code-block],
[{ 'list': 'ordered' }, { 'list': 'bullet' }],
[{ 'align': [] }],
['link'],
[{ 'size': ['small', false, 'large', 'huge'] }],
[{ 'header': [1, 2, 3, 4, 5, 6, false] }],
[{ 'indent': '-1' }, { 'indent': '+1' }],
[{ 'direction': 'rtl' }],
[{ 'color': [] }, { 'background': [] }],
[{ 'font': [] }],
['clean'],
['image'],
['video']] },
theme: 'snow' } } }, label: 'The content of the article'
f.input :images, as: :file, input_html: { multiple: true }, label: 'Add illustrations to the article'
end
f.actions
end
, .
, Google Analytics , Ahoy - Simple, powerful, first-party analytics for Rails. , , (, ). - , , .
:
@locations = Ahoy::Visit.all.group(:country).count
, , , nil :
@locations = Ahoy::Visit.all.group(:country).count.map { |k, v| [k ||= 'undefined', v] }
:
Ahoy::Visit.all.group(:city).count
, , ; :
@visits = Ahoy::Visit.all
@events = Ahoy::Event.all
<% @visits.each do |visit| %>
Visit Number: <%= visit.id %><br>
Visit Token: <%= visit.visit_token %><br>
Visitor Token: <%= visit.visitor_token %><br>
IP: <%= visit.ip %><br>
User Agent: <%= visit.user_agent %><br>
Referrer: <%= visit.referrer %><br>
Referring domain: <%= visit.referring_domain %><br>
Device Type: <%= visit.device_type %><br>
Country: <%= visit.country %><br>
Region: <%= visit.region %><br>
City: <%= visit.city %><br>
Latitude: <%= visit.latitude %><br>
Longitude: <%= visit.longitude %><br>
User ID: <%= visit.user_id %><br>
<% end %>
, - Ahoy , . .
, , , . , , , IP Ahoy. - :
class GetImages
def self.get_random_banner(country)
x = get_country(country)
File.join('/images', x, Dir.children(File.join(Rails.root, 'public', 'images', x)).sample)
end
def self.get_country(country)
if dir_names.include? country
country
else
'other'
end
end
def self.dir_names
target_folder_path = File.join(Rails.root, 'public', 'images')
Dir.children(target_folder_path)
end
end
..., . Enjoy! :)
PD La instalación y el uso de este blog no requiere ningún conocimiento de Ruby / Rails / PostgreSQL , ni ningún conocimiento de cómo usarlos, ni siquiera tenerlos en su PC. Todo lo que necesita es instalar git , y también una cuenta gratuita en Heroku , + registrar una cuenta en AWS (funcionará gratis, o casi gratis, durante un año). Simplemente siga las instrucciones Léame de GitHub, enlace al principio del artículo.
Me alegraría si pudiera darse de baja de sus impresiones.