• Как в PostgreSQL сделать уникальный идентификатор среди всех таблиц базы (глобально)?

    Athanor
    @Athanor
    Лайк + Решение: не жмись, нажми
    Здравствуйте. То, о чем вы говорите, называется GUID, но какого-то унифицированного одного алгоритма его генерации для всех нет. Но в postgres есть расширения, которые могут вам помочь и вам не придется генерить его на уровне приложения.
    Эта суперкороткая статья может быть вам полезна: https://postgrespro.ru/docs/postgrespro/9.5/dataty... и дать начальный стимул и понимание куда копать дальше. Удачи )

    Update (29.01.20):

    Сразу к делу и примерам. Сделать это можно, например, так:

    -- Начнем со схемы данных. На всякий случай проиллюстрирую как может выглядеть идея генерации guid базой, с которой
    -- я в самом начале и начал. Но вам, наверное, не будет смысла эту функцию использовать, т.к. сценарий использования
    -- у вас другой.
    --
    -- Обратите также внимание, что я поменял тип на BIGINT. У меня была гипотеза, что вы используете TEXT, т.к., возможно,
    -- не знали про BIGINT. Недостаток TEXT в том, что Postgres не построит по нему индекс и выборки по id будут все
    -- медленнее и медленнее. Я бы порекомендовал сразу отрефакторить все так, чтобы использовался именно BIGINT.
    --
    -- Все поля также назвал английскими словами, т.к. это можно считать индустриальным стандартом. NOT NULL добавил
    -- по наитию: логика подсказывает, что PRIMARY KEY у каждой таблице обязателен, как и данные. Просто для полноты.
    
    -- Начнем с функции, которая будет генерировать нам ID для примера.
    
    CREATE OR REPLACE FUNCTION guid()
        RETURNS BIGINT AS
    $BODY$
    BEGIN
        -- Количество секунд с начала эпохи Линукса и домножаем на какой-то множитель, чтобы увеличить точность
        -- и получить 1580307917143.431 вместо 1580307917.143431
        RETURN CAST(EXTRACT(EPOCH FROM NOW()) * 1000 AS BIGINT);
    END;
    $BODY$
        LANGUAGE 'plpgsql' VOLATILE;
    
    -- Теперь перейдем к самой схеме данных и создадим ее.
    
    CREATE TABLE users (
       id BIGINT PRIMARY KEY NOT NULL DEFAULT guid(),
       pseudonym TEXT NOT NULL
    );
    
    CREATE TABLE posts (
       id BIGINT PRIMARY KEY NOT NULL DEFAULT guid(),
       content TEXT NOT NULL
    );
    
    CREATE TABLE comments (
      id BIGINT PRIMARY KEY NOT NULL DEFAULT guid(),
      text TEXT NOT NULL
    );
    
    -- Для того чтобы повесить CONSTRAINT на id целевых таблиц, понадобится сделать VIEW, котоый будет содержать все
    -- id из всех этих таблиц, а также функцию, которую мы сможем использовать для CONSTRAINT. По сути, делаем то же,
    -- что делали бы на уровне приложения, но на уровне БД.
    
    CREATE OR REPLACE VIEW all_ids AS
    SELECT id FROM users UNION
    SELECT id FROM posts UNION
    SELECT id FROM comments;
    
    -- Теперь перейдем к функции, которая и будет выполнять всю грязную работу.
    
    CREATE OR REPLACE FUNCTION is_unique_id (BIGINT)
        RETURNS BOOLEAN AS 'SELECT CASE WHEN
                                       (SELECT 1
                                        FROM all_ids
                                        WHERE  id = $1) > 0
                            THEN FALSE ELSE TRUE END'
        LANGUAGE 'sql' WITH  (isstrict);
    
    -- Осталось только повесить CONSTRAINT
    
    ALTER TABLE users ADD CONSTRAINT id CHECK (is_unique_id(id));
    ALTER TABLE posts ADD CONSTRAINT id CHECK (is_unique_id(id));
    ALTER TABLE comments ADD CONSTRAINT id CHECK (is_unique_id(id));
    
    -- А теперь внимание. Теперь вам придется быть очень внимательным при добавлении таблиц, в рамках которых id должен
    -- быть уникален. При добавлении новой таблцы будет необходимо:
    --   1. Пересоздать VIEW, дополнив запрос новыми таблицами.
    --   2. Не забыть повесить аналогичный CONSTRAINT на новую таблицу.
    --
    -- Также обратите внимание, что при вставке новой записи в любую из таблиц будет проверяться весь созданный VIEW
    -- и очень важно чтобы это был не полнотекстовый поиск, а работали индексы, поэтому так важно отрефакторить все в BIGINT.
    
    -- Пришло время тестирования. Вставляем данные.
    
    INSERT INTO users (pseudonym) VALUES ('Первый');
    INSERT INTO users (pseudonym) VALUES ('Второй');
    
    INSERT INTO posts (content) VALUES ('О том как надо');
    INSERT INTO posts (content) VALUES ('О том как не надо');
    
    INSERT INTO comments (text) VALUES ('Я думаю что решение...');
    INSERT INTO comments (text) VALUES ('Хорошо я пропробую сделать...');
    
    -- И глянем что получилось.
    
    SELECT * FROM users;
    -- 1580326610797	Первый
    -- 1580326611809	Второй
    
    SELECT * FROM posts;
    -- 1580326613690	О том как надо
    -- 1580326613712	О том как не надо
    
    SELECT * FROM comments;
    -- 1580326613779	Я думаю что решение...
    -- 1580326613797	Хорошо я пропробую сделать...
    
    -- Время X: тестируем нашу проверку, пытаясь вставить в таблицу users id из таблицы comments:
    
    INSERT INTO users (id, pseudonym) VALUES (1580326613779, 'tiabc');
    -- [23514] ERROR: new row for relation "users" violates check constraint "id" Detail: Failing row contains (1580326613779, tiabc)
    
    -- Profit!


    Что хочу сказать с точки зрения проектирования архитектуры и вообще. Использование любого нового инструмента должно быть обосновано. Как правило, сложная схема БД ведет к сложностям в поддержке и к тому, что какие-то вещи забывают обновляться, в отличие от уровня приложения.

    В вашем же случае, честно говоря, схему очень сильно хочется упростить, а не усложнить. Хочется добавить поле created_at с DEFAULT CURRENT_TIMESTAMP() и хочется добавить реляционные связи. Либо же в принципе уйти на нереляционную БД и задать структуру сущностей там (что опять же должно быть обосновано).

    И дальше именно на уровне приложения делать эту выборку, т.к. это упростит поддержку кода, а с точки зрения трудозатрат ваших и БД при выборках и вставках будет то же самое.

    Помимо этого, поскольку вы делаете процессинг на основе id и его порядковых номеров, не могу не порекомендовать обратить внимание на одни из базовых принципов проектирования ПО. Конечно, вся картина не видна, но я тут вижу нарушение буквы S (Single Responsibility), что id у вас и за порядок отвечает, и за уникальность (да еще и между несколькими таблицами). Хочется как-то их развязать. Со временем жизни продукта это часто оказывается полезно.

    Опять же, беспокойств о том, что вы хотите достичь, достаточно много, но если отвечать именно конкретно на ваш вопрос и давать дополнительно какие-то рекомендации, то как-то так )

    Желаем удачи, образования и всех благ )

    С уважением,
    Иван Томилов
    CEO of Athanor
    Ответ написан
    2 комментария
  • Как сделать резиновое CSS Grid горизонтальное меню независимо от количества элементов?

    Как сделать резиновое CSS Grid горизонтальное меню независимо от количества элементов?


    Задать размер для автоматически добавляемых колонок через grid-auto-columns: minmax(100px, 20%); и добавление новых элементов в колонки через grid-auto-flow: column;

    Можете добавлять сколько угодно колонок

    Результат:
    https://codepen.io/hisbvdis/pen/pozwKmX
    Ответ написан
    1 комментарий
  • Есть ли возможность используя Vue не отображать фигурные скобки (Mustache синтаксис) при загрузке/инициализации страницы?

    Vlad_IT
    @Vlad_IT
    Front-end разработчик
    Используйте такую директиву v-cloak для блока с вашим приложением. vue удалит его после инициализации, а значит, можно написать такой css, который будет прятать блок с таким атрибутом.
    div[v-cloak] {
        display: none;
    }
    Ответ написан
    2 комментария
  • Как в Git продолжать разработку без отправки изменений на удалённый репозиторий?

    1) Фичу 1 оставить в своем репозитории и не лить ее в мастер локально
    2) Если для Фичи 2 изменения в Фиче 1 не нужны, просто переходишь в мастер, делаешь гит пулл и делаешь бранч для Фичи 2
    2а) Если для Фичи 2 нужны изменения, которые ты сделал в Фиче 1, то после второго шага делаешь gi rebase F1
    3) Перед тем как делать мерж реквест и к первой фиче и ко второй делаешь
    git fetch && git rebase origin/master таким образом ты в ветку подтянешь накопленные в мастере обновления и решишь конфликты если возникнут
    Ответ написан
    4 комментария
  • Как разделить проект на несколько независимых, затем подключать и использовать их в одном?

    Их возможно оформить в виде npm модулей? Если да, читайте документацию npm install он умеет ставить с гит репозитория. Ещё вариант - git submodules, но там большой шанс нарваться на танцы с бубном.
    Ответ написан
    3 комментария
  • IDE для PHP, JavaScript, HTML, CSS с встроенным веб и MySQL сервером и phpMyAdmin, FTP?

    Есть такая IDE, называется Windows.
    А под неё куча плагинов для твоих нужд.
    PhpStorm, SourceTree, HeidiSql, и вроде ещё парочка.

    Или ты правда думаешь, что есть прямо такой идеальный комбайн?
    Ответ написан
    7 комментариев
  • Почему при добавлении тега appendChild'oм, контент не отображается?

    Petroveg
    @Petroveg
    Миром правят маленькие с#@&ки
    Я не знаком с теми объектами, чьими методами вы пользуетесь для добавления, поэтому сразу к делу — у каждого языка разметки есть идентификатор Namespase. Более того, для ряда атрибутов (например, xlink:href) также есть своё пространство имён.

    Для создания элементов и таких атрибутов существуют специальные методы createElementNS(), setAttributeNS().

    В привычных createElement() и setAttribute() используется пространство имён xHTMLwww.w3.org/1999/xhtml. К тому же, setAttributeNS() можно использовать и вместо привычного setAttribute() с указанием null для пространства имён. В этом случае будет использовано то пространство имён, в котором создан сам элемент.

    Набросал пример для создания объектов с описанием в виде JSON.

    Структура и указание пространств имён
    var NS = 'http://www.w3.org/2000/svg',
    	NSL = 'http://www.w3.org/1999/xlink',
    	elements = [
    		{
    			name: 'svg',
    			attr: {
    				'class': 'main'
    			},
    			children: [
    				{
    					name: 'symbol',
    					attr: {
    						id: 'square',
    						viewBox: '0 0 100 100'
    					},
    					children: [
    						{
    							name: 'rect',
    							attr: {
    								x: 0,
    								y: 0,
    								width: 100,
    								height: 100,
    								fill: 'rgba(51,102,204,1)'
    							}
    						}
    					]
    				},
    				{
    					name: 'symbol',
    					attr: {
    						id: 'circle',
    						viewBox: '0 0 100 100'
    					},
    					children: [
    						{
    							name: 'circle',
    							attr: {
    								cx: 50,
    								cy: 50,
    								r: 50,
    								fill: 'rgba(51,204,102,1)'
    							}
    						}
    					]
    				}
    			]
    		},
    		{
    			name: 'svg',
    			attr: {
    				'class': 'icon'
    			},
    			children: [
    				{
    					name: 'use',
    					attr: {
    						'xlink:href': '#square'
    					}
    				}
    			]
    		}
    	],
    	newElement = {
    		name: 'svg',
    		attr: {
    			'class': 'icon'
    		},
    		children: [
    			{
    				name: 'use',
    				attr: {
    					'xlink:href': '#circle'
    				}
    			}
    		]
    	};

    Создание элемента
    function createSVG (elem) {
    	var svgElement = document.createElementNS(NS, elem.name);
    
    	if (elem.attr) {
    		Object.keys(elem.attr).forEach(function (value) {
    			if (value.indexOf('xlink') < 0) {
    				svgElement.setAttribute(value, elem.attr[value]);
    			} else {
    				svgElement.setAttributeNS(NSL, value, elem.attr[value]);
    			}
    		});
    	}
    
    	if (elem.children) {
    		elem.children.forEach(function (value) {
    			svgElement.appendChild(createSVG(value));
    		});
    	}
    
    	return svgElement;
    }

    Использование
    elements.forEach(function (element) {
    	document.body.appendChild(createSVG(element));
    });
    document.body.appendChild(createSVG(newElement));

    Стили
    .main {
    	display: none;
    }
    .icon {
    	width: 100px;
    	height: 100px;
    }
    Ответ написан
    Комментировать
  • Можно ли сделать сеттер и геттер не для свойства объекта а для самого объекта?

    k12th
    @k12th
    console.log(`You're pulling my leg, right?`);
    Ну можно положить сам объект в window и сделать соответствующие геттер и сеттер.
    Object.defineProperty(window, 'prozrachnost', {
        set(value) {
            if (value instanceof Osobaya_peremennaya) {
                window._prozrachnost = value;
            } else {
                window._prozrachnost.znachenie = value;
            }
        },
        
        get() {
            return window._prozrachnost;
        },
    });
    
    window.prozrachnost = new Osobaya_peremennaya;
    window.prozrachnost = 0.5;

    (не пробовал. а если без window. то в строгом режиме не запустится)

    Но вообще всю эту геттерно-сеттерную магию не очень весело читать, разгребать и дебажить. Лучше сделайте как Александр посоветовал, он всё правильно сказал.
    Ответ написан
    2 комментария
  • Можно ли сделать сеттер и геттер не для свойства объекта а для самого объекта?

    @codemafia
    Самоотвод
    Нет. Вы присваиваете переменной другое значение, теряя экземпляр объекта.
    Если нужно сократить запись, напишите метод в объекте, который будет обрабатывать сразу несколько переменных из параметра-объекта.
    Как нибудь так:
    myshader.someFunc({foo: "This", bar: "works!"})
    Ответ написан
    1 комментарий
  • IDE для PHP, JavaScript, HTML, CSS с встроенным веб и MySQL сервером и phpMyAdmin, FTP?

    С каких пор в phpstorm нету Javascript? Самая классная связка это шторм и open server
    Ответ написан
    1 комментарий