суббота, 4 февраля 2017 г.

Ubuntu Live: Restore partitions

Download and install gpart:

wget http://archive.ubuntu.com/ubuntu/pool/universe/g/gpart/gpart_0.3-3_amd64.deb

sudo dpkg -i gpart_0.3-3_amd64.deb

sudo apt-get install -f
View partition table on the drive:
sudo fdisk -l /dev/sda
If OK, write partition table to the drive:
sudo gpart -W /dev/sda /dev/sda

суббота, 24 декабря 2016 г.

Bitbucket: использование нескольких ssh ключей на одном компе

  • Генерируем новый ssh ключ (при этом указать имя не id_rsa, а например work)
  • Создаем файл конфигурации ~/.ssh/config и добавляем в него:
    Host work
      HostName bitbucket.org
      User git
      PreferredAuthentications publickey
      IdentityFile ~/.ssh/work
    
  • Клонируем или добавляем в remote с использованием домена work вместо bitbucket.org. Например:
    git clone git@work:fiftin/winformspopupalerts.git
    

суббота, 17 декабря 2016 г.

Ubuntu: как перопределить кнопку на клавиатуре

Купил для работы компактную клавиатуру Logitech Keyboard K230, а у неё кнопка Enter очень неудобная — в неё хрен попадешь.


Вначале я выковырял кнопку радом с Enter'ом потому что постоянно тыкал в нее:


Стало лучше - тепепь я не втыкал / вместо Enter, но и Enter тоже. По-этому я решил поискать как переопределить кнопку на Enter. И вот что я нашел тут:
  • Устанавливать ничего не нужно.
  • В терминале запускаем утилиту xev и жмем кнопку, которую хотим переопределить. В выводе программы ищем "Keycode" и запоминаем. В моем случае это 51.
  • Выполняем в терминале следующую команду:
    xmodmap -e "keycode 51 = Return"
    
Все. Терерь по при нажатии на будет вводиться Enter. Можно её добависть в .profile чтоб выполнялась при открытии сеанса.
Список символов Xmodmap

четверг, 7 апреля 2016 г.

Где хранить видео и фотографии, если их много

Я не люблю удалять фотографии. Потому что сложно оценить насколько та или иная фотография окажется интересной через 10 лет. По-этому у меня очень много фотографий.

И я боюсь их потерять. И чем больше фотографий становится тем больше я боюсь. Я использовал платный аккаунт на Flickr, покупал пространство на Google Drive и OneDrive. И везде меня одолевала ощущение что мои фотографии может кто-то увидеть кроме меня. Почему? Да потому что Flickr создан чтобы делиться фотографиями, Google Drive и OneDrive использует общий аккаунт Google и Microsoft под которым я залогинен и на работе и на телефоне, возможно где-то еще. А я хочу чтобы мои фотографии были надежно спрятаны, как бумажные фотографии в ящике. А не чтобы они светились у меня и у того кто стоит рядом перед глазами когда я захожу в аккаунт Google или Microsoft. Я не хочу чтобы Google делал коллаж из моих фотографий. Чтобы Windows делал из них слайд шоу на начальном экране.

По-этому у меня не получалось долго хранить фотографии в облачных хранилищах. В конце концов я удалял фотографии и хранил их только у себя на компьютере.

Возможно это паранойя, но я не могу от нее избавиться.

А потом я узнал про Amazon Glacier. Я понял, это то что я так долго искал: нет web-интерфейса, нет кнопки Поделиться. Что там, чтобы скачать фото или увидеть список файлов нужно ждать 4 часа. Amazon выстроил кучу преград для использования этого сервиса обычными пользователями. Для кого-то это покажется ужасно, но для меня это было то что нужно.

И всего $0.004 за Гб. Это дешевле любого облачного хранилища которое я знаю (Google Photos и Flickr не в счет). Вы можете сказать что Google Drive стоит всего $9.99 за 1Тб, а на Glacier это будет $7, не на много дешевле (а с учётом платного трафика еще и дороже). Но если построить график, то преимущество Glacier становится более очевидным (горизонтальная шкала взята по экспоненте для наглядности).

Этот график вызывет ощущение что Google нас где-то пывается обмануть.


А этот график говорит, что если данные занимают больше 15Гб, намного выгоднее хранить их в Amazon Glacier. Если усреднить цену 1Гб для Google Drive, то получится около 4 центов за Гб против 0.7 цента на Amazon Glacier.

Итак, узнав про Amazon Glacier я начал искать программу-клиент для него, так как сервис предоставляет только API. Из существующих я нашел только Fast Glacier с ограниченной бесплатной версией. Классная программа. Но не то что мне было нужно.

Тогда я начал писать свой клиент.

Я задумывал программу которая сможет синхронизировать фотографии на различных хранилищах (я остановился на Google Drive и локальном диске) и бекапить их в Amazon Glacier.

Итак:

  • Я хотел иметь возможность выбрать интересные фотографии на диске и отправить их на Google Drive чтобы они были под рукой когда я захочу их пересмотреть или поделиться с кем-нибудь.
  • Также я хотел чтобы фотографии оставались у меня на компьютере.
  • Чтобы все это синхронизировалось с Amazon Glacier в том числе фотографии с телефона сохраненные на Google Drive.
  • И чтобы все это делалось из одной программы.

Я сделал такую программу (ну почти такую) и назвал её Oblqo. Исходники программы доступны на github.

