$this->turtle # $this->bike() # $apple # Ruby @turtle # turtle # " " attr_reader: :turtle bike # apple #
attr_reader :turtle
dynamically determines the method used as a getter for @turtle
, so turtle
and bike
are one and the same. In this case, the PHP developer does not understand where it comes from, looking at using turtle
without explicitly defining the name of a method or variable.
attr_reader
elements with full methods, or vice versa, which will cause misunderstandings. It must be said that with the use of some very flexible APIs, this is a perfectly acceptable move, with the help of which you can implement quite bold schemes.
class Trip def canceled_at nil end end
trip.canceled_at
, it will get nil
instead of a field. And later it can be correctly removed.
int
, string
, float
, etc., appeared. In addition, scalar type indications were introduced. This functionality has caused many disputes and debates, but as a result has been implemented. Its use depends entirely on the preferences of the programmer himself, which is good news in the light of the diversity of PHP users.
FooInterface
”, with the result that FooInterface
will have a method bar(int $a, array $b)
, you can say otherwise: “The argument can be anything, just to react to bar
method And if it doesn’t react, we’ll think of something else. ”
def read_data(source) return source.read if source.respond_to?(:read) return File.read(source.to_str) if source.respond_to?(:to_str) raise ArgumentError end filename = "foo.txt" read_data(filename) #=> foo.txt File.read() input = File.open("foo.txt") read_data(input) #=> foo.txt #
int(0)
and int(1)
in weak mode are considered valid Boolean values ​​that take any value, so it’s quite risky to hope that everything will work as it should. In PHP, we could just define two different methods / functions:
function read_from_filename(string $filename) { $file = new SplFileObject($filename, "r"); return read_from_object($file); } function read_from_object(SplFileObject $file) { return $file->fread($file->getSize()); } $filename = "foo.txt"; read_from_filename($filename); $file = new SplFileObject($filename, "r"); read_from_object($file);
function read_data($source) { if (method_exists($source, 'read')) { return $source->read(); } elseif (is_string($source)) { $file = new SplFileObject($source, "r")); return $file->fread($file->getSize()); } throw new InvalidArgumentException; } $filename = "foo.txt"; read_data($filename); #=> foo.txt # SplFileObject->read(); $input = new SplFileObject("foo.txt", "r"); read_data($input); #=> foo.txt #
ExplodingBoxException
exception:
namespace Acme\Foo; class Box { public function somethingBad() { throw new Box\ExplodingBoxException; } }
“This means that each class is in a separate file, and in the namespace it occupies at least one level: the name of the top-level supplier”
namespace Acme\Foo\Box; class ExplodingBoxException {}
module Acme module Foo class Box class ExplodingBoxError < StandardError; end def something_bad! raise ExplodingBoxError end end end end
begin box = Acme::Foo::Box.new box.something_bad! rescue Acme::Foo::Box::ExplodingBoxError # ... end
class PopulateEmployerWithUserAccountName < ActiveRecord::Migration class User < ActiveRecord::Base belongs_to :account end class Account < ActiveRecord::Base has_many :users end def up Account.find_each do |account| account.users.update_all(employer: account.name) end end def down # , ID , # « » User.where.not(account_id: nil).update_all(employer: nil) end end
User
and Account
ORM models will be used. That is, if necessary, they can perform for us the role of snapshots. This is much more useful than calling the code in an environment where the rules of the game can change at any time. For some, all this sounds crazy, but only until you come across migration problems.
var_dump()
+ update” scheme that is widespread among novice developers.
zend_extension=xdebug.so
with your CLI and web version of the application, get sent checkpoints , even if you use Vagrant, etc.
debugger
into the code, thereby obtaining a checkpoint. When this line is executed, it does not matter that it is a $ rails server
, a unit test, an integration test, etc. - you will have access to a REPL instance that can work with your code.
pry
pry
and byebug
. Both of them are gems, and to install them you need to add the code to the Gemfile
via the Bundler:
group :development, :test do gem "byebug" end
debugger
. Otherwise, you must first execute require "byebug"
.
[1, 10] in /PathTo/project/app/controllers/articles_controller.rb 3: 4: # GET /articles 5: # GET /articles.json 6: def index 7: byebug => 8: @articles = Article.find_recent 9: 10: respond_to do |format| 11: format.html # index.html.erb 12: format.json { render json: @articles } (byebug)
@articles
not yet been defined, but you can call Article.find_recent
and see what happens. If an error occurs, you can type next
and go to the next line in the same context. Or type step
and execute the following instruction.
unless
. They are often abused, as are many other things in many other languages. Unless
does not give people peace of Unless
for many years, as noted in one article from 2008.
unless
is an antonym for if
. The code is blocked if the condition is true
, and continues to execute when the value is false
.
unless foo? # bar that thing end # Or def something return false unless foo? # bar that thing end
if ! (foo || bar) && baz
unless (foo || bar) && baz
unless
along with else
, but by itself it is a handy tool. Its implementation in PHP was requested back in 2007, but for a while the request was ignored. Finally, Rasmus Lerdorf, the creator of PHP, said that the unless()
function would violate backward compatibility, and this “will not be obvious to those for whom English is not native.”
“This is a strange word, essentially meaning“ no if ”, although logically it should be an analogue of how“ less (less) ”is the opposite of“ more ”, but the prefix“ un ”changes its meaning to the opposite (less - unless). ”
unless
, they do not perceive its meaning as “the opposite less” only because of the prefixed un
. Otherwise, we would read the uniqid()
function and consider it the opposite of iqid()
.
object.nil?
. In fact, this is an analogue of $object === nil
in PHP. If you need to request something and not perform an action, then it is better to use include?
instead of include
.
class Rider def driver? !potential_driver.nil? && vehicle.present? end end
is
and / or has
to the name when creating the predicate method, for example, isDriver()
or hasVehicle()
. But sometimes you can come across other prefixes. Suppose the method can_drive?
from Ruby can turn into canDrive()
in PHP, and it will not be entirely clear that this is a predicate method. It is better to rename it, in accordance with tradition, into something like isAbleToDrive()
.
// < 5.4 $a = array('one' => 1, 'two' => 2, 'three' => 'three'); // >= 5.4 $a = ['one' => 1, 'two' => 2, 'three' => 'three'];
$a = ['one': 1, 'two': 2, 'three': 'three'];
StdClass
with values, then you have two ways:
$esQuery = new stdClass; $esQuery->query = new stdClass; $esQuery->query->term = new stdClass; $esQuery->query->term->name = 'beer'; $esQuery->size = 1; // $esQuery = (object) array( "query" => (object) array( "term" => (object) array( "name" => "beer" ) ), "size" => 1 );
$esQuery = { "query" : { "term" : { "name" : "beer" } }, "size" : 1 };
esQuery = { "query" : { "term" : { "name" : "beer" } }, "size" : 1 }
try/catch
in PHP and begin/rescue
in Ruby. They work almost identically, especially in light of the PHP 5.6 finally
appearing, as an analogue of ensure
from Ruby. In both languages, there is the possibility of recovery after exclusion from any place, for which the try
and begin
commands are used. But Ruby does much more: you can skip the begin method and recover directly from the function / method body:
def create(params) do_something_complicated(params) true rescue SomeException false end
begin
.
function create($params) { do_something_complicated($params); return true; } catch (SomeException $e) { return false; }
retry
command:
begin SomeModel.find_or_create_by(user: user) rescue ActiveRecord::RecordNotUnique retry end
find_or_create_by
(ORM first performs a SELECT
and then INSERT
). And if you're unlucky, another process can create an entry after SELECT
, but before INSERT
.
SELECT
to consider the possibility of begin...rescue
. Perhaps in some cases you even want to put some logic here to drive it one or two times, but we will not consider this option. Let's better appreciate the convenience of re-execution of a piece of code. In Ruby, you can do this:
def upload_image begin obj = s3.bucket('bucket-name').object('key') obj.upload_file('/path/to/source/file') rescue AWS::S3::UploadException retry end end
function upload_image($path) { $attempt = function() use ($path) { $obj = $this->s3->bucket('bucket-name')->object('key'); $obj->upload_file($path); }; try { $attempt(); } catch (AWS\S3\UploadException $e) $attempt(); } }
Source: https://habr.com/ru/post/281004/