• Как в одной таблице сделать два внешних ключа?

    c3gdlk
    @c3gdlk
    Ментор в http://rubyboost.ru/
    Примеры к ответу nbekseitov
    Полиморфная связь
    class Buyer < User
    end
    
    class Seller < User
    end
    
    class Order
      belongs_to :buyer
      belongs_to :seller
    end


    Внешний ключ
    class Order
      belongs_to :buyer, foreign_key: :buyer_id, class_name: User
      belongs_to :seller, foreign_key: :seller_id, class_name: User
    end


    Сложно сказать какой вариант правильный, зависит от задачи и структуры проекта. Второй вариант намного проще и довольно часто его достаточно. В первом варианте Вы с самого начала будете явно разделять логику продавца и покупателя между двумя классами, что положительно скажется на качестве кода в дальнейшем.
    Ответ написан
    Комментировать
  • Правильно ли сделано кэширование?

    c3gdlk
    @c3gdlk
    Ментор в http://rubyboost.ru/
    Функция cache может принимать или уже готовый ключ для хранения, или, как в Вашем случае, экземпляр модели. В этом случае ключ будет построен из id и updated_at, поэтому updated_at должен быть во всех моделях.

    Еще в Вашем коде
    - menu = render_menu(code)

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

    Проще всего посмотреть логи консоли, в случае с кеширование рельса пишет какие фрагменты использует
    Ответ написан
  • Как организовать синхронизацию данных БД между разработчиками в период разработки?

    c3gdlk
    @c3gdlk
    Ментор в http://rubyboost.ru/
    Для наполнения базы тестовыми данными в рельсе используются сиды. Только их код пишется так, чтобы не просто пытались засунуть данные в базу, а перед этим поискать аналогичные. Если данные слишком сложные - те же сиды, но сами значения хранятся в YML файлах в какой-нибудь папке db/fixtures.

    Если и этого не хватает - можно посмотреть в сторону https://github.com/harrystech/seed_migration

    Еще можно писать rake таски типа db:populate:feature_name - такой подход позволит наполнять базу только нужными данными. Ну и соответсвенно будет один общий таск, который прогонит все populate
    Ответ написан
    Комментировать
  • Как в Ruby on Rails подключиться к шрифту создав папку fonts?

    c3gdlk
    @c3gdlk
    Ментор в http://rubyboost.ru/
    Ответ, который Вы отметили не совсем верный. При деплое на сервер происходит генерация ассетов с дайджетами.

    Правильно:
    src: font-url(rouble.ttf);
    Ответ написан
    Комментировать
  • Ruby and Rail связать две таблицы?

    c3gdlk
    @c3gdlk
    Ментор в http://rubyboost.ru/
    согласно конвенции rails не может быть таблички с именем posts_category

    может быть post_categories - когда у одной категории много постов, связь 1 ко многим и могут быть таблицы categories и posts_categories - связь многие ко многим

    Т.е в вашем случае скорее всего должна быть табличка post_categories и везде belongs_to :post_category
    Ответ написан
    Комментировать
  • Как отрендерить метод со статусом?

    c3gdlk
    @c3gdlk
    Ментор в http://rubyboost.ru/
    Мы обычно примерно так делаем. Добавляем методы в базовый контроллер

    def respond_with_400(exception)
        render json: { success: false, all_errors: ['The user has not authorized application'] }, status: 400
      end
    
      def respond_with_404(exception=nil)
        render json: { success: false, all_errors: [t('errors.not_found')] }, status: 404
      end
    
      def respond_with_500(exception)
        render json: {success: false, all_errors: [t('errors.something_went_wrong')], debug: exception.to_s}, status: 500
      end
    
      def respond_with_success(resource=nil, status=200)
        result = {success: true}
        result.merge!(:"#{resource.class.name.underscore}" => {id: resource.id}) if resource.present?
    
        render json: result, status: status
      end
    
      def respond_with_errors(resource=nil, status=422, debug=nil)
        result = {success: false}
    
        result.merge!(errors: resource.errors.messages, all_errors: resource.errors.full_messages)  if resource.present?
        result.merge!(debug: debug) if debug.present?
    
        render json: result, status: status
      end
    Ответ написан
    Комментировать
  • Как вывести в теме и теле письма данные из переменной?

    c3gdlk
    @c3gdlk
    Ментор в http://rubyboost.ru/
    Там где шаблон письма из базы подставляется в тело письма нужно использовать ERB процессор при этом передав в него текущий контекст(binding)

    @tmp = 'Some value'
    email_body = ERB.new(mail_template_from_database).result(binding)
    
    mail(to: user_email,  body: email_body,   content_type: "text/html",   subject: "Email subject")
    Ответ написан
  • Возможно ли изучение Рельсов, без знаний Ruby?

    c3gdlk
    @c3gdlk
    Ментор в http://rubyboost.ru/
    В компании в которой я работаю еще 17 рельсовиков и все начинали именно с рейлс. Руби прекрасный язык, но в нем нет ничего сверхъестественного. Достаточно знать основы ООП и иметь неплохой опыт в любом другом интерпретируемом языке.

    Мой более подробный ответ к такому же вопросу Что нужно знать прежде чем учить ROR?
    Ответ написан
    Комментировать
  • Более правильный способ обработки не найденной сущности?

    c3gdlk
    @c3gdlk
    Ментор в http://rubyboost.ru/
    Всегда должен быть find. А ошибка отлавливается в ApplicationController

    unless Rails.application.config.consider_all_requests_local
        rescue_from Exception, with: :respond_with_500
    
        rescue_from ActiveRecord::RecordNotFound,
                    ActionController::RoutingError,
                    ActiveRecord::RecordInvalid,
                    with: :respond_with_404
    
        rescue_from ActionController::BadRequest, with: :respond_with_400
      end
    
    def respond_with_404(exception=nil)
        redirect_to root_path
      end
    Ответ написан
    5 комментариев
  • Как правильно организовать права доступа rails?

    c3gdlk
    @c3gdlk
    Ментор в http://rubyboost.ru/
    В user_roles добавить связь к компании company_id

    В cancancan проверять доступ по конкретной компании. Чтобы передать компанию в ability из контроллера - нужно переопределить метод current_ability насколько я помню.
    Ответ написан
    Комментировать
  • Как правильно организовать nested form'у для трех моделей?

    c3gdlk
    @c3gdlk
    Ментор в http://rubyboost.ru/
    Чтобы вывести только позиции компании нужно их явно задать в контроллере

    @user.positions = @company.positions.where(user: @user)


    Но, я не думаю, что это будет работать, потому что сохранение скорее всего сотрет позиции других компаний.

    В этом случае проще написать эту логику явно
    Ответ написан
  • Что нужно знать прежде чем учить ROR?

    c3gdlk
    @c3gdlk
    Ментор в http://rubyboost.ru/
    По поводу того, что нужно знать из основ - полностью согласен с Денисом

    Хотел бы добавить свои мысли по поводу пути изучения RoR

    Довольно часто возникает вопрос в том, какую технологию стоит изучать. Обычно выбор стоит между Ruby on Rails, Python + Django и Node.js. Я считаю, что программист не должен замыкаться на одной технологии. Он должен иметь представление о смежных/новых технолоигях, и уметь, при необходимости, довольно быстро переключится на новый инструмент.

    RoR считаю идеальным в плане начала обучения, потому что рельсы, по сути, являются аккумуляцией многолетнего опыта в веб разработке, и понимание их подхода позволит легко и эффективно изучать и использовать другие технологии.

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

    Лучшим путем будет практика в какой-либо конторе, с решением реальных задач. Но, тут проблема вот в чем - обычно новичек примерно 3-5 месяцев практикуется на несложных проектах, и это, на мой взгляд довольно медленно.

    Идеальным, на мой взгляд, является практика в небольшой команде. Я так начинал, у меня был очень опытный наставник, проекты заходили намного сложнее, чем я мог потянуть и мне приходилось очень быстро учиться, с чем очень хорошо помогает опытный наставник. Альтернативой может послужить практика падаваном у упытного программиста, но тут главное не упустить тот момент, когда ты уже месяц решаешь знакомые тебе задачи и не продвигаешься вперед.

    Альтернативой может послужить прохождение курсов. Я знаком с материалами курсов rubybursa.com и ror.thinknetica.com, но они не показались мне интересными. Довольно интересными выглядят https://mkdev.me/. Не знаком с материалом (их нет на торрентах=)), но блог Кирила очень интересен, и я думаю, что курсы, скорее всего, тоже на уровне, тем более там несколько курсов для различного уровня подготовки.

    Я также планирую запустить свой курс. Он будет направлен на то, чтобы достаточно быстро (примерно месяц обучения) получить практические знания, которые помогут за месяц пройти этап неинтересных проетов и попасть в разработку серьезных приложений с сильным руководителем. Если интересно - подписывайтесь на твиттер, там будут обновления. https://twitter.com/c3gdlk

    P.S. Для начала ruby учить не надо. Основы учатся за пол часа learnxinyminutes.com/docs/ruby - остальное изучается через практику.

    Самым важным пожалуй является понимание того, что такое блоки и как их использовать и осознание того, что методы класса могут быть вызваны сразу же после их описание. Т.е. все эти немного не привычные scopes, validates, has_one и belongs_to - не что иное, как вызов методов класса, которые в этот самый класс добавляют какие-то данные.
    Ответ написан
    Комментировать
  • Как сделать аутентификацию через одноклассники на Angularjs?

    c3gdlk
    @c3gdlk
    Ментор в http://rubyboost.ru/
    Мы делали на Ember.js, но смысл тот же - фреймворк можно вообще не использовать.

    https://github.com/incubus/omniauth-odnoklassniki - ставим себе гем для айтентификации.

    По нажатию на кнопку - открываем новое окно с адресом аутентефикации

    Пример кода на Ember.js но смысл должен быть понятен
    SomeApp.SocialLoginButtonView = Ember.View.extend(
      tagName: "a"
      attributeBindings: ['href']
    
      click: (e)->
        e.preventDefault()
        provider  = $(e.currentTarget).attr('href')
    
        url = "/users/auth/#{provider}?transition_to_root=true"
        window.open(
          url, '_blank',
          'width=600,height=500,location=yes,resizable=yes,scrollbars=yes'
        )
    )


    Пример контроллера

    class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
    
      layout 'blank'
    
      def facebook
        sign_in_with_oauth_data(request.env['omniauth.auth'])
      end
    
      def twitter
        sign_in_with_oauth_data(request.env['omniauth.auth'])
      end
    
      private
    
      def sign_in_with_oauth_data(oauth_data)
        unless user_signed_in?
          user =  User.find_or_create_with_oauth(oauth_data)
          sign_in :user, user
          MailWorker.perform_in(1.hour, user.id, :account_dropoff)
        end
    
        @success = current_user.register_social_profile(normalize_oauth_data(oauth_data))
        @service_name = oauth_data.provider
    
        render 'shared/social_authentication'
      end
    
      def normalize_oauth_data(oauth_data)
        { service_name: oauth_data.provider, uid: oauth_data.uid, access_token: oauth_data.credentials.token, secret_key: oauth_data.credentials.secret }
      end
    end


    Контроллер рендерит представление - javascript, который отправляет данные родительскому окну и закрывает окно авторизации

    <script type="text/javascript" charset="UTF-8">
      <% if @success %>
          window.opener.SomeApp.sendSuccess()
      <% else %>
        window.opener.SomeApp.sendFailure()
      <% end %>
    
      window.close();
    </script>
    Ответ написан
    1 комментарий
  • Почему объект не сохраняется при выполении отложенного метода через Sidekiq?

    c3gdlk
    @c3gdlk
    Ментор в http://rubyboost.ru/
    Странно, что воркер не вылетает с ошибкой, потому что для вызова воркера после сохранения нужно использовать after_commit а не after_create. В момент, когда вызывается after_create транзакция еще не закончилась и id доступен только в модели.
    Ответ написан
    3 комментария