Modelのvalidatesメソッドについて
なんかrails難しいな。よくわからず使いたくない笑
Rubyを知る為にRailsのコード読む。
class Member < ActiveRecord::Base validates :email, presence: true end
ModelはまずActiveRecordモジュールのBaseクラスをを継承している
/ruby/2.1.0/gems/activerecord-4.0.2/lib/active_record/base.rb
module ActiveRecord #:nodoc: class Base extend ActiveModel::Naming ・ ・ ・ include Sanitization include AttributeAssignment include ActiveModel::Conversion include Integration include Validations include CounterCache ・ ・ end ActiveSupport.run_load_hooks(:active_record, Base) end
その中でActiveRecord::Validations をinclude
/ruby/2.1.0/gems/activerecord-4.0.2/lib/active_record/validations.rb
module ActiveRecord # = Active Record RecordInvalid # # Raised by <tt>save!</tt> and <tt>create!</tt> when the record is invalid. Use the # +record+ method to retrieve the record which did not validate. # # begin # complex_operation_that_calls_save!_internally # rescue ActiveRecord::RecordInvalid => invalid # puts invalid.record.errors # end class RecordInvalid < ActiveRecordError attr_reader :record # :nodoc: def initialize(record) # :nodoc: @record = record errors = @record.errors.full_messages.join(", ") super(I18n.t(:"#{@record.class.i18n_scope}.errors.messages.record_invalid", :errors => errors, :default => :"errors.messages.record_invalid")) end end # = Active Record Validations # # Active Record includes the majority of its validations from <tt>ActiveModel::Validations</tt> # all of which accept the <tt>:on</tt> argument to define the context where the # validations are active. Active Record will always supply either the context of # <tt>:create</tt> or <tt>:update</tt> dependent on whether the model is a # <tt>new_record?</tt>. module Validations extend ActiveSupport::Concern include ActiveModel::Validations module ClassMethods # Creates an object just like Base.create but calls <tt>save!</tt> instead of +save+ # so an exception is raised if the record is invalid. def create!(attributes = nil, &block) if attributes.is_a?(Array) attributes.collect { |attr| create!(attr, &block) } else object = new(attributes) yield(object) if block_given? object.save! object end end end # The validation process on save can be skipped by passing <tt>validate: false</tt>. # The regular Base#save method is replaced with this when the validations # module is mixed in, which it is by default. def save(options={}) perform_validations(options) ? super : false end # Attempts to save the record just like Base#save but will raise a +RecordInvalid+ # exception instead of returning +false+ if the record is not valid. def save!(options={}) perform_validations(options) ? super : raise(RecordInvalid.new(self)) end # Runs all the validations within the specified context. Returns +true+ if # no errors are found, +false+ otherwise. # # If the argument is +false+ (default is +nil+), the context is set to <tt>:create</tt> if # <tt>new_record?</tt> is +true+, and to <tt>:update</tt> if it is not. # # Validations with no <tt>:on</tt> option will run no matter the context. Validations with # some <tt>:on</tt> option will only run in the specified context. def valid?(context = nil) context ||= (new_record? ? :create : :update) output = super(context) errors.empty? && output end protected def perform_validations(options={}) # :nodoc: options[:validate] == false || valid?(options[:context]) end end end require "active_record/validations/associated" require "active_record/validations/uniqueness" require "active_record/validations/presence"
include ActiveModel::Validations
さらにActiveModel::Validationsをincludeしてる
/gems/activemodel-4.0.2/lib/active_model/validations.rb
require 'active_support/core_ext/array/extract_options' require 'active_support/core_ext/hash/keys' require 'active_support/core_ext/hash/except' module ActiveModel # == Active \Model Validations # # Provides a full validation framework to your objects. # # A minimal implementation could be: # # class Person # include ActiveModel::Validations # # attr_accessor :first_name, :last_name # # validates_each :first_name, :last_name do |record, attr, value| # record.errors.add attr, 'starts with z.' if value.to_s[0] == ?z # end # end # # Which provides you with the full standard validation stack that you # know from Active Record: # # person = Person.new # person.valid? # => true # person.invalid? # => false # # person.first_name = 'zoolander' # person.valid? # => false # person.invalid? # => true # person.errors.messages # => {first_name:["starts with z."]} # # Note that <tt>ActiveModel::Validations</tt> automatically adds an +errors+ # method to your instances initialized with a new <tt>ActiveModel::Errors</tt> # object, so there is no need for you to do this manually. module Validations extend ActiveSupport::Concern included do extend ActiveModel::Callbacks extend ActiveModel::Translation extend HelperMethods include HelperMethods attr_accessor :validation_context define_callbacks :validate, :scope => :name class_attribute :_validators self._validators = Hash.new { |h,k| h[k] = [] } end module ClassMethods # Validates each attribute against a block. # # class Person # include ActiveModel::Validations # # attr_accessor :first_name, :last_name # # validates_each :first_name, :last_name, allow_blank: true do |record, attr, value| # record.errors.add attr, 'starts with z.' if value.to_s[0] == ?z # end # end # # Options: # * <tt>:on</tt> - Specifies the context where this validation is active # (e.g. <tt>on: :create</tt> or <tt>on: :custom_validation_context</tt>) # * <tt>:allow_nil</tt> - Skip validation if attribute is +nil+. # * <tt>:allow_blank</tt> - Skip validation if attribute is blank. # * <tt>:if</tt> - Specifies a method, proc or string to call to determine # if the validation should occur (e.g. <tt>if: :allow_validation</tt>, # or <tt>if: Proc.new { |user| user.signup_step > 2 }</tt>). The method, # proc or string should return or evaluate to a +true+ or +false+ value. # * <tt>:unless</tt> - Specifies a method, proc or string to call to # determine if the validation should not occur (e.g. <tt>unless: :skip_validation</tt>, # or <tt>unless: Proc.new { |user| user.signup_step <= 2 }</tt>). The # method, proc or string should return or evaluate to a +true+ or +false+ # value. def validates_each(*attr_names, &block) validates_with BlockValidator, _merge_attributes(attr_names), &block end # Adds a validation method or block to the class. This is useful when # overriding the +validate+ instance method becomes too unwieldy and # you're looking for more descriptive declaration of your validations. # # This can be done with a symbol pointing to a method: # # class Comment # include ActiveModel::Validations # # validate :must_be_friends # # def must_be_friends # errors.add(:base, 'Must be friends to leave a comment') unless commenter.friend_of?(commentee) # end # end # # With a block which is passed with the current record to be validated: # # class Comment # include ActiveModel::Validations # # validate do |comment| # comment.must_be_friends # end # # def must_be_friends # errors.add(:base, 'Must be friends to leave a comment') unless commenter.friend_of?(commentee) # end # end # # Or with a block where self points to the current record to be validated: # # class Comment # include ActiveModel::Validations # # validate do # errors.add(:base, 'Must be friends to leave a comment') unless commenter.friend_of?(commentee) # end # end # # Options: # * <tt>:on</tt> - Specifies the context where this validation is active # (e.g. <tt>on: :create</tt> or <tt>on: :custom_validation_context</tt>) # * <tt>:allow_nil</tt> - Skip validation if attribute is +nil+. # * <tt>:allow_blank</tt> - Skip validation if attribute is blank. # * <tt>:if</tt> - Specifies a method, proc or string to call to determine # if the validation should occur (e.g. <tt>if: :allow_validation</tt>, # or <tt>if: Proc.new { |user| user.signup_step > 2 }</tt>). The method, # proc or string should return or evaluate to a +true+ or +false+ value. # * <tt>:unless</tt> - Specifies a method, proc or string to call to # determine if the validation should not occur (e.g. <tt>unless: :skip_validation</tt>, # or <tt>unless: Proc.new { |user| user.signup_step <= 2 }</tt>). The # method, proc or string should return or evaluate to a +true+ or +false+ # value. def validate(*args, &block) options = args.extract_options! if options.key?(:on) options = options.dup options[:if] = Array(options[:if]) options[:if].unshift("validation_context == :#{options[:on]}") end args << options set_callback(:validate, *args, &block) end # List all validators that are being used to validate the model using # +validates_with+ method. # # class Person # include ActiveModel::Validations # # validates_with MyValidator # validates_with OtherValidator, on: :create # validates_with StrictValidator, strict: true # end # # Person.validators # # => [ # # #<MyValidator:0x007fbff403e808 @options={}>, # # #<OtherValidator:0x007fbff403d930 @options={on: :create}>, # # #<StrictValidator:0x007fbff3204a30 @options={strict:true}> # # ] def validators _validators.values.flatten.uniq end # Clears all of the validators and validations. # # Note that this will clear anything that is being used to validate # the model for both the +validates_with+ and +validate+ methods. # It clears the validators that are created with an invocation of # +validates_with+ and the callbacks that are set by an invocation # of +validate+. # # class Person # include ActiveModel::Validations # # validates_with MyValidator # validates_with OtherValidator, on: :create # validates_with StrictValidator, strict: true # validate :cannot_be_robot # # def cannot_be_robot # errors.add(:base, 'A person cannot be a robot') if person_is_robot # end # end # # Person.validators # # => [ # # #<MyValidator:0x007fbff403e808 @options={}>, # # #<OtherValidator:0x007fbff403d930 @options={on: :create}>, # # #<StrictValidator:0x007fbff3204a30 @options={strict:true}> # # ] # # If one runs Person.clear_validators! and then checks to see what # validators this class has, you would obtain: # # Person.validators # => [] # # Also, the callback set by +validate :cannot_be_robot+ will be erased # so that: # # Person._validate_callbacks.empty? # => true # def clear_validators! reset_callbacks(:validate) _validators.clear end # List all validators that are being used to validate a specific attribute. # # class Person # include ActiveModel::Validations # # attr_accessor :name , :age # # validates_presence_of :name # validates_inclusion_of :age, in: 0..99 # end # # Person.validators_on(:name) # # => [ # # #<ActiveModel::Validations::PresenceValidator:0x007fe604914e60 @attributes=[:name], @options={}>, # # #<ActiveModel::Validations::InclusionValidator:0x007fe603bb8780 @attributes=[:age], @options={in:0..99}> # # ] def validators_on(*attributes) attributes.flat_map do |attribute| _validators[attribute.to_sym] end end # Returns +true+ if +attribute+ is an attribute method, +false+ otherwise. # # class Person # include ActiveModel::Validations # # attr_accessor :name # end # # User.attribute_method?(:name) # => true # User.attribute_method?(:age) # => false def attribute_method?(attribute) method_defined?(attribute) end # Copy validators on inheritance. def inherited(base) #:nodoc: dup = _validators.dup base._validators = dup.each { |k, v| dup[k] = v.dup } super end end # Clean the +Errors+ object if instance is duped. def initialize_dup(other) #:nodoc: @errors = nil super end # Returns the +Errors+ object that holds all information about attribute # error messages. # # class Person # include ActiveModel::Validations # # attr_accessor :name # validates_presence_of :name # end # # person = Person.new # person.valid? # => false # person.errors # => #<ActiveModel::Errors:0x007fe603816640 @messages={name:["can't be blank"]}> def errors @errors ||= Errors.new(self) end # Runs all the specified validations and returns +true+ if no errors were # added otherwise +false+. # # class Person # include ActiveModel::Validations # # attr_accessor :name # validates_presence_of :name # end # # person = Person.new # person.name = '' # person.valid? # => false # person.name = 'david' # person.valid? # => true # # Context can optionally be supplied to define which callbacks to test # against (the context is defined on the validations using <tt>:on</tt>). # # class Person # include ActiveModel::Validations # # attr_accessor :name # validates_presence_of :name, on: :new # end # # person = Person.new # person.valid? # => true # person.valid?(:new) # => false def valid?(context = nil) current_context, self.validation_context = validation_context, context errors.clear run_validations! ensure self.validation_context = current_context end # Performs the opposite of <tt>valid?</tt>. Returns +true+ if errors were # added, +false+ otherwise. # # class Person # include ActiveModel::Validations # # attr_accessor :name # validates_presence_of :name # end # # person = Person.new # person.name = '' # person.invalid? # => true # person.name = 'david' # person.invalid? # => false # # Context can optionally be supplied to define which callbacks to test # against (the context is defined on the validations using <tt>:on</tt>). # # class Person # include ActiveModel::Validations # # attr_accessor :name # validates_presence_of :name, on: :new # end # # person = Person.new # person.invalid? # => false # person.invalid?(:new) # => true def invalid?(context = nil) !valid?(context) end # Hook method defining how an attribute value should be retrieved. By default # this is assumed to be an instance named after the attribute. Override this # method in subclasses should you need to retrieve the value for a given # attribute differently: # # class MyClass # include ActiveModel::Validations # # def initialize(data = {}) # @data = data # end # # def read_attribute_for_validation(key) # @data[key] # end # end alias :read_attribute_for_validation :send protected def run_validations! #:nodoc: run_callbacks :validate errors.empty? end end end Dir[File.dirname(__FILE__) + "/validations/*.rb"].each { |file| require file } <|| Dir[File.dirname(__FILE__) + "/validations/*.rb"].each { |file| require file } 同じ階層のvalidationsディレクトリーのなかのrbファイルをrequireしてる! あったvalidates.rb! /gems/activemodel-4.0.2/lib/active_model/validations/validates.rb >|ruby| require 'active_support/core_ext/hash/slice' module ActiveRecord module Validations module ClassMethods ・ ・ ・ class RecordInvalid < ActiveRecordError ・ ・ ・ def validates(*attributes) defaults = attributes.extract_options!.dup validations = defaults.slice!(*_validates_default_keys) raise ArgumentError, "You need to supply at least one attribute" if attributes.empty? raise ArgumentError, "You need to supply at least one validation" if validations.empty? defaults[:attributes] = attributes validations.each do |key, options| next unless options key = "#{key.to_s.camelize}Validator" begin validator = key.include?('::') ? key.constantize : const_get(key) rescue NameError raise ArgumentError, "Unknown validator: '#{key}'" end validates_with(validator, defaults.merge(_parse_validates_options(options))) end end ・ ・ ・ protected # When creating custom validators, it might be useful to be able to specify # additional default keys. This can be done by overwriting this method. def _validates_default_keys # :nodoc: [:if, :unless, :on, :allow_blank, :allow_nil , :strict] end def _parse_validates_options(options) # :nodoc: case options when TrueClass {} when Hash options when Range, Array { :in => options } else { :with => options } end end end end end
あったあったvalidates
def validates(*attributes) defaults = attributes.extract_options!.dup validations = defaults.slice!(*_validates_default_keys) raise ArgumentError, "You need to supply at least one attribute" if attributes.empty? raise ArgumentError, "You need to supply at least one validation" if validations.empty? defaults[:attributes] = attributes validations.each do |key, options| next unless options key = "#{key.to_s.camelize}Validator" begin validator = key.include?('::') ? key.constantize : const_get(key) rescue NameError raise ArgumentError, "Unknown validator: '#{key}'" end validates_with(validator, defaults.merge(_parse_validates_options(options))) end end protected # When creating custom validators, it might be useful to be able to specify # additional default keys. This can be done by overwriting this method. def _validates_default_keys # :nodoc: [:if, :unless, :on, :allow_blank, :allow_nil , :strict] end def _parse_validates_options(options) # :nodoc: case options when TrueClass {} when Hash options when Range, Array { :in => options } else { :with => options } end end
Valitionモジュールのこのコード
①
defaults = attributes.extract_options!.dup
で
作成したvalidates
validates :email, presence: true
の
presence: true
これを複製
②
これで
validations = defaults.slice!(*_validates_default_keys)
よくわからないけど以下のオプションをスライス
[:if, :unless, :on, :allow_blank, :allow_nil , :strict]
③ ①で複製した配列をループ。クラスを取得して、validate_withに渡す
※ next unless options → optionがtrueの場合処理へ進む
※to_s→配列を文字列に
※camelize → Camel方に直す
※constantize/const_get → モジュール、クラスの取得
※merge→ハッシュの統合
validations.each do |key, options| next unless options key = "#{key.to_s.camelize}Validator" begin validator = key.include?('::') ? key.constantize : const_get(key) rescue NameError raise ArgumentError, "Unknown validator: '#{key}'" end validates_with(validator, defaults.merge(_parse_validates_options(options))) end
あー、仕事行かなきゃ、validate_withについては今日中に。
ということで今日はまだ終わっていない。
validates_with
同じ階層にwith.rbってある。
/gems/activemodel-4.0.2/lib/active_model/validations/with.rb
と思ったけどわからないまた今度。
今日思った事。
遠回りしてるけど、コレが自分のやり方です。
Ruby Rails勉強会
試しに自分で開催してみよう。
初心者中心の会になると思います。
自分も初心者なので。。。
もちろん経験者大歓迎です!!
Railsのvalidationメッセージを日本語化する。
デフォルトのエラーメッセージが英語。。
一回一回メッセージをカスタマイズするのめんどくさい。
色々調べてたら日本語かできそう。
http://guides.rubyonrails.org/i18n.html
kurodaさんがgitにあげてくれているファイルをコピペ
https://github.com/svenfuchs/rails-i18n/blob/master/rails/locale/ja.yml
以下の階層にja.ymlを置く。
|-アプリケーション |-config |-locales |-ja.yml
application.rbに以下の一行を追加
config.i18n.default_locale = :ja
|-アプリケーション |-config |-locales |-application.rb
サーバー再起動
成功!
rails登録フォーム作成
1.スケルトン作成
- スケルトン作成
$ rails new test_apl -d postgresql
フォルダ構成 [test_app] ├ [app] →アプリ本体 ├ [bin] →rails,rakeコマンド ├ [config] →設定用ファイル ├ [lib] →ライブラリ └ [log] →ログ └ [public] →Webroot └ [test] └ [tmp] └ [vender] →gemファイル
2.登録フォーム作成
- scaffoldでひな形作成
rails generate scaffold members lastname:string firstname:string sex:integer
→model,controller,viewにファイルが追加される
rake db:migrate
→membersテーブルと指定したカラムが追加される
rails server
→Webrick起動
※別にコレじゃなくてもいい。
http://ホスト:3000/member
にアクセスすると
が表示される。
この画面から新規登録、編集、削除、表示の一通り動作する
アプリができる。
*1:dbがpostgresqlのrailsスケルトン作成
Rails Guides Active Record Migrations
http://guides.rubyonrails.org/migrations.html
これ日本語に訳してみました。
最後の方よくわからなかった。
ちょっと動かしてもう一回書き直します。
Active Record Migrations
Active Recordの特徴の一つであるMigrationsによって、
瞬時にデータベースのスキーマを展開する事ができます。
純粋なSQLでスキーマに変更を加えるのではなく、
簡単なRuby DSLでテーブルに変更を加える事ができるのがMigrationsの特徴。
このガイドで、次の知識をえることができます。
・migrationsを作成する為のgenetators
・データベースを簡単に操作する為のActive Recordのmethodについて
・migrationsとスキーマを操作する為のrakeの動作
・migrationsとschema.rbの関係
1、Migrations概要
Migrationsによって、便利で簡単に、矛盾なくデーターベーススキーマに変更を加えることができる。
方法としては、直接SQLを書かずにRuby DSLを使う。そしてRuby DSLはDBに依存しない。
migrationはまるで新しいデータベースのように思えるかもしれません。
migrationによって、何もない状態から、テーブルやカラム、エントリーをスキーマに作成したり、
スキーマから削除したりする。時系列にそって、最新の履歴からActive Record はスキーマに更新を
かけます。またDBの最新の状態と矛盾しないようdb/schema.rbを更新します。
migrationの一例です。
class CreateProducts < ActiveRecord::Migration def change create_table :products do |t| t.string :name t.text :description t.timestamps end end end
このmigrationは型がstringのnameカラム、型がtextのdescriptionを持つproductsテーブル
を作成しています。
プライマリキーであるidは自動的に作成されます。(すべてのActive Record modelsにとってこのプライマリーキーはデフォルトです。)
timestampsのマクロは、created_atとupdated_atという2つのカラムを作成します。
この2つのカラムが存在する場合は、Active Recordによって、自動的に管理されます。
次にその時の変更を以前の状態に戻したい時の変更の定義についてお話しします。
migrationが実行される前は、テーブルは存在しません。実行された後には存在します。
逆に、ActiveRecordはこのmigrationの操作をなかったことにすることもできます。
migrationをrollbackすれば、テーブルは削除されます。
スキーマの変更文に対するトランザクションをサーポートするDBでは、migrationsは
トランザクションにラップされています。データベースがトランザクションをサポートしていない場合、
実行されたmigrationの一部に失敗し、rollbackはされません。
その時は、直接変更文を作成し、rollbackする必要があります。
※
Active Record では戻す事のできない処理をmigrationで行いたい場合は、reversibleを使う
def change reversible do |dir| change_table :products do |t| dir.up { t.change :price, :string } dir.down { t.change :price, :integer } end end end end
またchangeの代わりにup and downも使える。
class ChangeProductsPrice < ActiveRecord::Migration def up change_table :products do |t| t.change :price, :string end end def down change_table :products do |t| t.change :price, :integer end end end
2、Migrationの作成
2.1 スタンドアローンMigrationの作成
Migrationsはdb/migrateディレクトリーにmigration class毎に保存される。
ファイル名の命名規則はYYYYMMDDHHMMSS_create_products.tb。
UTC timestamp_migration名。ファイル名の後方はmigrationのクラス名と一致していなければ
ならない。
例えば20080906120000_create_products.rbのクラス名はCreateProducts、
20080906120001_add_details_to_products.rbはAddDetailsToProductsと
定義される必要がある。
Railsはどのmigrationを、どの順番で実行するかをこのtimestampで判断している。
なので、もし、自分で他のアプリケーションからmigrationをコピーし、ファイルを生成する場合、
順番に気をつけてもらいたい。
timestampを計算するのが楽しくない、なのでもちろんActive Recordにはtimestampを計算
するgeneratorがある
$ rails generate migration AddPartNumberToProducts
空ではあるが、きっちり命名されたmigrationが作成させる。
class AddPartNumberToProducts < ActiveRecord::Migration def change end end
もしmigration nameが "AddXXXToYYY" or "RemoveXXXFromYYY"の形式で、
カラム名と型のリストが続いて書かれている場合、
add_column と remove_column を含んだ、migrationが作られる。
$ rails generate migration AddPartNumberToProducts part_number:string
を実行すれば
class AddPartNumberToProducts < ActiveRecord::Migration def change add_column :products, :part_number, :string end end
が生成される。
もし、新しいカラムにindexを作成したい場合は、このようにして下さい。
$ rails generate migration AddPartNumberToProducts part_number:string:index
を実行すれば
class AddPartNumberToProducts < ActiveRecord::Migration def change add_column :products, :part_number, :string add_index :products, :part_number end end
ができる。
同じくコマンドラインからカラムを削除するmigrationを生成することができる
$ rails generate migration RemovePartNumberFromProducts part_number:string
を実行すれば、
class RemovePartNumberFromProducts < ActiveRecord::Migration def change remove_column :products, :part_number, :string end end
が生成される。
一度に生成されるカラムに制限はありません。
例えば、
$ rails generate migration AddDetailsToProducts part_number:string price:decimal <|| を実行すれば >|ruby| class AddDetailsToProducts < ActiveRecord::Migration def change add_column :products, :part_number, :string add_column :products, :price, :decimal end end
が生成される。
migration名が"CreateXXX"でカラムと型名のリストが続く場合、migrationはリストにあるカラム
とセットのXXXテーブルが作成される。
例えば
$ rails generate migration CreateProducts name:string part_number:string
を実行すれば
class CreateProducts < ActiveRecord::Migration def change create_table :products do |t| t.string :name t.string :part_number end end end
が生成される。
いつもどおり、最初の段階で生成されたものに、追加や削除の変更を加えたい場合、
db/migrate/YYYYMMDDHHMMSS_add_details_to_products.rbファイルを編集すればよい。
また、話が変わるが、generatorはreferencesという型のカラムを作る事ができる。
例えば、
$ rails generate migration AddUserRefToProducts user:references
を実行すると
class AddUserRefToProducts < ActiveRecord::Migration def change add_reference :products, :user, index: true end end
が生成される。
このmigrationはuser_idカラムと適切なインデックスを作成する。
もしJoinTableがmigration名の一部にあれば、結合したテーブルを生成するgeneratorとなる。
rails g migration CreateJoinTableCustomerProduct customer product
は下記のmigrationを生成する。
class CreateJoinTableCustomerProduct < ActiveRecord::Migration def change create_join_table :customers, :products do |t| # t.index [:customer_id, :product_id] # t.index [:product_id, :customer_id] end end end
2.2 Model Generators
class CreateProducts < ActiveRecord::Migration def change create_table :products do |t| t.string :name t.text :description t.timestamps end end end
2.2 Model Generator
model scaffold generator は 適切に新しいmodelを追加する為のmigrationを生成する。
このmigrationはmodelと関係するテーブルを作成する命令も含まれている。
どんなカラムが必要かRailsに指示すれば、それらのカラムを加える為の実行文が生成される。
例えば
$ rails generate model Product name:string description:text
を実行させると下記の様なmigrationが生成される。
class CreateProducts < ActiveRecord::Migration def change create_table :products do |t| t.string :name t.text :description t.timestamps end end end
必要なカラムとその型を好きなだけ追加できます。
2.3 サポートされているタイプの拡張
フィールドタイプの後ろにカーリブランケットでいくつかのオプションの指定も可能だ。
以下の拡張が可能。
limit string/text/binary/integer フィールドの最大サイズの指定 precision decimal フィールドの精度の定義 scale decimal フィールドのscaleの定義 polymorphic 外部キー null カラムへのnullを許可するかしないか
例えば
$ rails generate migration AddDetailsToProducts price:decimal{5,2} supplier:references{polymorphic}
を実行させると
class AddDetailsToProducts < ActiveRecord::Migration def change add_column :products, :price, :decimal, precision: 5, scale: 2 add_reference :products, :supplier, polymorphic: true, index: true end end
が生成される。
3 Migrationの書き方
generatorsでmigrationを作ったので、それを実行させよう。
3.1 Creating a Table
最も基本的だが、それっきりのmethodであるcreate_table methodは、
model scafforld generatorを使えば生成される。
典型的なものがこれである。
create_table :products do |t| t.string :name end
nameカラムを持ったproductsテーブルが生成される。
(暗黙的にidカラムも生成される。)
デフォルトで、create_tableはidと呼ばれるプライマリキーが生成される。
primary_keyオプションを使用すれば、primary_keyの名前を変更する事が可能です。
(ただし関係するmodelを更新するのも忘れないで下さい。)
もしプライマリキーが不必要であれば、id: falseオプションを指定して下さい。
特別なオプションをデータベースに指定したい場合は:optionsオプションを使えばSQLの
一部に置き換える事ができる。
例えば
create_table :products, options: "ENGINE=BLACKHOLE" do |t| t.string :name, null: false end
は
テーブルを作成するのに使われるSQL分にENGINE=BLACKHOLEを加えます。
(MySQLの場合defaultはENGINE=InnoDB)
3.2 JoinTableを作成する。
create_join_table methodはHABTM join Tableを作成する。
典型的な使われ方です。
create_join_table :products, :categories
category_id と product_idと呼ばれる2つのカラムを持ったcategories_productsテーブル
を作成する。これらのカラムはdefaultでnullオプションにfalseが設定される。
テーブルnameをカスタマイズしたい時は:table_name を使えば可能だ。
create_join_table :products, :categories, table_name: :categorization
コレを実行すればcategorizationテーブルが生成されるでしょう。
デフォルトで、オプションのない2つのカラムを生成する。しかし、:column_options
オプションを使えばオプションを使用できる。例えば、
create_join_table :products, :categories, column_options: {null: true}
を実行すれば、:nullオプションがtrueのproduct_id と category_idが生成される。
create_join_tableはindexや追加カラムを加える為のブロックもかける。
create_join_table :products, :categories do |t| t.index :product_id t.index :category_id end
3.3Changing Tables
create_tableに近いchange_tableは、既存のテーブルに変更を加える際に使用する。
create_tableにほぼ似ているが、ブロック内で使用されるオブジェクトはちょっとトッリキーだ。
change_table :products do |t| t.remove :description, :name t.string :part_number t.index :part_number t.rename :upccode, :upc_code end
descriptionとnameカラムを削除し、part_numberカラムを追加しそれに、indexを加えている。
最後にはupccodeカラムをリネームしている。
3.4 When Helpers aren't Enough
Active Record のヘルパーでできない場合、
生のSQLを実行する為のexecute methodを使用する。
Products.connection.execute('UPDATE `products` SET `price`=`free` WHERE 1')
ここのmethodの詳細と例は、APIドキュメントをチェックしてください。
特に
ActiveRecord::ConnectionAdapters::SchemaStatements
( change, up and down methodsの利用方法)
ActiveRecord::ConnectionAdapters::TableDefinition
( create_tableによって生成されたオブジェクトの利用)
ActiveRecord::ConnectionAdapters::Table
( change_tableによって生成されたオブジェクトの利用)
のドキュメント
3.5 Using the change Method
変更する為のmethodは、基本ん的にwriting migrations.の方法です。
だいたいの場面で動作し、自動的にmigrationを戻す方法がActive Record にはある。
現在、変更methosは以下のmigrationの定義のみサポートする。
add_column
add_index add_reference add_timestamps create_table create_join_table drop_table (must supply a block) drop_join_table (must supply a block) remove_timestamps rename_column rename_index remove_reference rename_table
change_table は change,change_default,removeを呼ぶ事のできない、
reversibleである。
もし、上記のmethod以外のものを使う必要がある場合は、changeテーブルの代わりにreversibleかup and down methos
を使用すべきである
3.6 Using reversible
複雑なmigrationsはActive Recordが置き換えられない処理を要求する場合がある。
migrationを実行する時にすべき事、migrationを変換させる時に他にする事、
を特記するのにreversibleを使用する。
例えば
class ExampleMigration < ActiveRecord::Migration def change create_table :products do |t| t.references :category end reversible do |dir| dir.up do #add a foreign key execute <<-SQL ALTER TABLE products ADD CONSTRAINT fk_products_categories FOREIGN KEY (category_id) REFERENCES categories(id) SQL end dir.down do execute <<-SQL ALTER TABLE products DROP FOREIGN KEY fk_products_categories SQL end end add_column :users, :home_page_url, :string rename_column :users, :email, :email_address end
reversibleを使えば、正しい順番で、指示が実行される。
このmigrationが戻される場合、home_page_urlが削除された後、productsテーブルが削除される直前にdownブロックが
実行される。
3.7 Using the up/down Methods
change mathodの変わりに、古いmigration styleのup down methodを使う事もできる。
up methosはスキーマに変更を加えたいとき、down methodは up methodによる変更を取り消したい
時に使う。一方でdown methodの変更を加えた後に、up methodを使用するような変更は、
データベーススキーマに加えられるべきではない。up methodでテーブルを作成したならば、
down methodでテーブルを削除するべきだ。
up methodでなされた変更の順番にそって、変更を取り消すのが賢明だ。
reversible methodnの例は以下と同等である。
class ExampleMigration < ActiveRecord::Migration def up create_table :products do |t| t.references :category end # add a foreign key execute <<-SQL ALTER TABLE products ADD CONSTRAINT fk_products_categories FOREIGN KEY (category_id) REFERENCES categories(id) SQL add_column :users, :home_page_url, :string rename_column :users, :email, :email_address end def down rename_column :users, :email_address, :email remove_column :users, :home_page_url execute <<-SQL ALTER TABLE products DROP FOREIGN KEY fk_products_categories SQL drop_table :products end end
もしmigrationで逆行できない様な事があれば、down methodから ActiveRecord::IrreversibleMigration
を呼ぶべきです。誰かがそのmigrationを逆行しようとすれば、「それはできない」という
エラーメッセージをディスプレイに表示させる。
3.8 Reverting Previous Migrations
revert methosを使えば、migrationsをrollbackできるのも Active Record
の特徴だ。
require_relative '2012121212_example_migration' class FixupExampleMigration < ActiveRecord::Migration def change revert ExampleMigration create_table(:apples) do |t| t.string :variety end end end
またrevert methodでは逆行する為の命令文を、ブロックの中に書く事もできる。
以前のmigrationの一部を逆行する際に便利だ。ExampleMigrationがcommitされ、
後に、商品リストにするのが良いと決まった場合。一例としてこのようにかける。
class SerializeProductListMigration < ActiveRecord::Migration def change add_column :categories, :product_list reversible do |dir| dir.up do # transfer data from Products to Category#product_list end dir.down do # create Products from Category#product_list end end revert do # copy-pasted code from ExampleMigration create_table :products do |t| t.references :category end reversible do |dir| dir.up do #add a foreign key execute <<-SQL ALTER TABLE products ADD CONSTRAINT fk_products_categories FOREIGN KEY (category_id) REFERENCES categories(id) SQL end dir.down do execute <<-SQL ALTER TABLE products DROP FOREIGN KEY fk_products_categories SQL end end # The rest of the migration was ok end end end
同様な動作をするmigrationを、revert methodを使わずに書く事はできるが、
2、3作業が増える。create_table、reversible methodの順番で逆行させ、
create_table method をdrop_table methodで置き換え、最後にdoen method
でup methodを置き換える。逆もまた然りである。
この作業ははrevert methodによっては必要ない。
4 Running Migrations
Railsには一連のmigrationsを実行する為の、Rakeタスクが存在する。
まだどのmigrationも実行されていない場合は、全てのmigrationでchange か up
methodが実行されるのが基本の動きである。すでに実行されたmigrationが存在する場合は、
migrationの日付を基準に実行される。
db:migrateタスクを実行すると、db/schema.rb fileを更新する為のdb:schema:dumpタスクも
実行される。これによりデータベースの構造との差異をなくす。
指定されたバージョンがあれば、 Active Recordはmigrationsが指定されたバージョンに
なるまで要求されたmigrationsを実行する。
バージョンはファイル名の数字の接頭辞である。例えば、version 20080906120000のmigrationを
実行する場合は
$ rake db:migrate VERSION=20080906120000
こうである。
もし20080906120000が現バージョンよりも新しければ、20080906120000を含むすべてのmigrationで
change or up methosを実行する。もし現バージョンよりも古ければ、何も実行しない。
もし、下方にmigrateしたい場合は、全てのmigrationでdownmethodが実行される。
それは20080906120000を含まない。
4.1 Rolling Back
よくあるのが、最後に実行したmigrationをrollbackすることだ。
実行したmigrationに間違いがあり、それを修正したい場合だ。
前に実行したmigrationと関係するバージョンの数字を追っていくよりも。
$ rake db:rollback
実行する事で実現する。
これで、最新のmigrationはrollbackされる。これでchange methodやdown methosで
後戻しする必要はない。もしいくつかのmigrationをなかったことにする必要がある場合は
STEPパラメーターを使用すれば良い。
$ rake db:rollback STEP=3
これを実行すれば、最新の3つのmigrationを後戻しすることができる。
db:migrate:redo taskを実行すれば、rollbackとmigrationの再実行を同時に行ってくれる。
db:rollbackと同様に、STEPパラメーターを使えば、1バージョン以上遡って実行することがかのうである。
例えば
$ rake db:migrate:redo STEP=3
db:migratを一度も実行していなこれば、これらのtaskは何も動作しない。
これらのmethodを使用すれば、migrateのバージョンを気にする必要もない。
4.2 Resetting the Database
4.3 Running Specific Migrations
特別なmigrationのup down methodを実行する必要がある時、
db:migrate:up, db:migrate:downタスクを実行させる。
適切なバージョンを指定し、それに一致するmigrationがあれば、
change,up,down methodが実行される。
例えば
$ rake db:migrate:up VERSION=20080906120000
を実行すれば
バージョン20080906120000のmigrationの、change or up methodが動作する。
このtaskは先ずmigrationが既に実行済みのものかをチェックし、それが既に実行されている
ものであれば、なんの動作も行わない。
4.4 Running Migrations in Different Environments
rake db:migrateはデフォルトではdevelopment環境で実行される。
別の環境に対して実行させたい場合は、RAILS_ENVという環境変数を使用すればよい。
例えばtest環境にたいしてmigratinを実行させたい場合、
$ rake db:migrate RAILS_ENV=test
を実行すればよい。
4.5 Changing the Output of Running Migrations
defaultのmigrationでは、何をして、それにどれくらいの時間がかかったを、教えてくれる。
テーブルを作成し。indexを作成すrmigrationは以下の様なものを出力する。
== CreateProducts: migrating =================================================
-
- create_table(:products)
-> 0.0028s
== CreateProducts: migrated (0.0028s) ========================================
この出力を変更できるようにmigrationにはいくつかのmethodがある。
Method Purpose
suppress_messages Takes a block as an argument and suppresses any output generated by the block.
say Takes a message argument and outputs it as is. A second boolean argument can be passed to specify whether to indent or not.
say_with_time Outputs text along with how long it took to run its block. If the block returns an integer it assumes it is the number of rows affected.
例えば、このmigration。
class CreateProducts < ActiveRecord::Migration def change suppress_messages do create_table :products do |t| t.string :name t.text :description t.timestamps end end say "Created a table" suppress_messages {add_index :products, :name} say "and an index!", true say_with_time 'Waiting for a while' do sleep 10 250 end end end
このような出力となる。
== CreateProducts: migrating =================================================
-
- Created a table
-> and an index!
-
- Waiting for a while
-> 10.0013s
-> 250 rows
== CreateProducts: migrated (10.0054s) =======================================
Active Recordを使って、何も出力してほしくない場合は、
rake db:migrate VERBOSE=false
を実行すればよい。
5 Changing Existing Migrations
migrationを書けば、時々ミスをする時もある。
既にそのmigrationを実行してしまっていれば、そのmigrationを編集する事も、
再度実行する事もできない。
Railsの設計上、すでにrake db:migrateされたmigrationに対しては
なにも行わない。
migrationをrollbackし、migrationを変更した後にrake db:migrate
を実行しなければならない。
普通、既に存在するmigrationを編集することはあまりおすすめしない。
自分や共同作業者に余分な仕事をさせてしまうだけでなく、既に存在している
migrationが本番で実行されてしまっている場合は、頭を悩ます大きな原因となる。
代わりに、変更を反映させる為の新しいmigrationを書くべきだ。
まだソース管理ツールにコミットされていないmigration(あなたのmachineにしかないmigration)
を編集することは、比較的危険性は低い。
以前のmigrationのすべて、または一部をなかったことにする為の、新しいmigration
書く際に,revert methodは役に立つ。
6 Using Models in Your Migrations
migrationでデータを作ったり、更新したりする時、しばしばModelを使う。
Modelを使用する事で、基本的なデータへのアクセスが簡単にできるようになる。
それはいいが、いくつか懸念点がある。
例えば、
問題はこういう場合に生じる。
今データベース上には存在しないが、
このmigrationか次のmigratioによって作られる様なカラムをModelで使用する際だ。
アリスとボブがProduct model含む、同じコードを共同作業度編集している場合を想定してほしい。
ボブは休暇に行くとする。
その間にアリスはproductsテーブルに新しいカラムを追加するmigrationを作り、それを実行する。
# db/migrate/20100513121110_add_flag_to_product.rb
class AddFlagToProduct < ActiveRecord::Migration def change add_column :products, :flag, :boolean reversible do |dir| dir.up { Product.update_all flag: false } end end end
彼女はまた、新しいカラムに対するValidationをProduct Modelに追記する。
# app/models/product.rb
class Product < ActiveRecord::Base validates :flag, presence: true end
アリスはproductsテーブルに他のカラムを追加する第二のmigrationを作成し、実行する。
# db/migrate/20100515121110_add_fuzz_to_product.rb
class AddFuzzToProduct < ActiveRecord::Migration def change add_column :products, :fuzz, :string reversible do |dir| dir.up { Product.update_all fuzz: 'fuzzy' } end end end
彼女はまたProduct modelに新しカラムに対するvalidationを追記する。
# app/models/product.rb
class Product < ActiveRecord::Base validates :flag, :fuzz, presence: true end
両方のmigrationは正常に動作する。
ボブは休みから帰ってくる、そして
・全てのソースを更新 - 両方のmigrationと最新のProduct Modelを含む
・rake db:migrateでmigrationを実行させる。それは、Product Modelを更新
するmigrationも含む。
migrationはクラッシュする。モデルが保存しようとする際、
最初のmigrationが実行された時にはデータベース上には
存在しない、2つ目のカラムに対してvalidation使用とするからだ。
rake aborted!
An error has occurred, this and all later migrations canceled:
undefined method `fuzz' for #
コレを解決するには、migration内にローカルなmodelを作成すればよい。
そうすれば、validationが実行されず、migrationの実行は完了する。
local modelを使用する際に、もう一つやっておいた方がいいことは、
Product.reset_column_informationを呼び出すことだ。
これにより、データベースを更新する前のProduct Modelに対するActive Recordのキャッシュ
を更新することができる。
もし代わりにアリスがやってくれていれば、なにも問題はない。
# db/migrate/20100513121110_add_flag_to_product.rb
class AddFlagToProduct < ActiveRecord::Migration class Product < ActiveRecord::Base end def change add_column :products, :flag, :boolean Product.reset_column_information reversible do |dir| dir.up { Product.update_all flag: false } end end end
# db/migrate/20100515121110_add_fuzz_to_product.rb
class AddFuzzToProduct < ActiveRecord::Migration class Product < ActiveRecord::Base end def change add_column :products, :fuzz, :string Product.reset_column_information reversible do |dir| dir.up { Product.update_all fuzz: 'fuzzy' } end end end
7 Schema Dumping and You
7.1 What are Schema Files for?
Migrationはデーターベーススキーマは主として操作する為のソースコードではない。
Migrationはデータベースの状態をしらべ、Active Recordが生成するdb/schema.rb
もしくは、SQLファイルを元に、データベースに落とし込む。
db/schema.rbやSQLファイルは編集されるように設計はされていない。
ただ現状のデータベースの状態を表しているだけである。
アプリの新しいインスタンスを展開するのに、migrationの履歴置き換える必要はない。
現在のスキーマの情報をデータベースにより単純で素早くロードする為の方法である。
例えば、testデータベースを作る方法の例を挙げる。
development用のデータベースがダンプされる。
そしてtest用データベースにロードされる。
db/schema.rbはActive Record object がどのような属性を持っているのかすぐに見るのに
便利である。modelのソースコードの情報もないし、いくつかのmigrationにそって展開されているが、
大変良く要約されている。
annotate_models gemを使えば、そのスキーマをまとめているモデルの最新の
コメントを要約し、更新することができる。
7.2 Types of Schema Dumps
スキーマをダンプするには2つの方法がある。
config/application.rbにconfig.active_record.schema_format setting,
を記述する。:ruby :sqlのステータスがある。
もし:rubyが選択されていれば、スキーマの情報はdb/schema.rbに蓄積されていく。
もし、
ActiveRecord::Schema.define(version: 20080906171750) do create_table "authors", force: true do |t| t.string "name" t.datetime "created_at" t.datetime "updated_at" end create_table "products", force: true do |t| t.string "name" t.text "description" t.datetime "created_at" t.datetime "updated_at" t.string "part_number" end end
このファイルはデータベースを検証し、create_table, add_indexなどで
構造を表現する事によって作られる。なぜなら、これらはデータベースに依存していないからだ。
Active Recordが対応しているどんなデータベースにでもロードされる。
どんな多様なデータベースを実行するアプリケーションを運用するのには非常に便利なことである。
しかしトレードオフとしてdb/schema.rb はデータベースに依存する、外部キーやトリガー
ストアドプロシージャようなものには対応する事ができない。
migrationの中で、カスタムされたSQLを実行することはできるが、このschemaの情報からは、
データベースに合うように命令文を再構築することができない。
もしこの特徴を使いたいのなら、:sqlオプションで、スキーマ情報を用意すべきだ。
Active Recordのスキーマ情報を使用する代わりに、データベースの構造はdb/structure.sql
にデータベースの情報を記載するツールを使う事で、データベースの構造を表現する事ができる。
例えばPostgreSQLではpg_dump utilityが使われる。MySQLでは、このファイルに
SHOW CREATE
TABLE for the various tables.
の出力が含まれている。
スキーマをロードする事は、単純な
定義によって、データベース構造の完全んあコピーを作る。:sql使うスキーマのフォーマットは、
7.3 Schema Dumps and Source Control
schema dumpsはデータベースのスキーマをコントロールする。
そのため、それらはソース管理することを進める。
8 Active Record and Referential Integrity
ロジックは、modelに書くべきで、データベースに書くものではないというのが、ActiveRecordの
特徴だ。外部キーやトリガーのようなロジックをDBに集約してまうようは方法は多用しない。
validates :foreign_key, uniqueness:のようなバリデーションはデータが整合性を保つ為の方法である。
:dependentオプションは親のオブジェクトが消された時に自動的に子のオブジェクトを消す為のものだ。
9 Migrations and Seed Data
データベースにデータを作る際に
class AddInitialProducts < ActiveRecord::Migration def up 5.times do |i| Product.create(name: "Product ##{i}", description: "A product.") end end def down Product.delete_all end end <|| こう書かれる時がある。 だが、Railsにはseedというものがる。初期データをデータベースに作る時に使われる。 これはほんとにシンプルなものだ。db/seeds.rb にRuby codeを書いて、rake db:seed: を実行させるだけ。 >|ruby| 5.times do |i| Product.create(name: "Product ##{i}", description: "A product.") end <||
nfs設定
※環境
【Webサーバー】
eth0 インターネット
eth1 LAN(192.168.0.1)
【スイッチ】
eth0 LAN(192.168.0.2)
【DB用サーバー】
WebサーバーからDB用サーバーの/usr/postgres-9.3を参照できるようにしたい。
sanbaかnfsでファイル共有。
Linux同士だし、設定簡単そうなnfsでやることに。
NFSサーバの設定(192.168.0.2)
# yum install nfs-utils
(portmapパッケージ付)
# yum install rpcbind
•匿名ユーザ(nfsnobody)書き込みを可能にするため、所有者を変更します。
#chown nfsnobody:nfsnobody /nfs_dir
# NFS の設定ファイルの編集
# vi /etc/exports
/nfs_dir 192.168.0.0/24(rw,root_squash)
•exportfsコマンドで設定の反映と確認を行います。
# exportfs -ra
# exportfs -v
/usr/pgsql-9.3 192.168.0.0/24(rw,wdelay,root_squash,no_subtree_check)
•関連デーモンを順に起動します。
# /etc/rc.d/init.d/rpcbind start
rpcbind を起動中: [ OK ]
# /etc/init.d/nfslock start
NFS statd を起動中: [ OK ]
# /etc/init.d/nfs start
NFS サービスを起動中: [ OK ]
NFS クォータを起動中: [ OK ]
NFS デーモンを起動中: [ OK ]
NFS mountd を起動中: [ OK ]
自動起動ON
# chkconfig rpcbind on
# chkconfig nfslock on
# chkconfig nfs on
NFSクライアントの設定(192.168.0.1)
•rpcbindをインストールします。
# yum install rpcbind
•rpcbindを起動します。
# /etc/init.d/rpcbind start
rpcbind を起動中:
•自動起動の設定を行います。
# chkconfig rpcbind on
マウントの設定
•マウント用のディレクトリを作成します。
# mkdir /usr/postgres-9.3
•マウント
# mount -t nfs 192.168.0.2:/usr/postgres-9.3 /usr/postgres-9.3
・確認
% df -h
Filesystem Size Used Avail Use% マウント位置
/dev/vda3 195G 4.1G 181G 3% /
tmpfs 939M 0 939M 0% /dev/shm
/dev/vda1 243M 50M 181M 22% /boot
192.168.0.2:/usr/pgsql-9.3
195G 1.7G 184G 1% /usr/pgsql-9.3
※実はmaunt時にエラー
mount.nfs: trying text-based options 'vers=4,addr=192.168.0.2,clientaddr=192.168.0.1'
ファイヤーフォールでひかかってるっぽいから、iptables変更
再度mountすると成功!
railsスケルトン作成
環境
【Webサーバー】
eth0 インターネット
eth1 スイッチ
【スイッチ】
eth0 スイッチ
【DB用サーバー】
設定
【Webサーバー】
Railsインストール
ドキュメントを省いてインストール
gem install rails # --no-ri --no-rdoc
#railsあぷり作成
$ rails new soneTrack
Could not find gem 'sqlite3 (>= 0) ruby' in the gems available on this machine.
??エラー
※rails new のデフォルトDBサーバーはsqllite。
sqlliteインストールしていないから当然エラー
#db postgre指定でrails new
$ rails new test_apl -d postgresql
#bundler installでGemfileファイルから該当のgemをインストール
% bundle install --path=vendor/bundle --binstubs=vendor/bin
(注)pg インストール時にエラーが出る場合
bundle config build.pg --with-pg-config=/usr/pgsql-9.3/bin/pg_config
⇒pg_configのパスを設定してあげる。
その後にbundle install
◾[--path]
指定したディレクトリへGemをインストールします。指定しない場合はrbenvのグローバルな領域へインストールされます。
上記の場合、カレントディレクトリに「vendor/bundle」というディレクトリが掘られ、インストールされます。
◾[--binstubs]
指定したディレクトリへコマンドとなるスクリプトを配置します。指定しない場合はカレントに 「bin」というディレクトリが出来てそれいかにスクリプトが置かれます(※1 注意が必要)
上記の場合、「vendor/bin」というディレクトリにスクリプトが配置されます。 「bundle_bin」というディレクトリ名を指定するのも多いようですが、自分はvendor/binとしてインストールしました。
【DB用サーバー】
#postgres設定
すでにpostgresSQLはインストール済み
#userの追加
createuser -a xxxxx
- a, --adduser
新しいユーザが他のユーザを作成することを許可します。(注意: 実際これにより新しいユーザはスーパーユーザ となります。このオプションの名前はあまり適したものとはいえません。)
% createdb -E UTF8 -O xxxx test_production -T template0
所有者xxxxx db名test_production を文字コードUTF8 で template0を下に作成
#ユーザーのパスワード設定
% psql -c "alter user postgres with password 'xxxxxx'"
% psql -c "alter user xxxx with password 'xxxxxxx'"
※192.168.0.0/24 から 接続許可設定
vim /var/lib/pgsql/9.3/data/pg_hba.conf
以下の一行を追加
host all all 192.168.0.0 255.255.255.0 md5
#DB接続方法変更(md5)
http://www.postgresql.jp/document/9.2/html/auth-pg-hba-conf.html
※Listen_Adressの変更
vim /var/lib/pgsql/9.3/data/postgressql.conf
listen_adress = "*"
※postgresの再起動(設定の読み込み)
service postgresql-9.3 restart
※postgresSqlで使用するポートの解放
vim /etc/sysconfig/iptables
以下一行を追加
- A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport xxxxx -j ACCEPT
rbenvでruby2.1.0インストール
rbenvのインストール
rbenvとは
rubyバージョン切り替えの為のツール
#homeディレクトリにrbenvをgit clone(どこでもいい)
$ git clone git://github.com/sstephenson/rbenv.git .rbenv
#rbenvコマンドへのpath設定
path=(# rbenv用
$HOME/.rbenv/bin(N-/)
#rbenv initコマンド実行
'eval "$(rbenv init -)"
#インストール確認
$ rbenv
rbenv 0.3.0
usage: rbenv
・・・・
ruby-buildのインストール
ruby-buildとは
rbenvのプラグインで、ruby等をインストールする為のツール
git cloneでrbenvのpluginに追加
$ git clone git://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build
ruby インストール
rbenv install 2.1.0
#使用するバージョンのしてい
rbenv global 2.1.0
#バージョンの確認
- [2994]% ruby -v
ruby 2.1.0p0 (2013-12-25 revision 44422) [x86_64-linux]
ruby アクセサメソッド
クラスの中でインスタンス変数に値を保存したり呼び出したりするメソッド。
ゲッターとかセッターとか言われるやつ。
■インスタンス変数(CFでいうとcfpropertyみたいな。)
http://www.rubylife.jp/ini/class/index4.html
■アクセサメソッド
http://fujitaiju.com/blog/%E5%88%9D%E5%BF%83%E8%80%85/ruby%E3%81%AE%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B5%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89%EF%BC%88attr_%E3%81%A3%E3%81%A6%E3%82%84%E3%81%A4%E3%81%AD%EF%BC%89/
なんか上のサイトに全部書いてくれいるので、メモ終わり。
Singleオブジェクト Processオブジェクト
Signal
http://doc.ruby-lang.org/ja/1.9.3/class/Signal.html
Process
http://doc.ruby-lang.org/ja/1.9.3/class/Process.html
まぁリファレンスにも書いてる通り
SignalはUnixのシグナル関連を操作するオブジェクト
ProcessはUnixのプロセスを操作するオブジェクト
Signalオブジェクトにはtrapって関数あるみたいだけど、
送信されたシグナルをトリガーにコマンド実行させる事できるみたい。
Signal.trap("INT") { print "test"; exit 1; }
Ctrl+Cで割り込みシグナルを送信したらtestって出力してexitする。
Processオブジェクトはまた今度。