Video of my speech in "Read more"
Read more ...
"Экосистема Ruby (on Rails) с горьким привкусом, или «Как мы любим пошпынять PHP»"
https://habrahabr.ru/post/306564/
переведена на Хабре Романом Ахмадуллиным (@saggid), за что ему большое спасибо!
Trailblazer is a high-level Architecture libraries for the Ruby web application (not only for Rails). If you are no familiar with it yet - take a 20 minutes walk through guide...
I want to cover once again those places where our team had issues or misunderstanding. Trailblazer documentation got a lot of improvements recently and keep getting more and more care. Some points from this list are covered by the docs, but in practice not everything was smooth.
Recently I have evaluated different HTTP request wrapper libraries for Ruby project. Took 3 most popular: Faraday, RestClient, HTTParty. And found an interesting fact that illustrates very common issue in the world of Ruby libs.
Metaprogramming is used for the sake of Metaprogramming - "because it is Ruby and I can do it like this...". Not to make end-user developer life simpler.
Let's see the main purpose of HTTP request lib - is to send HTTP request (GET, POST, etc.). And the main purpose should dictate public interface of the lib classes. It should have a generic method to do any kind of HTTP request + shortcut methods to do the most common requests, like GET and POST.
That is what all these libs have
# kind-a this
connection.get(url)
# or this
Client.post(url, body_params_hash)
# it doesn't really matter is it static or object method
The issue is - these methods get
/post
are not real. For some reasons lib author try to spare 10 lines of code, but to use "cool Metaprogramming approach".
The consequences of this - I am as an end-user of this lib, can't Ctrl+Click on post
method in my IDE to see how it is implemented and what's happen inside. Because this method does not really exist in class, it appears in runtime after class_eval
or define_method
. I can't even find the place in Gem where it defined without getting deep in internal implementation.
That is a bit frustrating for me. These 3-5 methods are the most important parts of such a lib, I don't care about all other parts, but exactly these parts are hidden from me. And for what good reason?
%w[get head delete].each do |method|
class_eval <<-RUBY, __FILE__, __LINE__ + 1
def #{method}(url = nil, params = nil, headers = nil)
run_request(:#{method}, url, nil, headers) { |request|
request.params.update(params) if params
yield(request) if block_given?
}
end
RUBY
end
POSSIBLE_VERBS = ['get', 'put', 'post', 'delete']
...
POSSIBLE_VERBS.each do |m|
define_method(m.to_sym) do |path, *args, &b|
r[path].public_send(m.to_sym, *args, &b)
end
end
Only HTTParty has explicit declaration of these methods . Thank you guys, you rock! :)
...
def get(path, options = {}, &block)
perform_request Net::HTTP::Get, path, options, &block
end
...
As we can see it is 3-5 line methods. There is no any problem to write them explicitly and hardcode method name inside them + extract all repeating lines inside a separate method. That is absolutely normal code design approach. Instead of sacrificing code simplicity and readability of favor of code size.
Postal and ClutterFish fully featured open source mail delivery platform for incoming & outgoing e-mails
Active Interaction - an implementation of the command pattern in Ruby. To organize and manags application-specific business logic.
Animista - is a place where you can play with a collection of ready to use CSS animations, tweak them and download only those you will actually use.
Cachex - a powerful caching library for Elixir with support for transactions, fallbacks and expirations
retext is an ecosystem of plug-ins for processing natural language.
Staticman - handles user-generated content for you and transforms it into data files that sit in your GitHub repository, along with the rest of your content.
Best Practices for Building a Microservice Architecture. Looks like a wide set of questions covered.