Skip to content

Instantly share code, notes, and snippets.

@Andrew8xx8
Last active December 13, 2015 21:18
Show Gist options
  • Select an option

  • Save Andrew8xx8/4976405 to your computer and use it in GitHub Desktop.

Select an option

Save Andrew8xx8/4976405 to your computer and use it in GitHub Desktop.
Rails Tips. Конспект по Rails Guides (3.2.12))

Конспект только нужного с Rails Guides (3.2.12)

Перед прочтением ознакомится с оригиналом

Миграции

Методы для изменения

  • add_column
  • add_index
  • change_column
  • change_table
  • create_table
  • create_join_table Rails 4
  • drop_table
  • remove_column
  • remove_index
  • rename_column

Типы данных

  • :binary
  • :boolean
  • :date
  • :datetime
  • :decimal
  • :float
  • :integer
  • :primary_key
  • :string
  • :text
  • :time
  • :timestamp

Автоматическое создание миграций

$ rails generate migration RemovePartNumberFromProducts part_number:string

class RemovePartNumberFromProducts < ActiveRecord::Migration
  def up
    remove_column :products, :part_number
  end
 
  def down
    add_column :products, :part_number, :string
  end
end

$ rails generate migration AddPartNumberToProducts part_number:string

class AddPartNumberToProducts < ActiveRecord::Migration
  def change
    add_column :products, :part_number, :string
  end
end

Запуск

Конкретная редакция: $ rake db:migrate:up VERSION=20080906120000

Откат трёх миграций: $ rake db:rollback STEP=3

Active Record

new_record? - Новая запись или нет

Методы сохраняющие объект без валидации

  • decrement!
  • decrement_counter
  • increment!
  • increment_counter
  • toggle!
  • touch
  • update_all
  • update_attribute
  • update_column
  • update_counters
  • save(:validate => false)

Волшебный чекбокс типа 'Я согласен с правилами сайта', не сохраняется в базу

class Person < ActiveRecord::Base
  validates :terms_of_service, :acceptance => true`

  # Или так

  validates :licence_agreement, :acceptance => { :accept => 'yes' }`
end

Валидация связанных сущностей

class Library < ActiveRecord::Base
  has_many :books
  validates_associated :books
end

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

confirmation - ЗЛО, использовать Types

presence

class Person < ActiveRecord::Base
  validates :name, :login, :email, :presence => true

  # Связь с ордером существует и order_id не пустой
  belongs_to :order
  validates :order_id, :presence => true

  # Конкретный ордер переданный в order_id существует в базе, *не работает с has_one*
  belongs_to :order
  validates :order, :presence => true

  # Исключение. Валидация булева поля
  validates :field_name, :inclusion => { :in => [true, false] }.
end

length

class Person < ActiveRecord::Base
  validates :name, :length => { :minimum => 2 }
  validates :bio, :length => { :maximum => 500 }
  validates :password, :length => { :in => 6..20 }
  validates :registration_number, :length => { :is => 6 }
end

uniqueness

class Account < ActiveRecord::Base
  validates :email, :uniqueness => true
  validates :name, :uniqueness => { :scope => :year,
    :message => "should happen once per year" }
  validates :second_name, :uniqueness => { :case_sensitive => false }
end

Опции валидаторов

  • :allow_nil - Разрешить нил
  • :allow_blank - Разрешить пустое значение
  • :on - Выполнить валидацию только на определённое действие. ЗЛО, Изспользовать Types
  • :message - Специфическое сообщение при фейле. ЗЛО, использовать i18n

Условная валидация - ЗЛО, использовать Types

Собственные валидаторы

class EmailValidator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
    unless value =~ /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i
      record.errors[attribute] << (options[:message] || "is not an email")
    end
  end
end
 
class Person < ActiveRecord::Base
  validates :email, :presence => true, :email => true
end
class Invoice < ActiveRecord::Base
  validate :expiration_date_cannot_be_in_the_past,
    :discount_cannot_be_greater_than_total_value
 
  def expiration_date_cannot_be_in_the_past
    errors.add(:expiration_date, "can't be in the past") if
      !expiration_date.blank? and expiration_date < Date.today
  end
 
  def discount_cannot_be_greater_than_total_value
    errors.add(:discount, "can't be greater than total value") if
      discount > total_value
  end
end

Доступные колбэки в порядке вызова

Создание объекта

  • before_validation
  • after_validation
  • before_save
  • around_save
  • before_create
  • around_create
  • after_create
  • after_save

Обновление объекта

  • before_validation
  • after_validation
  • before_save
  • around_save
  • before_update
  • around_update
  • after_update
  • after_save

Уничтожение объекта

  • before_destroy
  • around_destroy
  • after_destroy

Методы пропускающие колбеки

  • decrement
  • decrement_counter
  • delete
  • delete_all
  • increment
  • increment_counter
  • toggle
  • touch
  • update_column
  • update_all
  • update_counters

Колбеки только в обсерверы

class MailerObserver < ActiveRecord::Observer
  observe :registration, :user
 
  def after_create(model)
    # code to send confirmation email...
  end
end
# Activate observers that should always be running.
config.active_record.observers = :mailer_observer

Выключить обсервер в тестах

  ActiveRecord::Base.observers.disable :all

Транзакционный колбек

class PictureFile < ActiveRecord::Base
  attr_accessor :delete_file
 
  after_destroy do |picture_file|
    picture_file.delete_file = picture_file.filepath
  end
 
  after_commit do |picture_file|
    if picture_file.delete_file && File.exist?(picture_file.delete_file)
      File.delete(picture_file.delete_file)
      picture_file.delete_file = nil
    end
  end
end

AR Relations

  • belongs_to
  • has_one
  • has_many
  • has_many :through
  • has_one :through
  • has_and_belongs_to_many

Полиморфная связь

class Picture < ActiveRecord::Base
  belongs_to :imageable, :polymorphic => true
end
 
class Employee < ActiveRecord::Base
  has_many :pictures, :as => :imageable
end
 
class Product < ActiveRecord::Base
  has_many :pictures, :as => :imageable
end

Связь сама на себя

class Employee < ActiveRecord::Base
  has_many :subordinates, :class_name => "Employee",
    :foreign_key => "manager_id"
  belongs_to :manager, :class_name => "Employee"
end

Колбеки связи

before_add
after_add
before_remove
after_remove

Локали

# В роутинг
scope "(:locale)", :locale => /ru|en|fr|jp/ do

# Локаль устанавливается
def set_locale
  I18n.locale= params[:locale] || I18n.default_locale
  default_url_options[:locale] = params[:locale]
end

# В конфиг
config.i18n.available_locales = [:en, :ru]
config.i18n.default_locale = :en
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment