Страницы

Поиск по вопросам

суббота, 1 июня 2019 г.

Проблема с миграцией базы данных на postgres

При создании базы возникает следующая ошибка:
andrey@asus:~/project/odnogrupniki$ rake db:create:all FATAL: Peer authentication failed for user "odnogrupniki"
логи целиком: ТУТ
databse.yml:
default: &default adapter: postgresql encoding: unicode pool: 5 timeout: 5000 username: 'odnogrupniki' password: '1111'
development: <<: *default database: odnogrupniki
test: <<: *default database: odnogrupniki_test
production: <<: *default database: odnogrupniki_production
в Gemfile добавлял: gem 'pg' Bundle - выполнял
andrey@asus:~/project/odnogrupniki$ psql --version psql (PostgreSQL) 9.5.1
Пользователя создавал так:
postgres@asus:/home/andrey/project/odnogrupniki$ createuser odnogrupniki -P -S -R -D Enter password for new role: Enter it again:


Ответ

Локально можно настроиться на работу по peer athentication, но для этого в базе данных должен быть пользователь с таким же именем, какой у подключающегося логин в операционной системе. Для разработки это можно настроить максимально быстро на чистом дистрибутиве.
Чтобы ActiveRecord подключался, удостоверяясь только с помощью учётной записи подключающегося через Unix domain socket, то надо убрать логин, пароль и хост из настроек подключения. Совсем. А сделать "себя" суперпользователем в БД на свежеустановленном PostgreSQL (когда пользователь там всего один, postgres) можно в одну команду:
sudo -u postgres createuser --superuser $(whoami)

\______________/ \______________________________/ Притворившись Создать суперпользователя с postgres именем, выведенным командой whoami
А дальше обычное rake db:create и прочее.
Плюсов у такого подхода хватает:
Работает с настройками по умолчанию: установил, сделал себя-администратора и вперёд Учётные данные ни в какой момент не существуют в рабочем дереве
На "боевом" сервере так делать не стоит, но это уже совсем другая история...

Как открывать приложение при переходе на ссылку Android

Например, на сайте есть спец ссылки aliexpress://product/desc?productId=32309744542 при переходе по которым открывается приложение AliExpress. Если мне нужно добавить GET параметр, например, aliexpress://?param=32309744542 он должен быть передан в ссылку, так: http://m.aliexpress.com?param=32309744542 (в обычном браузере). В приложении невозможно просмотреть ссылку поэтому я хочу узнать, будет ли это работать?


Ответ

На андроиде схема такая:
В манифесте для нужной активити добавляется IntentFilter, в коем указывается на нажатия на какие ссылки нужно реагировать. В этой активити, уже в коде через Intent вытаскивается ссылка, коей запущено приложение. Ссылка разбирается на части и выстраивается логика её обработки.
В манифесте примерно так (сначала идёт пример обычных ссылок на сайт, потом типа такой как вы в вопросе написали):


В активити получаем ссылку так:
Uri data = getIntent().getData(); Log.d("ЛОГ", "Uri data: " + data);

Конструкторы в Java

Здравствуйте, скажите, пожалуйста, какя разница между конструкторами:
int age; string name; Man (int age, string name){ age=age; name=name; }
Man (int age, string name){ this.age=age; this.name=name; }


Ответ

В первом вы не установите значение у полей класса. Это называется сокрытие переменных(Variable shadowing). Хороший ответ о сокрытии на SOen

Использование ScrollView вместо ListView

Есть приложение (чат) в котором нужно сделать отображение сообщений в виде списка. Но не просто отобразить списком view-хи с текстом, view могут содержать в себе еще картинки + view сами по себе могут быть разными. При простом отображении элементов выбор пал бы на ListView. Но нужно не только их отображать но и иметь возможность их видоизменять, анимировать и т.д. Попробовав сделать список через ScrollView я столкнулся с проблемой что ScrollView притормаживает, как я понял потому что элементы не пересоздаются, а хранятся в памяти! Вопрос: каким образом лучше реализовать нужную задачу, лично я склоняюсь к ScrollView, так как с ним по идее должно быть проще работать, но как можно решить проблему притормаживания, может есть какие то механизмы?
p.s. может кто то знает как подобные задачи реализован в Viber, VK и остальные messanger