Сейчас её использую наверное только я. По ходу использования я добавляю в нее фичи в которых у меня появляется необходимость: поддержка нескольких Google аккаунтов, сохранение уменьшенной копии фотографии и др.

Надеюсь что статья будет полезна и возможно подтолкнет кого-то к использованию Amazon Glacier который на мой взгляд необоснованно обходят стороной.

четверг, 23 июля 2015 г.

Изучаем Devise 2: Аутентификация по номеру телефна

Это не обязательно должен быть номер телефона, это может быть username или еще что-нибудь. Но в дальнейшем планируется сделать подтверждение по номеру телефона с помощью SMS, по-этому здесь выбран именно номер телефона.

1) Вначале добавим колонку phone_number в таблицу users с помощью миграции:
rails g migration AddPhoneNumberToUsers phone_number:string:uniq:index
rake db:migrate
2) Внесем следующие изменения в модель (класс User):
  • Добавим опцию authentication_keys: [:login] в вызов метода devise:
      devise :database_authenticatable, :registerable,
             :recoverable, :rememberable, :trackable,
             :validatable, :confirmable,
             authentication_keys: [:login]
  • Добавим поле login:
      def login=(login)
        @login = login
      end
    
      def login
        @login || self.phone_number || self.email
      end
    
  • Перегрузим метод отвечающий за поиск модели в базе данных:
      def self.find_for_database_authentication(warden_conditions)
        conditions = warden_conditions.dup
        if login = conditions.delete(:login)
          where(conditions.to_h).where(["lower(phone_number) = :value OR lower(email) = :value", { value: login.downcase }]).first
        else
          where(conditions.to_h).first
        end
      end
3) Добавим следующий код в контроллер ApplicationController:
  before_action :configure_permitted_parameters, if: :devise_controller?

  protected
  def configure_permitted_parameters
    devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:phone_number, :email, :password, :password_confirmation) }
    devise_parameter_sanitizer.for(:sign_in) { |u| u.permit(:login, :phone_number, :email, :password, :remember_me) }
    devise_parameter_sanitizer.for(:account_update) { |u| u.permit(:phone_number, :email, :password, :password_confirmation, :current_password) }
  end
Этот код указыает Devise какие поля формы следует сохранить в моделе. Для понимания этот код был бы аналогичен такому коду в контроллере SessionsController:
def sign_in
  permit_params = params.required(:user).permit(:phone_number,
    :email, :password, :password_confirmation)
  @user.attributes=permit_params
end
5) Далее нужно внести изменения в представления. По-умолчанию представления берутся из gem'а. Приведенная ниже команда генерирует представляения в вашем проекте. Они перегружают представления из gem'а:
rails generate devise:views
В форму регистрации (представление views/devise/registrations/new.html.erb) добавляем поле phone_number. Также вы можете добавить поле phone_number в представление редактирования данных пользователя views/devise/registrations/edit.html.erb. В форме аутентификации(представление views/devise/sessions/new.html.erb) заменяем поле email на поле login.

6) Не уверен обязательно ли это, но в config/initializers/devise.rb нужно желательно указать:
config.authentication_keys = [ :login ]
7) Перезапускаем сервер, пробуем.

воскресенье, 19 июля 2015 г.

Ruby on Rails: Настройка отправки сообщений через GMail

В конфигурационном файле config/environments/development.rb прописать следующие настройки:
  config.action_mailer.delivery_method :smtp
  config.action_mailer.smtp_settings = {
    openssl_verify_mode: 'none',
    tls: false,
    enable_starttls_auto: true,
    address: 'smtp.gmail.com',
    domain: 'gmail.com',
    port: 587,
    authentication: 'login',
    user_name: 'login@gmail.com',
    password: 'password'
  }
Перезапустить сервер. Если при попытке отправить сообщение возникнет ошибка:
Net::SMTPAuthenticationError in Devise::RegistrationsController#create
534-5.7.14 <https://accounts.google.com/ContinueSignIn?sarp=1&scc=1&plt=...
def check_auth_response(res)
  unless res.success?
    raise SMTPAuthenticationError, res.message
  end
end
то необходимо изменить натройки безопасности аккаунта гугл. Как, написано здесь.

HTML: Перенос длинных слов

Оригинальный текст можно прочесть здесь.
Я нагуглил следующие способы решения проблемы с длинными словами, которые ломают верстку:
1) http://slopjong.de/2013/06/18/how-to-word-wrap-text-in-html/
div { 
    white-space: pre-wrap;      /* CSS3 */
    white-space: -moz-pre-wrap; /* Firefox */
    white-space: -pre-wrap;
    word-wrap: break-word; 
}
2) Использовать специальные символы для разделения длинных слов на более короткие. Вот эти символы: &shy; &#8203; <wbr>
Пример спользования в Ruby on Rails https://gist.github.com/fiftin/004b70ac0fc0a72738f8.
Каждый из этих сиволов имеет свои недостатки:
  • &#8203;  - представляют собой невидимый пробел который разделяет слово на отдельные слова. По-этому при двойном щелчке мыши по слову, выделяется не полностью слово, а только его часть
  • &shy; &#8203; - копируются вместе с тектом хоть и невидимы для пользователя. Проблема может возникнуть, если пользовтель пытается использовать скопированный текст (содержащий один из этих символов) для поиска.
  • <wbr> - не имеет описанных выше недостатков, но он не поддерживается Internet Explorer'ом.
3) Если ширина div'ки с тектом фиксирована, то достаточно использовать для нее такой стиль:
div {
    width: 100px;
    word-wrap: break-word;
}