
$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/
All Articles