{"id":288815,"date":"2018-08-31T17:10:06","date_gmt":"2018-08-31T13:10:06","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=288815"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=288815","title":{"rendered":"\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c SQL \u0432 Rails"},"content":{"rendered":"\n<div data-io-article-url=\"https:\/\/habr.com\/post\/421939\/\" class=\"post__text post__text-html js-mediator-article\">\n<p>\u0412\u043e-\u043f\u0435\u0440\u0432\u044b\u0445, \u0441\u0442\u0430\u0442\u044c\u044f \u043d\u0435 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u044f \u043b\u044e\u0431\u043b\u044e \u0440\u0435\u043b\u044c\u0441\u044b, \u0432\u043e-\u0432\u0442\u043e\u0440\u044b\u0445, \u0441\u0442\u0430\u0442\u044c\u044f \u043d\u0435 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u044f \u0438\u0445 \u043d\u0435\u043d\u0430\u0432\u0438\u0436\u0443. \u041a \u043d\u0438\u043c \u043c\u043e\u0436\u043d\u043e \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u044c\u0441\u044f \u0441\u043e\u0432\u0435\u0440\u0448\u0435\u043d\u043d\u043e \u043f\u043e-\u0440\u0430\u0437\u043d\u043e\u043c\u0443 \u0438 \u043b\u0443\u0447\u0448\u0435 \u043e\u043d\u0438 \u0441\u0442\u0430\u043d\u0443\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0435\u0441\u043b\u0438 \u0438\u0445 \u043c\u0435\u043d\u044f\u0442\u044c. \u0418 \u0445\u0443\u0436\u0435 \u043e\u043d\u0438 \u043c\u043e\u0433\u0443\u0442 \u0441\u0442\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0435\u0441\u043b\u0438 \u0438\u0445 \u043d\u0430\u0447\u0430\u0442\u044c \u043c\u0435\u043d\u044f\u0442\u044c. \u041d\u0443, \u0432 \u043e\u0431\u0449\u0435\u043c, \u044f \u0432\u0430\u0441 \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0434\u0438\u043b, \u0430 \u0432\u044b \u043c\u0435\u043d\u044f \u043f\u043e\u043d\u044f\u043b\u0438.<\/p>\n<p>  <\/p>\n<p>\u041e\u0434\u043d\u0430 \u0438\u0437 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0445 \u043a\u043e\u043d\u0446\u0435\u043f\u0446\u0438\u0439 ActiveRecord \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u0431\u0430\u0437\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0443\u0442\u0438\u043b\u0438\u0442\u0430\u0440\u043d\u0430 \u0438 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0430. \u041d\u0443, \u0432\u044b \u0442\u0430\u043a\u0438\u0435 \u0441\u0438\u0434\u0438\u0442\u0435, \u043f\u0438\u0448\u0435\u0442\u0435 \u0441\u0432\u043e\u0438 \u043c\u043e\u0434\u0435\u043b\u044c\u043a\u0438 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c MySQL \u0438 \u0432\u0434\u0440\u0443\u0433 \u0433\u0434\u0435-\u0442\u043e \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u043b\u0438, \u0447\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0432\u043e\u0442 \u0442\u0430\u043a \u0432\u043e\u0442 \u0432\u0437\u044f\u0442\u044c \u0438 \u0437\u0430\u043c\u0435\u043d\u0438\u0442\u044c MySQL \u043d\u0430 MongoDB. \u0425\u043e\u0440\u043e\u0448\u043e, \u043d\u0435 \u0442\u0430\u043a \u0440\u0430\u0434\u0438\u043a\u0430\u043b\u044c\u043d\u043e, \u043d\u043e, \u0441\u043a\u0430\u0436\u0435\u043c, \u043d\u0430 PostgreSQL \u0443 \u0432\u0430\u0441 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043f\u0440\u0438\u0447\u0438\u043d\u044b \u0437\u0430\u043c\u0435\u043d\u0438\u0442\u044c MySQL. \u0418\u043b\u0438 \u043d\u0430\u043e\u0431\u043e\u0440\u043e\u0442, \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0438\u043c\u0435\u044e \u043f\u0440\u043e\u0442\u0438\u0432 MySQL. \u0422\u0443\u0442 ActiveRecord \u0443\u0442\u0432\u0435\u0440\u0436\u0434\u0430\u0435\u0442, \u0447\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0432\u0430\u043c \u044d\u0442\u043e \u043f\u0440\u043e\u0449\u0435 \u043f\u0440\u043e\u0441\u0442\u043e\u0433\u043e, \u043c\u043e\u043b \u0441\u043a\u043e\u0443\u043f\u044b, before\/after \u0444\u0438\u043b\u044c\u0442\u0440\u044b \u0438 \u0430\u0441\u0441\u043e\u0446\u0438\u0430\u0446\u0438\u0438 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u044b, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u043f\u0435\u0440\u0435\u0436\u0438\u0432\u0430\u0442\u044c \u0437\u0430 \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043a \u0431\u0430\u0437\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u0437\u0430\u0431\u043e\u0442\u0438\u0442\u0441\u044f \u043e \u043b\u043e\u0433\u0438\u043a\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u0427\u0442\u043e \u0432\u043c\u0435\u0441\u0442\u043e <code>WHERE is_archived = TRUE<\/code> \u0432\u044b \u0441 \u0440\u0430\u0434\u043e\u0441\u0442\u044c\u044e \u043d\u0430\u043f\u0438\u0448\u0435\u0442\u0435 <code>where(is_archived: true)<\/code> \u0438 ActiveRecord \u0441\u0434\u0435\u043b\u0430\u0435\u0442 \u0432\u0441\u0435 \u0437\u0430 \u0432\u0430\u0441. \u0412\u0441\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u044b \u0431\u0443\u0434\u0443\u0442 \u043f\u0440\u0435\u0432\u0435\u0434\u0435\u043d\u044b \u0434\u043b\u044f PostgreSQL, \u0430 \u043d\u0435 \u0434\u043b\u044f MySQL, \u0442\u0430\u043a \u0447\u0442\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 MySQL \u0432\u044b\u043d\u0443\u0436\u0434\u0435\u043d\u044b \u0431\u0443\u0434\u0443\u0442 \u0438\u0437\u043e\u0431\u0440\u0435\u0442\u0430\u0442\u044c \u0441\u0432\u043e\u0439 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u0432\u0435\u043b\u043e\u0441\u0438\u043f\u0435\u0434.<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/e53\/ff1\/cfc\/e53ff1cfc747b1a79b89c8139cd1d196.gif\"><\/p>\n<p>  <\/p>\n<p>\u041d\u043e \u043a\u0430\u043a \u0431\u044b \u043d\u0435 \u0442\u0430\u043a! \u041d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435 \u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f, \u0447\u0442\u043e \u044d\u0442\u043e\u0442 \u0441\u043b\u043e\u0439 \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0446\u0438\u0438 \u0432\u0441\u044f \u043d\u0430\u043f\u0440\u043e\u0447\u044c \u0434\u044b\u0440\u044f\u0432\u0430\u044f, \u043a\u0430\u043a \u043a\u043e\u0440\u044b\u0442\u043e \u0438\u0437 \u0441\u043a\u0430\u0437\u043a\u0438 \u043e \u0417\u043e\u043b\u043e\u0442\u043e\u0439 \u0420\u044b\u0431\u043a\u0435. \u0418 \u0447\u0442\u043e \u043c\u043d\u043e\u0433\u0438\u0435 \u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043d\u0435\u043b\u044c\u0437\u044f, \u0432\u0440\u043e\u0434\u0435 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f \u0434\u0430\u0442 \u0438\u043b\u0438 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043c\u0430\u0441\u0441\u0438\u0432\u0430\u043c\u0438. \u0418 \u043f\u043e\u043b\u0443\u0447\u0430\u044e\u0442\u0441\u044f \u0441\u043a\u043e\u0443\u043f\u044b \u0441 \u0432\u044b\u043d\u0443\u0436\u0434\u0435\u043d\u043d\u044b\u043c\u0438 <code>where(\"#{quoted_table_name}.finished_at &gt;= ?\", Date.current)<\/code> \u0438\u043b\u0438 <code>where(\"#{quoted_table_name}.other_ids &lt;@ ARRAY[?]\", ids)<\/code>. \u041d\u0430 \u0447\u0442\u043e ActiveRecord \u0434\u0430\u0435\u0442 \u0432\u043f\u043e\u043b\u043d\u0435 \u043e\u0441\u043e\u0437\u043d\u0430\u043d\u043d\u044b\u0439 \u0438 \u043b\u043e\u0433\u0438\u0447\u043d\u044b\u0439 \u043e\u0442\u0432\u0435\u0442: \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u044d\u0442\u043e. \u0412\u043c\u0435\u0441\u0442\u043e \u043c\u0430\u0441\u0441\u0438\u0432\u043e\u0432 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 habtm-\u0441\u0432\u044f\u0437\u044c, \u0430 \u0435\u0441\u043b\u0438 \u043d\u0430\u0434\u043e \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0442\u044c \u0434\u0430\u0442\u044b, \u0436\u0438\u0432\u0438\u0442\u0435 \u0441 \u044d\u0442\u0438\u043c. \u0414\u0430, \u0438 \u043d\u0435 \u0434\u0430\u0439 \u0431\u043e\u0433 \u0432\u0430\u043c \u043f\u0440\u043e\u043f\u0443\u0441\u0442\u0438\u0442\u044c <code>quoted_table_name<\/code> \u0432 \u0442\u0430\u043a\u043e\u043c \u0441\u043a\u043e\u0443\u043f\u0435 \u2014 \u043f\u0435\u0440\u0432\u044b\u0439 \u0436\u0435 <code>includes<\/code> \u0438\u043b\u0438 <code>joins<\/code> \u0440\u0430\u0441\u0441\u0442\u0430\u0432\u0438\u0442 \u0432\u0441\u0435 \u043d\u0430 \u0441\u0432\u043e\u0438 \u043c\u0435\u0441\u0442\u0430. \u041f\u0440\u043e\u0449\u0435 \u0432\u0435\u0437\u0434\u0435 \u0438 \u0432\u0441\u0435\u0433\u0434\u0430 \u043f\u0438\u0441\u0430\u0442\u044c, \u0447\u0442\u043e\u0431\u044b \u0440\u0443\u043a\u0443 \u043d\u0435 \u0441\u0431\u0438\u0432\u0430\u0442\u044c.<\/p>\n<p><a name=\"habracut\"><\/a>  <\/p>\n<p>\u041d\u0443 \u0438, \u043a\u043e\u043d\u0435\u0447\u043d\u043e \u0436\u0435, \u043a\u0430\u043a \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u044b \u0440\u0435\u0448\u0438\u0442\u0435\u0441\u044c \u043d\u0430 \u0432\u043e\u0442 \u0442\u0430\u043a\u043e\u0435 \u0432\u043e\u0442 \u0432\u043c\u0435\u0448\u0438\u0432\u0430\u043d\u0438\u0435 \u0432 \u0440\u0430\u0431\u043e\u0442\u0443 ActiveRecord, \u043d\u0430\u0437\u0430\u0434 \u043f\u0443\u0442\u0438 \u0443\u0436\u0435 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442. \u041d\u0435 \u0442\u043e, \u0447\u0442\u043e\u0431\u044b \u0448\u0430\u043d\u0441\u043e\u0432, \u0434\u0430\u0436\u0435 \u043f\u0440\u0438\u0437\u0440\u0430\u0447\u043d\u043e\u0439 \u043d\u0430\u0434\u0435\u0436\u044b \u043d\u0430 \u0431\u0435\u0437\u0431\u043e\u043b\u0435\u0437\u043d\u0435\u043d\u044b\u0439 \u043f\u0435\u0440\u0435\u0445\u043e\u0434 \u043d\u0430 \u0434\u0440\u0443\u0433\u0443\u044e \u0431\u0430\u0437\u0443 \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442. \u0417\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0449\u0435 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0441\u043f\u0435\u0447\u0430\u0442\u0430\u0442\u044c \u0438 \u0441\u0436\u0435\u0447\u044c \u044d\u0442\u043e\u0442 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434. \u0418 \u0441\u0430\u043c\u043e \u0441\u043e\u0431\u043e\u0439, \u043d\u0438\u043a\u0430\u043a\u043e\u0439 \u0434\u0440\u0443\u0433\u043e\u0439 \u043f\u0440\u0438\u0447\u0438\u043d\u044b \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u044d\u043a\u0441\u0442\u0440\u0430-\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u0432\u0430\u0448\u0435\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u043d\u0435\u0442. \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u043d\u0430 \u0437\u0434\u043e\u0440\u043e\u0432\u044c\u0435 \u0438 \u0434\u0440\u0443\u0433\u0438\u0445 \u0437\u0430\u0441\u0442\u0430\u0432\u043b\u044f\u0439\u0442\u0435!<\/p>\n<p>  <\/p>\n<p>\u0418 \u043a\u043e\u0433\u0434\u0430 \u043e\u043a\u0430\u0436\u0435\u0442\u0441\u044f, \u0447\u0442\u043e \u0432\u0430\u0448\u0438 \u0441\u043a\u043e\u0443\u043f\u044b \u0432 \u043f\u0430\u043f\u043a\u0435 models \u0441\u043e\u0441\u0442\u043e\u044f\u0442 \u0431\u043e\u043b\u0435\u0435 \u0447\u0435\u043c \u043d\u0430\u043f\u043e\u043b\u043e\u0432\u0438\u043d\u0443 \u0438\u0437 \u0432\u043e\u0442 \u0442\u0430\u043a\u0438\u0445 \u0432\u043e\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0439 \u044d\u043a\u0441\u0442\u0440\u0430-\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0435\u0439, \u0442\u043e \u0441\u0442\u0430\u043d\u0435\u0442 \u0441\u043e\u0432\u0435\u0440\u0448\u0435\u043d\u043d\u043e \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u043e, \u0447\u0442\u043e ActiveRecord \u2014 \u0432\u0441\u0435\u0433\u043e \u043b\u0438\u0448\u044c \u0443\u0434\u043e\u0431\u043d\u0430\u044f \u043e\u0431\u043e\u043b\u043e\u0447\u043a\u0430 \u0434\u043b\u044f \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438 \u043e\u0434\u043d\u043e\u0433\u043e \u043a\u0443\u0441\u043a\u0430 \u043a\u043e\u0434\u0430 \u0441 \u0442\u0430\u0431\u043b\u0438\u0447\u043a\u0430\u043c\u0438 \u0441 \u0434\u0440\u0443\u0433\u0438\u043c \u043a\u0443\u0441\u043a\u043e\u043c \u043a\u043e\u0434\u0430. \u0418 \u0441\u043a\u043e\u0443\u043f\u044b, \u0432\u0440\u043e\u0434\u0435 <code>where(is_archived: true).joins(:sprint).merge(Sprint.archived)<\/code>, \u0431\u0443\u0434\u0443\u0442 \u043e\u0442\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u043f\u0440\u0435\u043a\u0440\u0430\u0441\u043d\u043e \u0438 \u043a\u043e\u043c\u0431\u0438\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438\u0445 \u0431\u0443\u0434\u0435\u0442 \u043d\u0435 \u0441\u043b\u043e\u0436\u043d\u0435\u0435, \u0447\u0435\u043c \u043f\u0440\u0438\u0433\u043e\u0442\u043e\u0432\u0438\u0442\u044c \u044f\u0438\u0448\u043d\u0438\u0446\u0443, \u043f\u0440\u0430\u0432\u0434\u0430 \u0432\u0435\u0434\u044c?<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/618\/8a9\/0b1\/6188a90b173dcc6238fa5fa649ee3227.gif\"><\/p>\n<p>  <\/p>\n<p>\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u0441\u0442\u0430\u0434\u0438\u0435\u0439 \u0431\u0443\u0434\u0435\u0442 \u0434\u0435\u043d\u043e\u0440\u043c\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f. \u041d\u0435\u0442, \u0434\u0435\u043d\u043e\u0440\u043c\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043a\u0430\u043a \u0431\u044b \u0438 \u0431\u044b\u043b\u0430 \u0432\u0441\u0435\u0433\u0434\u0430 \u0438 \u043d\u0438\u043a\u0443\u0434\u0430 \u043d\u0435 \u0438\u0441\u0447\u0435\u0437\u0430\u043b\u0430, \u043d\u043e \u0437\u0430\u0431\u043e\u0442\u0430 \u043e \u043d\u0435\u0439 \u0432\u043e\u0437\u043b\u0430\u0433\u0430\u043b\u0430\u0441\u044c \u043d\u0430 \u043c\u043e\u0433\u0443\u0447\u0438\u0435 \u043f\u043b\u0435\u0447\u0438 Rails \u0438 ActiveRecord, \u0430 \u0432\u044b \u0437\u043d\u0430\u0435\u0442\u0435, \u0447\u0442\u043e \u044d\u0442\u0438 \u0434\u0432\u0430 \u043f\u0430\u0440\u043d\u044f \u043d\u0435 \u043e\u0442\u043b\u0438\u0447\u0430\u043b\u0438\u0441\u044c \u0440\u0430\u0441\u0442\u043e\u0440\u043e\u043f\u043d\u043e\u0441\u0442\u044c\u044e \u0438 \u0430\u0441\u043a\u0435\u0442\u0438\u0447\u043d\u043e\u0441\u0442\u044c\u044e \u0432 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f\u0445 \u043a \u0440\u0435\u0441\u0443\u0440\u0441\u0430\u043c. \u0414\u043e\u043f\u0443\u0441\u0442\u0438\u043c, <code>counter_cache: true<\/code> \u2014 \u044d\u0442\u043e \u043f\u0435\u0440\u0432\u044b\u0439 \u0448\u0430\u0433 \u043a \u0434\u0435\u043d\u043e\u0440\u043c\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438, \u0432\u0435\u0434\u044c <code>COUNT(*) AS sprints_count<\/code> \u0432\u0430\u043c \u0441\u0434\u0435\u043b\u0430\u0442\u044c ActiveRecord \u0442\u0430\u043a \u0432\u043e\u0442 \u043f\u0440\u043e\u0441\u0442\u043e \u043d\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 (\u0432\u044b \u0436\u0435 \u043d\u0435 \u0445\u043e\u0442\u0438\u0442\u0435 \u043c\u0435\u043d\u044f\u0442\u044c <code>select()<\/code>, \u043f\u0440\u0430\u0432\u0434\u0430 \u0432\u0435\u0434\u044c?). \u0418 \u0435\u0449\u0435 <code>counter_cache<\/code> \u043d\u0435 \u0434\u0430\u043b\u0435\u043a \u043e\u0442 \u0441\u043e\u0432\u0435\u0440\u0448\u0435\u043d\u0441\u0442\u0432\u0430 \u0438 \u0432 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0441\u043b\u0443\u0447\u0430\u044f\u0445 \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u043e\u0438\u0437\u043e\u0439\u0442\u0438 \u0440\u0430\u0441\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u044f \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u043e\u0442 \u0437\u0430\u043a\u0435\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e. \u041d\u0435\u043a\u0440\u0438\u0442\u0438\u0447\u043d\u043e, \u043a\u043e\u043d\u0435\u0447\u043d\u043e, \u043d\u043e \u043d\u0435\u043f\u0440\u0438\u044f\u0442\u043d\u043e. \u0418 \u044d\u0442\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0435\u0440\u0432\u044b\u0439 \u043a\u0430\u043d\u0434\u0438\u0434\u0430\u0442 \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u043e\u0441\u0435\u0441\u0442\u044c \u0432 \u0431\u0430\u0437\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u043d\u0435 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u0438 \u0431\u0435\u0437 \u0442\u043e\u0433\u043e \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u043d\u0443\u044e \u0433\u043e\u043b\u043e\u0432\u0443 \u0440\u0443\u0431\u0438-\u043c\u0430\u0448\u0438\u043d\u044b. \u0412\u0441\u0435\u0433\u043e-\u0442\u043e \u043f\u0430\u0440\u0430 \u0442\u0440\u0438\u0433\u0433\u0435\u0440\u043e\u0432 \u0438 \u0433\u043e\u0442\u043e\u0432\u043e! \u0412\u043e-\u043f\u0435\u0440\u0432\u044b\u0445 \u043f\u0440\u0438 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0438 \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0438 \u043d\u043e\u0432\u043e\u0439 \u0437\u0430\u043f\u0438\u0441\u0438 \u0432 \u0442\u0430\u0431\u043b\u0438\u0447\u043a\u0443 \u0410 \u043d\u0443\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0441\u0447\u0438\u0442\u0430\u0442\u044c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0430\u043f\u0438\u0441\u0435\u0439 \u0432 \u0442\u0430\u0431\u043b\u0438\u0447\u043a\u0435 \u0411 \u0438 \u0432\u0441\u0435, \u0434\u0430? \u041d\u0443 \u0438 \u043f\u0440\u0438 \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438, \u043a\u043e\u043d\u0435\u0447\u043d\u043e \u0436\u0435, \u0435\u0441\u043b\u0438 <code>foreign_key<\/code> \u043f\u043e\u043c\u0435\u043d\u044f\u043b\u0441\u044f, \u0432\u0435\u0434\u044c \u0437\u0430\u043f\u0440\u043e\u0441 <code>UPDATE B SET a_id = $1 WHERE id = $2<\/code> \u0441\u043b\u043e\u043c\u0430\u0435\u0442 counter_cache \u0438 \u0434\u043b\u044f \u0441\u0442\u0430\u0440\u043e\u0433\u043e \u0410 \u0438 \u0434\u043b\u044f \u043d\u043e\u0432\u043e\u0433\u043e.<\/p>\n<p>  <\/p>\n<pre><code>  CREATE OR REPLACE FUNCTION update_#{parent_table}_#{child_table}_counter_on_insert() RETURNS TRIGGER AS $$   BEGIN     UPDATE #{parent_table} SET #{counter_column} = COALESCE((SELECT COUNT(id) FROM #{child_table} GROUP BY #{foreign_column} HAVING #{foreign_column} = NEW.#{foreign_column}), 0) WHERE (#{parent_table}.id = NEW.#{foreign_column});     RETURN NULL;   END;   $$ LANGUAGE plpgsql; <\/code><\/pre>\n<p>  <\/p>\n<p>\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u0441\u0442\u0435\u0437\u044f \u0440\u0430\u0431\u043e\u0442 \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445 \u043e\u043a\u0430\u0436\u0435\u0442\u0441\u044f \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u043e\u0439 \u0441 \u0434\u0430\u0442\u043e\u0439-\u0432\u0440\u0435\u043c\u0435\u043d\u0435\u043c. \u0418 \u0434\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u043e\u043b\u044f <code>created_at<\/code> \u0438 <code>updated_at<\/code> \u0431\u0443\u0434\u0435\u043c \u043e\u0431\u0441\u043b\u0443\u0436\u0438\u0432\u0430\u0442\u044c \u0432 \u0431\u0430\u0437\u0435, \u0431\u043b\u0430\u0433\u043e, \u044d\u0442\u043e \u0441\u0438\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0449\u0435. \u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u043c \u0434\u0435\u0444\u043e\u043b\u0442\u044b:<\/p>\n<p>  <\/p>\n<pre><code>  change_column_default :table_name, :created_at, -&gt; { 'CURRENT_TIMESTAMP' }   change_column_default :table_name, :updated_at, -&gt; { 'CURRENT_TIMESTAMP' }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0410 \u0447\u0442\u043e\u0431\u044b \u0441\u0440\u0430\u0437\u0443 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e \u0432\u0435\u0437\u0434\u0435, \u043c\u043e\u0436\u043d\u043e \u0446\u0438\u043a\u043b \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u043e \u0432\u0441\u0435\u043c \u0442\u0430\u0431\u043b\u0438\u0447\u043a\u0430\u043c, \u0433\u0434\u0435 \u0435\u0441\u0442\u044c \u044d\u0442\u0438 \u043f\u043e\u043b\u044f. \u041a\u0440\u043e\u043c\u0435 \u0442\u0430\u0431\u043b\u0438\u0446 <code>schema_migrations<\/code> \u0438 <code>ar_internal_metadata<\/code>, \u043a\u043e\u043d\u0435\u0447\u043d\u043e \u0436\u0435:<\/p>\n<p>  <\/p>\n<pre><code>  (tables - %w(schema_migrations ar_internal_metadata)).each { ... }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0412\u0441\u0435, \u0442\u0435\u043f\u0435\u0440\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u043e-\u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0434\u043b\u044f \u044d\u0442\u0438\u0445 \u0442\u0430\u0431\u043b\u0438\u0446 \u0431\u0443\u0434\u0435\u0442 \u0440\u043e\u0432\u043d\u043e \u0442\u0430\u043a\u0438\u043c, \u043a\u0430\u043a \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e. \u0418 \u0442\u0435\u043f\u0435\u0440\u044c \u0441\u0430\u043c\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u043f\u043e\u0437\u0430\u0431\u043e\u0442\u0438\u0442\u044c\u0441\u044f \u043e \u0442\u043e\u043c, \u0447\u0442\u043e\u0431\u044b \u0440\u0435\u043b\u044c\u0441\u044b \u043d\u0435 \u0442\u0440\u043e\u0433\u0430\u043b\u0438 \u044d\u0442\u0438 \u043f\u043e\u043b\u044f. \u0414\u0435\u043b\u0430\u0435\u0442\u0441\u044f \u044d\u0442\u043e \u0434\u0432\u0443\u043c\u044f \u0431\u043e\u043b\u0442\u0430\u043c\u0438 \u0432 \u043d\u0443\u0436\u043d\u044b\u0445 \u043c\u0435\u0441\u0442\u0430\u0445. \u0418 \u0434\u0430, \u0435\u0441\u0442\u044c \u043e\u043f\u0446\u0438\u044f \u0432 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0435 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0437\u0430 \u044d\u0442\u043e \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442:<\/p>\n<p>  <\/p>\n<pre><code>Rails.application.config.active_record.record_timestamps = false<\/code><\/pre>\n<p>  <\/p>\n<p>\u0418\u0442\u0430\u043a, \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u0448\u0430\u0433\u043e\u043c \u0431\u0443\u0434\u0435\u0442 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044f <code>updated_at<\/code> \u0432 \u043c\u043e\u043c\u0435\u043d\u0442 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0437\u0430\u043f\u0438\u0441\u0438. \u042d\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u043e:<\/p>\n<p>  <\/p>\n<pre><code>  CREATE OR REPLACE FUNCTION touch_for_#{table_name}_on_update() RETURNS TRIGGER AS $$   BEGIN     SELECT CURRENT_TIMESTAMP INTO NEW.updated_at;     RETURN NEW;   END;   $$ LANGUAGE plpgsql;<\/code><\/pre>\n<p>  <\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0438\u0437\u0431\u0430\u0432\u0438\u0442\u0441\u044f \u043e\u0442 <code>touch: true<\/code> \u0432 \u043c\u043e\u0434\u0435\u043b\u044f\u0445. \u042d\u0442\u0430 \u0448\u0442\u0443\u043a\u0430 \u043e\u0447\u0435\u043d\u044c \u0441\u0438\u043b\u044c\u043d\u043e \u043f\u043e\u0445\u043e\u0436\u0430 \u043d\u0430 \u043c\u0438\u0448\u0435\u043d\u044c \u0432 \u0442\u0438\u0440\u0435 \u2014 \u0442\u043e\u0436\u0435 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0434\u044b\u0440\u044f\u0432\u0430\u044f. \u0418 \u0434\u0430\u0436\u0435 \u043d\u0435 \u0431\u0443\u0434\u0443 \u043e\u0431\u044a\u044f\u0441\u043d\u044f\u0442\u044c \u043f\u043e\u0447\u0435\u043c\u0443, \u0432\u0435\u0434\u044c \u0432\u044b \u0438 \u0442\u0430\u043a \u0432\u0441\u0435 \u044d\u0442\u0438 \u0441\u043b\u0443\u0447\u0430\u0438 \u0437\u043d\u0430\u0435\u0442\u0435. \u042d\u0442\u043e \u043d\u0435 \u0441\u0438\u043b\u044c\u043d\u043e \u0441\u043b\u043e\u0436\u043d\u0435\u0435, \u0432\u0441\u0435\u0433\u043e-\u043b\u0438\u0448\u044c \u043d\u0443\u0436\u043d\u043e \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c updated_at \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u0435\u0431\u0435:<\/p>\n<p>  <\/p>\n<pre><code>  CREATE OR REPLACE FUNCTION touch_for_#{table_name}_on_update() RETURNS TRIGGER AS $$   BEGIN     UPDATE foreign_table_name SET updated_at = CURRENT_TIMESTAMP WHERE id = NEW.foreign_column_name;     SELECT CURRENT_TIMESTAMP INTO NEW.updated_at;     RETURN NEW;   END;   $$ LANGUAGE plpgsql;<\/code><\/pre>\n<p>  <\/p>\n<p>\u041a\u043e\u043d\u0435\u0447\u043d\u043e, \u0446\u0435\u043f\u043e\u0447\u043a\u0430 \u0432\u044b\u0437\u043e\u0432\u043e\u0432 \u0442\u0430\u043a\u0438\u0445 \u0432\u043e\u0442 \u0442\u0440\u0438\u0433\u0433\u0435\u0440\u043e\u0432 \u0431\u0443\u0434\u0435\u0442 \u0434\u0435\u043b\u0430\u0442\u044c \u043b\u0438\u0448\u043d\u0435\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435, \u043d\u043e \u0432\u043e\u0442 \u0432 \u043f\u043e\u0441\u0442\u0433\u0440\u0435\u0441\u0435 \u0432\u043c\u0435\u043d\u044f\u0435\u043c\u043e\u0433\u043e \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u0430 \u0432\u044b\u0437\u0432\u0430\u0442\u044c \u0442\u0440\u0438\u0433\u0433\u0435\u0440\u044b \u043d\u0435 \u043c\u0435\u043d\u044f\u044f \u0441\u0430\u043c\u0443 \u0437\u0430\u043f\u0438\u0441\u044c \u043d\u0435\u0442. \u041c\u043e\u0436\u043d\u043e \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u0441\u0434\u0435\u043b\u0430\u0442\u044c <code>SET title = title<\/code>, \u043d\u043e \u044d\u0442\u043e \u0432\u044b\u0445\u043e\u0434\u0438\u0442 \u043d\u0438\u0447\u0435\u043c \u043d\u0435 \u043b\u0443\u0447\u0448\u0435, \u0447\u0435\u043c <code>SET updated_at = CURRENT_TIMESTAMP<\/code>.<\/p>\n<p>  <\/p>\n<p>\u0422\u043e\u0447\u043d\u043e \u0442\u0430\u043a\u043e\u0439 \u0436\u0435 \u0442\u0440\u0438\u0433\u0433\u0435\u0440 \u0431\u0443\u0434\u0435\u0442 \u0438 \u043d\u0430 \u0432\u0441\u0442\u0430\u0432\u043a\u0443, \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c <code>updated_at<\/code> \u043d\u0435 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e:<\/p>\n<p>  <\/p>\n<pre><code>  CREATE OR REPLACE FUNCTION touch_for_#{table_name}_on_insert() RETURNS TRIGGER AS $$   BEGIN     UPDATE foreign_table_name SET updated_at = CURRENT_TIMESTAMP WHERE id = NEW.foreign_column_name;     RETURN NEW;   END;   $$ LANGUAGE plpgsql;<\/code><\/pre>\n<p>  <\/p>\n<p>\u041a\u043e\u043d\u0435\u0447\u043d\u043e, \u043c\u043e\u0436\u043d\u043e \u0431\u044b \u043f\u043e\u043f\u044b\u0442\u0430\u0442\u044c\u0441\u044f \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u044d\u0442\u043e \u043e\u0434\u043d\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0435\u0439, \u0434\u043e\u0431\u0430\u0432\u0438\u0432 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u043d\u0430 \u0442\u0435\u043a\u0443\u0449\u0435\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u043f\u0440\u044f\u043c \u0432\u043d\u0443\u0442\u0440\u044c \u0442\u0440\u0438\u0433\u0433\u0435\u0440\u0430, \u043d\u0430 \u043f\u043e\u0434\u043e\u0431\u0438\u0438 <code>IF TG_OP = 'UPDATE' THEN<\/code>, \u043d\u043e \u043f\u0440\u0435\u0434\u043f\u043e\u0447\u0442\u0438\u0442\u0435\u043b\u044c\u043d\u0435\u0435 \u0434\u0435\u043b\u0430\u0442\u044c \u0432\u0441\u0435 \u0442\u0440\u0438\u0433\u0433\u0435\u0440\u044b \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0449\u0435, \u0447\u0442\u043e\u0431\u044b \u0443\u043c\u0435\u043d\u044c\u0448\u0438\u0442\u044c \u0432\u0435\u0440\u043e\u044f\u0442\u043d\u043e\u0441\u0442\u044c \u043e\u0448\u0438\u0431\u043a\u0438.<\/p>\n<p>  <\/p>\n<p>\u0412\u0430\u043c, \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u0437\u0430\u0445\u043e\u0447\u0435\u0442\u0441\u044f \u043a\u0430\u043a-\u0442\u043e \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044e \u0442\u0430\u043a\u0438\u0445 \u0442\u0440\u0438\u0433\u0433\u0435\u0440\u043e\u0432, \u0438 \u0442\u043e\u0433\u0434\u0430 \u0432\u0430\u043c \u043d\u0430\u0432\u0435\u0440\u043d\u044f\u043a\u0430 \u043d\u0443\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u0439\u0442\u0438 \u0432\u0441\u0435 foreign-\u0441\u0432\u044f\u0437\u0438 \u043c\u0435\u0436\u0434\u0443 \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u0442\u0430\u0431\u043b\u0438\u0446\u0435\u0439 \u0438 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u043c\u0438. \u0412\u043e\u0442 \u0441 \u044d\u0442\u0438\u043c \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u043c \u044d\u0442\u043e \u0432\u044b \u043b\u0435\u0433\u043a\u043e \u0441\u0434\u0435\u043b\u0430\u0435\u0442\u0435:<\/p>\n<p>  <\/p>\n<pre><code>  SELECT ccu.table_name AS foreign_table_name, kcu.column_name AS column_name   FROM information_schema.table_constraints AS tc     JOIN information_schema.key_column_usage AS kcu     ON tc.constraint_name = kcu.constraint_name     JOIN information_schema.constraint_column_usage AS ccu     ON ccu.constraint_name = tc.constraint_name   WHERE constraint_type = 'FOREIGN KEY' AND tc.table_name = '#{table_name}'   ORDER BY ccu.table_name; <\/code><\/pre>\n<p>  <\/p>\n<p>\u0415\u0449\u0435 \u043e\u0434\u0438\u043d \u043e\u0447\u0435\u043d\u044c \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0439 \u0441\u043e\u0432\u0435\u0442. \u041d\u0430\u0437\u044b\u0432\u0430\u0439\u0442\u0435 \u0442\u0440\u0438\u0433\u0433\u0435\u0440\u044b \u043e\u0434\u043d\u043e\u043e\u0431\u0440\u0430\u0437\u043d\u043e, \u0447\u0442\u043e\u0431\u044b \u0438\u043c\u0435\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0443\u0431\u0435\u0434\u0438\u0442\u044c\u0441\u044f \u0432 \u043d\u0430\u043b\u0438\u0447\u0438\u0438 \u0438\u043b\u0438 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0433\u043e \u043e\u0434\u043d\u0438\u043c \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u043c, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u044d\u0442\u043e\u0442 \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430\u0439\u0434\u0435\u0442 \u0432\u0441\u0435 touch-insert \u0442\u0440\u0438\u0433\u0433\u0435\u0440\u044b:<\/p>\n<p>  <\/p>\n<pre><code>  SELECT routine_name AS name   FROM information_schema.routines   WHERE     routine_name LIKE 'touch_for_%_on_insert' AND     routine_type ='FUNCTION' AND     specific_schema='public';<\/code><\/pre>\n<p>  <\/p>\n<p>\u0418 \u043d\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u043a \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0441\u0430\u043c\u043e\u0435 \u0441\u0442\u0440\u0430\u0448\u043d\u043e\u0435. \u0414\u0435\u043b\u043e \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u0440\u0435\u043b\u044c\u0441\u044b \u043d\u0435 \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u0430\u043d\u044b \u043d\u0430 \u0445\u043e\u0442\u044c \u0441\u043a\u043e\u043b\u044c\u043a\u043e-\u043d\u0438\u0431\u0443\u0434\u044c \u0443\u043c\u043d\u0443\u044e \u0431\u0430\u0437\u0443 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u0441\u043e\u0432\u0435\u0440\u0448\u0435\u043d\u043d\u043e \u043f\u043b\u0435\u0432\u0430\u0442\u044c \u0445\u043e\u0442\u0435\u043b\u0438 \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e \u0432 \u0431\u0430\u0437\u0435 \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u043c\u0435\u043d\u044f\u0442\u044c\u0441\u044f \u0445\u043e\u0442\u044c \u0447\u0442\u043e-\u0442\u043e, \u043a\u0440\u043e\u043c\u0435 \u043f\u043e\u043b\u044f <code>id<\/code>, \u0438 \u0442\u043e, \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u0438 \u0432\u0441\u0442\u0430\u0432\u043a\u0435. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0435\u0442 \u0432\u043c\u0435\u043d\u044f\u0435\u043c\u043e\u0433\u043e \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u0430 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c <code>RETURNING updated_at<\/code> \u043a update-\u0437\u0430\u043f\u0440\u043e\u0441\u0430\u043c \u043d\u0438\u043a\u0430\u043a\u043e\u0433\u043e \u043d\u0435\u0442, \u043d\u0443\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u043d\u044b\u0440\u043d\u0443\u0442\u044c \u0432\u043e \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u043e\u0441\u0442\u0438 Rails \u043f\u043e \u0441\u0430\u043c\u044b\u0435 \u0443\u0448\u0438.<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/5e2\/741\/5b9\/5e27415b90ea63490670e7d4e2e4e758.jpg\"><\/p>\n<p>  <\/p>\n<p>\u041c\u0430\u043d\u043a\u0438\u043f\u0430\u0442\u0447 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0441\u044f \u043d\u0435 \u0442\u0430\u043a\u043e\u0439 \u0443\u0436, \u0447\u0442\u043e\u0431\u044b \u0441\u0438\u043b\u044c\u043d\u043e \u0430\u043a\u043a\u0443\u0440\u0430\u0442\u043d\u044b\u0439, \u043d\u043e \u0432 \u043f\u0435\u0440\u0432\u0443\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0441\u0442\u0430\u0432\u0438\u043b\u0430\u0441\u044c \u0446\u0435\u043b\u044c \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u043c\u0435\u043d\u044c\u0448\u0435 \u043f\u043e\u0432\u0440\u0435\u0436\u0434\u0430\u0442\u044c \u0442\u0435\u043a\u0443\u0449\u0443\u044e \u0440\u0430\u0431\u043e\u0442\u0443 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430.<\/p>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u041f\u0440\u0438\u0432\u0435\u0434\u0443 \u0435\u0433\u043e \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code>module ActiveRecord   module Persistence     # https:\/\/github.com\/rails\/rails\/blob\/v5.2.0\/activerecord\/lib\/active_record\/persistence.rb#L729-L741     def _create_record(attribute_names = self.attribute_names)       attribute_names &amp;= self.class.column_names       attributes_values = attributes_with_values_for_create(attribute_names)        an_id, *affected_rows = self.class._insert_record(attributes_values).dup       self.id ||= an_id if self.class.primary_key       Hash[ApplicationRecord.custom_returning_columns(self.class.quoted_table_name, :create).take(affected_rows.size).zip(affected_rows)].each do |column_name, value|         public_send(\"#{column_name}=\", self.class.attribute_types[column_name.to_s].deserialize(value)) if value       end        @new_record = false        yield(self) if block_given?        id     end     private :_create_record      # https:\/\/github.com\/rails\/rails\/blob\/v5.2.0\/activerecord\/lib\/active_record\/persistence.rb#L710-L725     def _update_record(attribute_names = self.attribute_names)       attribute_names &amp;= self.class.column_names       attribute_names = attributes_for_update(attribute_names)        if attribute_names.empty?         affected_rows = []         @_trigger_update_callback = true       else         affected_rows = _update_row(attribute_names)         @_trigger_update_callback = affected_rows.any?       end        Hash[ApplicationRecord.custom_returning_columns(self.class.quoted_table_name, :update).take(affected_rows.size).zip(affected_rows)].each do |column_name, value|         public_send(\"#{column_name}=\", self.class.attribute_types[column_name.to_s].deserialize(value))       end        yield(self) if block_given?        affected_rows.none? ? 0 : 1     end     private :_update_record   end    module ConnectionAdapters     module PostgreSQL       module DatabaseStatements         # https:\/\/github.com\/rails\/rails\/blob\/v5.2.0\/activerecord\/lib\/active_record\/connection_adapters\/postgresql\/database_statements.rb#L93-L96         def exec_update(sql, name = nil, binds = [])           execute_and_clear(sql_with_returning(sql), name, binds) { |result| Array.wrap(result.values.first) }         end          # https:\/\/github.com\/rails\/rails\/blob\/v5.2.0\/activerecord\/lib\/active_record\/connection_adapters\/abstract\/database_statements.rb#L147-L152         def insert(arel, name = nil, pk = nil, _id_value = nil, sequence_name = nil, binds = [])           sql, binds = to_sql_and_binds(arel, binds)           exec_insert(sql, name, binds, pk, sequence_name).rows.first         end         alias create insert          # https:\/\/github.com\/rails\/rails\/blob\/v5.2.0\/activerecord\/lib\/active_record\/connection_adapters\/postgresql\/database_statements.rb#L98-L111         def sql_for_insert(sql, pk, id_value, sequence_name, binds) # :nodoc:           table_ref = extract_table_ref_from_insert_sql(sql)           if pk.nil?             # Extract the table from the insert sql. Yuck.             pk = primary_key(table_ref) if table_ref           end            returning_columns = quote_returning_column_names(table_ref, pk, :create)           if returning_columns.any?             sql = \"#{sql} RETURNING #{returning_columns.join(', ')}\"           end            super         end          # No source in original repo         def quote_returning_column_names(table_ref, pk, action)           returning_columns = []           returning_columns &lt;&lt; pk if suppress_composite_primary_key(pk)           returning_columns += ApplicationRecord.custom_returning_columns(table_ref, action)           returning_columns.map { |column| quote_column_name(column) }         end          # No source in original repo         def sql_with_returning(sql)           table_ref = extract_table_ref_from_update_sql(sql)            returning_columns = quote_returning_column_names(table_ref, nil, :update)            return sql if returning_columns.blank?           \"#{sql} RETURNING #{returning_columns.join(', ')}\"         end          # No source in original repo         def extract_table_ref_from_update_sql(sql)           sql[\/update\\s(\"[A-Za-z0-9_.\"\\[\\]\\s]+\"|[A-Za-z0-9_.\"\\[\\]]+)\\s*set\/im]           Regexp.last_match(1)&amp;.strip         end       end     end   end end<\/code><\/pre>\n<\/div>\n<\/div>\n<p>  <\/p>\n<p>\u0421\u0430\u043c\u043e\u0435 \u0433\u043b\u0430\u0432\u043d\u043e\u0435, \u0447\u0442\u043e \u0442\u0443\u0442 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043e\u0431\u0440\u0430\u0449\u0435\u043d\u0438\u0435 \u043a <code>ApplicationRecord.custom_returning_columns<\/code>, \u0447\u0442\u043e\u0431\u044b \u0443\u0437\u043d\u0430\u0442\u044c \u043a\u0430\u043a\u0438\u0435 \u0436\u0435 \u043a\u043e\u043b\u043e\u043d\u043a\u0438, \u043a\u0440\u043e\u043c\u0435 id \u043d\u0430\u0441 \u0438\u043d\u0442\u0435\u0440\u0438\u0441\u0443\u044e\u0442. \u0418 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u044d\u0442\u043e\u0442 \u043c\u0435\u0442\u043e\u0434 \u043a\u0430\u043a-\u0442\u043e \u0442\u0430\u043a:<\/p>\n<p>  <\/p>\n<pre><code>  class &lt;&lt; self     def custom_returning_columns(table_ref, action)       return [] if ['\"schema_migrations\"', '\"ar_internal_metadata\"'].include?(table_ref)        res = []       res &lt;&lt; :created_at if action == :create       res &lt;&lt; :updated_at        res += case table_ref              when '\"user_applications\"'                [:api_token]              when '\"users\"'                [:session_salt, :password_changed_at]              # ...              else                []              end        res     end   end<\/code><\/pre>\n<p>  <\/p>\n<hr>\n<p>  <\/p>\n<p>\u0412\u043c\u0435\u0441\u0442\u043e \u0432\u044b\u0432\u043e\u0434\u043e\u0432 \u043c\u043e\u0436\u043d\u043e \u0441\u043a\u0430\u0437\u0430\u0442\u044c, \u0447\u0442\u043e, \u0431\u043e\u043b\u044c\u043d\u0430\u044f \u0433\u043e\u043b\u043e\u0432\u0430 Rails \u0441\u0442\u0430\u043b\u0430 \u0447\u0443\u0442\u044c \u043c\u0435\u043d\u0435\u0435 \u0431\u043e\u043b\u044c\u043d\u0430\u044f. \u0422\u0430\u043a\u0438\u0435 \u0440\u0443\u0442\u0438\u043d\u043d\u044b\u0435 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u044b, \u043a\u0430\u043a <code>counter_cache<\/code> \u0438 <code>touch<\/code> \u043a\u0430\u043d\u0443\u0442 \u0432 \u043b\u0435\u0442\u0443 \u0438 \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u043e\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0434\u0443\u043c\u0430\u0442\u044c \u043e \u0447\u0435\u043c-\u0442\u043e \u0431\u043e\u043b\u0435\u0435 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u043e\u043c, \u0432\u0440\u043e\u0434\u0435 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f \u0432\u0438\u0441\u044f\u0447\u0438\u0445 \u043f\u0440\u043e\u0431\u0435\u043b\u043e\u0432, \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438 \u0434\u0430\u043d\u043d\u044b\u0445, \u043a\u0430\u0441\u043a\u0430\u0434\u043d\u043e\u043c \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u043b\u0438 \u043f\u0430\u0440\u0430\u043d\u043e\u0438\u0434\u0430\u043b\u044c\u043d\u043e\u043c \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0438. \u0415\u0441\u043b\u0438 \u044d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f \u043f\u043e\u043d\u0440\u0430\u0432\u0438\u043b\u0430\u0441\u044c, \u043a\u043e\u043d\u0435\u0447\u043d\u043e \u0436\u0435.<\/p>\n<\/div>\n<p>        <script class=\"js-mediator-script\">!function(e){function t(t,n){if(!(n in e)){for(var r,a=e.document,i=a.scripts,o=i.length;o--;)if(-1!==i[o].src.indexOf(t)){r=i[o];break}if(!r){r=a.createElement(\"script\"),r.type=\"text\/javascript\",r.async=!0,r.defer=!0,r.src=t,r.charset=\"UTF-8\";var d=function(){var e=a.getElementsByTagName(\"script\")[0];e.parentNode.insertBefore(r,e)};\"[object Opera]\"==e.opera?a.addEventListener?a.addEventListener(\"DOMContentLoaded\",d,!1):e.attachEvent(\"onload\",d):d()}}}t(\"\/\/mediator.mail.ru\/script\/2820404\/\",\"_mediator\")}(window);<\/script>     <br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/post\/421939\/\"> https:\/\/habr.com\/post\/421939\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"\n<div data-io-article-url=\"https:\/\/habr.com\/post\/421939\/\" class=\"post__text post__text-html js-mediator-article\">\n<p>\u0412\u043e-\u043f\u0435\u0440\u0432\u044b\u0445, \u0441\u0442\u0430\u0442\u044c\u044f \u043d\u0435 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u044f \u043b\u044e\u0431\u043b\u044e \u0440\u0435\u043b\u044c\u0441\u044b, \u0432\u043e-\u0432\u0442\u043e\u0440\u044b\u0445, \u0441\u0442\u0430\u0442\u044c\u044f \u043d\u0435 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u044f \u0438\u0445 \u043d\u0435\u043d\u0430\u0432\u0438\u0436\u0443. \u041a \u043d\u0438\u043c \u043c\u043e\u0436\u043d\u043e \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u044c\u0441\u044f \u0441\u043e\u0432\u0435\u0440\u0448\u0435\u043d\u043d\u043e \u043f\u043e-\u0440\u0430\u0437\u043d\u043e\u043c\u0443 \u0438 \u043b\u0443\u0447\u0448\u0435 \u043e\u043d\u0438 \u0441\u0442\u0430\u043d\u0443\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0435\u0441\u043b\u0438 \u0438\u0445 \u043c\u0435\u043d\u044f\u0442\u044c. \u0418 \u0445\u0443\u0436\u0435 \u043e\u043d\u0438 \u043c\u043e\u0433\u0443\u0442 \u0441\u0442\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0435\u0441\u043b\u0438 \u0438\u0445 \u043d\u0430\u0447\u0430\u0442\u044c \u043c\u0435\u043d\u044f\u0442\u044c. \u041d\u0443, \u0432 \u043e\u0431\u0449\u0435\u043c, \u044f \u0432\u0430\u0441 \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0434\u0438\u043b, \u0430 \u0432\u044b \u043c\u0435\u043d\u044f \u043f\u043e\u043d\u044f\u043b\u0438.<\/p>\n<p>  <\/p>\n<p>\u041e\u0434\u043d\u0430 \u0438\u0437 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0445 \u043a\u043e\u043d\u0446\u0435\u043f\u0446\u0438\u0439 ActiveRecord \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u0431\u0430\u0437\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0443\u0442\u0438\u043b\u0438\u0442\u0430\u0440\u043d\u0430 \u0438 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0430. \u041d\u0443, \u0432\u044b \u0442\u0430\u043a\u0438\u0435 \u0441\u0438\u0434\u0438\u0442\u0435, \u043f\u0438\u0448\u0435\u0442\u0435 \u0441\u0432\u043e\u0438 \u043c\u043e\u0434\u0435\u043b\u044c\u043a\u0438 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c MySQL \u0438 \u0432\u0434\u0440\u0443\u0433 \u0433\u0434\u0435-\u0442\u043e \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u043b\u0438, \u0447\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0432\u043e\u0442 \u0442\u0430\u043a \u0432\u043e\u0442 \u0432\u0437\u044f\u0442\u044c \u0438 \u0437\u0430\u043c\u0435\u043d\u0438\u0442\u044c MySQL \u043d\u0430 MongoDB. \u0425\u043e\u0440\u043e\u0448\u043e, \u043d\u0435 \u0442\u0430\u043a \u0440\u0430\u0434\u0438\u043a\u0430\u043b\u044c\u043d\u043e, \u043d\u043e, \u0441\u043a\u0430\u0436\u0435\u043c, \u043d\u0430 PostgreSQL \u0443 \u0432\u0430\u0441 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043f\u0440\u0438\u0447\u0438\u043d\u044b \u0437\u0430\u043c\u0435\u043d\u0438\u0442\u044c MySQL. \u0418\u043b\u0438 \u043d\u0430\u043e\u0431\u043e\u0440\u043e\u0442, \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0438\u043c\u0435\u044e \u043f\u0440\u043e\u0442\u0438\u0432 MySQL. \u0422\u0443\u0442 ActiveRecord \u0443\u0442\u0432\u0435\u0440\u0436\u0434\u0430\u0435\u0442, \u0447\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0432\u0430\u043c \u044d\u0442\u043e \u043f\u0440\u043e\u0449\u0435 \u043f\u0440\u043e\u0441\u0442\u043e\u0433\u043e, \u043c\u043e\u043b \u0441\u043a\u043e\u0443\u043f\u044b, before\/after \u0444\u0438\u043b\u044c\u0442\u0440\u044b \u0438 \u0430\u0441\u0441\u043e\u0446\u0438\u0430\u0446\u0438\u0438 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u044b, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u043f\u0435\u0440\u0435\u0436\u0438\u0432\u0430\u0442\u044c \u0437\u0430 \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043a \u0431\u0430\u0437\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u0437\u0430\u0431\u043e\u0442\u0438\u0442\u0441\u044f \u043e \u043b\u043e\u0433\u0438\u043a\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u0427\u0442\u043e \u0432\u043c\u0435\u0441\u0442\u043e <code>WHERE is_archived = TRUE<\/code> \u0432\u044b \u0441 \u0440\u0430\u0434\u043e\u0441\u0442\u044c\u044e \u043d\u0430\u043f\u0438\u0448\u0435\u0442\u0435 <code>where(is_archived: true)<\/code> \u0438 ActiveRecord \u0441\u0434\u0435\u043b\u0430\u0435\u0442 \u0432\u0441\u0435 \u0437\u0430 \u0432\u0430\u0441. \u0412\u0441\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u044b \u0431\u0443\u0434\u0443\u0442 \u043f\u0440\u0435\u0432\u0435\u0434\u0435\u043d\u044b \u0434\u043b\u044f PostgreSQL, \u0430 \u043d\u0435 \u0434\u043b\u044f MySQL, \u0442\u0430\u043a \u0447\u0442\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 MySQL \u0432\u044b\u043d\u0443\u0436\u0434\u0435\u043d\u044b \u0431\u0443\u0434\u0443\u0442 \u0438\u0437\u043e\u0431\u0440\u0435\u0442\u0430\u0442\u044c \u0441\u0432\u043e\u0439 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u0432\u0435\u043b\u043e\u0441\u0438\u043f\u0435\u0434.<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/e53\/ff1\/cfc\/e53ff1cfc747b1a79b89c8139cd1d196.gif\"><\/p>\n<p>  <\/p>\n<p>\u041d\u043e \u043a\u0430\u043a \u0431\u044b \u043d\u0435 \u0442\u0430\u043a! \u041d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435 \u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f, \u0447\u0442\u043e \u044d\u0442\u043e\u0442 \u0441\u043b\u043e\u0439 \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0446\u0438\u0438 \u0432\u0441\u044f \u043d\u0430\u043f\u0440\u043e\u0447\u044c \u0434\u044b\u0440\u044f\u0432\u0430\u044f, \u043a\u0430\u043a \u043a\u043e\u0440\u044b\u0442\u043e \u0438\u0437 \u0441\u043a\u0430\u0437\u043a\u0438 \u043e \u0417\u043e\u043b\u043e\u0442\u043e\u0439 \u0420\u044b\u0431\u043a\u0435. \u0418 \u0447\u0442\u043e \u043c\u043d\u043e\u0433\u0438\u0435 \u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043d\u0435\u043b\u044c\u0437\u044f, \u0432\u0440\u043e\u0434\u0435 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f \u0434\u0430\u0442 \u0438\u043b\u0438 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043c\u0430\u0441\u0441\u0438\u0432\u0430\u043c\u0438. \u0418 \u043f\u043e\u043b\u0443\u0447\u0430\u044e\u0442\u0441\u044f \u0441\u043a\u043e\u0443\u043f\u044b \u0441 \u0432\u044b\u043d\u0443\u0436\u0434\u0435\u043d\u043d\u044b\u043c\u0438 <code>where(\"#{quoted_table_name}.finished_at &gt;= ?\", Date.current)<\/code> \u0438\u043b\u0438 <code>where(\"#{quoted_table_name}.other_ids &lt;@ ARRAY[?]\", ids)<\/code>. \u041d\u0430 \u0447\u0442\u043e ActiveRecord \u0434\u0430\u0435\u0442 \u0432\u043f\u043e\u043b\u043d\u0435 \u043e\u0441\u043e\u0437\u043d\u0430\u043d\u043d\u044b\u0439 \u0438 \u043b\u043e\u0433\u0438\u0447\u043d\u044b\u0439 \u043e\u0442\u0432\u0435\u0442: \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u044d\u0442\u043e. \u0412\u043c\u0435\u0441\u0442\u043e \u043c\u0430\u0441\u0441\u0438\u0432\u043e\u0432 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 habtm-\u0441\u0432\u044f\u0437\u044c, \u0430 \u0435\u0441\u043b\u0438 \u043d\u0430\u0434\u043e \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0442\u044c \u0434\u0430\u0442\u044b, \u0436\u0438\u0432\u0438\u0442\u0435 \u0441 \u044d\u0442\u0438\u043c. \u0414\u0430, \u0438 \u043d\u0435 \u0434\u0430\u0439 \u0431\u043e\u0433 \u0432\u0430\u043c \u043f\u0440\u043e\u043f\u0443\u0441\u0442\u0438\u0442\u044c <code>quoted_table_name<\/code> \u0432 \u0442\u0430\u043a\u043e\u043c \u0441\u043a\u043e\u0443\u043f\u0435 \u2014 \u043f\u0435\u0440\u0432\u044b\u0439 \u0436\u0435 <code>includes<\/code> \u0438\u043b\u0438 <code>joins<\/code> \u0440\u0430\u0441\u0441\u0442\u0430\u0432\u0438\u0442 \u0432\u0441\u0435 \u043d\u0430 \u0441\u0432\u043e\u0438 \u043c\u0435\u0441\u0442\u0430. \u041f\u0440\u043e\u0449\u0435 \u0432\u0435\u0437\u0434\u0435 \u0438 \u0432\u0441\u0435\u0433\u0434\u0430 \u043f\u0438\u0441\u0430\u0442\u044c, \u0447\u0442\u043e\u0431\u044b \u0440\u0443\u043a\u0443 \u043d\u0435 \u0441\u0431\u0438\u0432\u0430\u0442\u044c.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-288815","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/288815","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=288815"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/288815\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=288815"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=288815"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=288815"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}