Ответ

Не используйте ScrollView, со временем он будет тормозить еще больше, по мере добавления View. Используйте RecyclerView, примеров в сети достаточно. В нем вы можете указывать любые View в зависимости от объекта, который вам нужно показать. В добавок "ячейки" в RecyclerView которые ушли за экран, дестроятся. это экономит память.
UPD У RecyclerView можно переопределить метод getItemViewType(), и в зависимости от возвращаемого значения в onCreateViewHolder() в можете подставлять нужную View

Как избавиться от параллельных иерархий наследования?

Я решаю задачу о нахождении лидера (leader election) Это чисто алгоритмическая задача, у которой есть 2 формы: однонаправленное кольцо и двунаправленное. Для представления данных я создал свой собственный класс для списка, закрученного в кольцо. То есть у меня два алгоритма, по одному для каждой формы задачи.
public abstract class MyAbstractRoundList {
protected int size; protected Agent[] arr = new Agent[1]; protected int index = 0;
public boolean isEmpty() { return size == 0; }
public int size() { return size; }
public void add(Agent agent) { if (size >= arr.length) { Agent[] temp = arr; arr = new Agent[temp.length * 2]; System.arraycopy(temp, 0, arr, 0, temp.length); } arr[size++] = agent; } // и дальше еще много методов
Далее я создаю наследников этого класса для однонаправленного режима и для двунаправленного. Реализации в них конечно различаются. Далее, у меня есть класс:
public class LeaderElection {
public static void solve(MyAbstractList list, int i) { if (i == 0) { list.initiateStartState(); } else { list.setMessages(); } }
}
В нем у меня решение для однонаправленного режима. И есть похожий класс с решением для двунаправленного, но реализации конечно тоже различаются. Что бы не прописывать в клиентском коде
if(isOneDirectMode()){ LeaderElection.solve(); { if(isBiDirectMode()){ BiLeaderElection.solve(); }
Я мог бы так же создать абстрактный класс для решения и его наследников и пользоваться полиморфизмом (так я и делаю для списков). Но вот тут и возникает проблема: у меня получаются параллельные иерархии наследования. Если появится новый режим я должен буду добавить новый класс подкласс MyAbstractRoundList и новый подкласс решения. Можно как то избавиться от этого? Я вижу только один способ: Можно было бы сделать в MyAbstractRoundList абстрактный метод solve() и реализовывать его в подклассах каждого режима так как это требуется для конкретного режима. Но это плохо, потому что тогда у меня подклассы MyAbstractRoundList будут не только хранить данные, но и решать задачу. То есть выполнять 2 функции.


Ответ

Они не параллельны. Изменения в одной иерархии никак не влекут за собой изменения в другой иерархии.
Если появится новый режим я должен буду добавить новый класс подкласс MyAbstractRoundList и новый подкласс решения. Можно как то избавиться от этого? Я вижу только один способ: Можно было бы сделать в MyAbstractRoundList абстрактный метод solve() и реализовывать его в подклассах каждого режима так как это требуется для конкретного режима.
Решение задачи - это поведение. Поведение лучше описывать интерфейсами.
public interface Solver { void solve(MyAbstractList list, int i); } ... public class LeaderElection implements Solver {
... public class BiLeaderElection implements Solver {
... public class MultiTreadingLeaderElection implements Solver {
У вас отдельная иерархия наследования классов, отвечающих за хранение данных, и отдельная иерархия классов, отвечающих за решения. Это нормально. Если появится новый вид хранения (новый тип списка), вы добавите новый класс-наследник MyAbstractRoundList. Это никак не связано с решениями, новый класс может использоваться и существующими решениями. Если потребуется добавить новый способ решения, вы добавите новый класс, реализующий интерфейс Solver, и это не обязательно должно отразиться на иерархии классов для хранения.
При таком подходе у вас всегда будет работать код solver.solve(abstractList, i);, если в переменную solver положить объект любого класса, реализующего интерфейс Solver, а в переменную abstractList - любой объект класса-наследника MyAbstractRoundList, и самое главное - этот код не придется менять при добавлении новых классов, как и должно быть с точки зрения ООП.

UPD. Есть данные, есть поведение. В рамках класса поля описывают данные, методы - поведение. Например, я руковожу бригадой роботов. Одни из них могут строить, другие - переносить, третьи - разрушать, четвертые - поливать. Робот-строитель, например, может принести себе стройматериал, но только в небольшом количестве, таким образом, он может и строить, и носить. А робот-носитель - только носить. И если вдруг поступает задача срочно разгрузить вагон стройматериалов, то мне надо собрать всех роботов, умеющих носить. И мне плевать, что это за роботы. Хоть робот-поливалка. Если может носить - пусть идет носить. Я просто выберу роботов с нужным мне поведением, и буду уверен, что они смогут сделать то, что мне надо.
public interface Carrier { void carry(); //нести }
public interface Builder { void build(); //построить }
public interface Destroer { void destroy(); //сломать }
public class RobotBuilder extends Robot implements Builder, Carrier { public void carry() {
}
public void build() {
} }
public class RobotDestroer extends Robot implements Destroer { public void destroy() {
} }
public class RobotCarrier extends Robot implements Carrier { public void carry() {
} }

Как вы истрактовали бы постановку тестовой задачи?

Имеется тестовое задание:
Дан файл вида
operand1;operand2;operation;result operand1;operand2;operation;result operand1;operand2;operation;result operand1;operand2;operation;result Каждая строка описывает арифметическое действие. operand1 и operand2 - операнды, целые числа operation - арифметическое действие + - / * result - результат операции operation над operand1 и operand2 В файле могут содержаться любые значения полей Требуется Реализовать юнит (JUnit) тесты арифметических действий. Каждое действие должно выглядеть в отчете как отдельный тестовый сценарий Конец задания
Я понимаю, как написать тесты JUnit, но не понимаю, что именно тестируется в данном случае.
Правильно ли я считаю, что нужно сначала написать код, который парсит переменные, 4 функции для разных арифметических действий, а потом проверять с помощью JUnit корректность работы функций на основании тестовых равенств в файле ?
Прошу вас высказать свое понимание задачи.


Ответ

Я бы написал скрипт (хотя, если там несколько строк, то можно и ручками), который на основании исходного файла нагенерирует Java файл с тестами. То есть, на каждую строку исходного файла будет генерировать что то вида
@Test public void test1() { int actual = operand1 operationoperand2; int expect = result; assertEquals(expect , actual); }
ну м конечно несколько строк "обвязки" для всего этого, что бы модуль был "компилируемый".
В более навороченном виде я бы добалял проверку на 0 для operand2 если operation равно /
UPD
Вот на коленке на perl сделать за минут 5, для собеседования считаю самое оно
#!/usr/bin/perl
use strict; use warnings;
print ' import junit.framework.*;
public class JavaTest extends TestCase {
protected void setUp(){
} ';
my $i = 1; while (my $line = <>) { chomp $line; my ($op1, $op2, $oper, $result) = split /;/, $line; print <<"ONE_TEST"; \@Test public void test$i() { int actual = $op1 $oper $op2; int expect = $result; assertEquals(expect, actual); }
ONE_TEST
$i += 1; }
print "}
";

Android. AlertDialog. Как изменить цвет фона у кнопок?

Как изменить цвет кнопок в АлертДиалоге?

В разметке диалога задаю
android:background="@color/background_window"
все, кроме кнопок подсвечивается серым цветом
пробую вот так:
dialog.getButton(DialogInterface.BUTTON_POSITIVE).setBackgroundColor(ContextCompat.getColor(MyApplication.getAppContext(), R.color.background_window));
приложение падает при открытии диалога
Заранее спасибо


Ответ

Решение выше перекрашивает только бакграунд у кнопок

По сути ответ на вопрос был закоментирован в ответе выше
Перед открытием диалога вставил строчку:
dialog.getWindow().setBackgroundDrawableResource(R.color.background_window);
и все заработало:

Странно, что строка в разметке не устанавливает бэкграунд для панели кнопок