ihatov08 blog

プログラミング初心者だけどRailsとSwiftマスターします

初めのアルファベットに該当するレコードのみ表示するメソッドの定義の仕方

models

  def self.by_letter(letter)
    where("lastname LIKE ?", "#{letter}%").order(:lastname)
  end

controller

  def index
    if params[:letter]
      @contacts = Contact.by_letter(params[:letter])
    else
      @contacts = Contact.order('lastname, firstname')
    end
  end

view

    <% ('A'..'Z').each do |letter| %>
      <%= link_to letter, contacts_path(letter: letter) %>
    <% end %>
    <%= link_to 'All', contacts_path %>

bootstrapも適用すれば、こんな感じのviewを出力してくれる。 f:id:ihatov08:20160713160600p:plain

RailsでAさんは同じ連絡先を登録できないが、AさんとBさんで同じ連絡先を登録できるバリデーションの設定方法

app/models/contact.rb

class Contact < ActiveRecord::Base
has_many phones

phoneモデルで同じcontact_idは持てないようにuniqunessな制約をつけると実現できる。

app/models/phone.rb

class Phone < ActiveRecord::Base
belongs_to :contact
validates :phone, uniquness: { scope: :contact_id }

Railsで掲載期間の有無を設定する実装方法

チェックボックスにチェックを入れた時はずっと掲載し続ける場合の実装方法

check_boxは引数をつけなかった場合、チェックした場合は1を、つけない場合は0が値として渡される。

form.html.erb

<%= form.check_box :no_expiration %>

アクセスメソッドを定義する。 それなら、attr_accessor使えばいいじゃんと思うけど、今回はただ、値を読みだしたり、書き出したりするのでは、事足りないので独自に定義する必要がある。 check_boxにチェックがつけられていた場合、つまり1が渡された場合に、@no_expirationをtrueにして、そうでなければfalseにする。 メソッドの中身を普段なら@no_expiration = valだけにするが、valの値をそのまま代入するのではなく、今回はtrueかfalseを代入したいので、独自に定義している。 model.rb

  def no_expiration=(val)
    @no_expiration = val.in?([true, 1, "1"])
  end

expired_atの有無によって、falseかtrueを返す。 model.rb

def no_expiration
  expired_at.blank?
end

Railsでエラーを起こした入力欄にCSSを適用させる方法

railsでエラーを起こした入力欄はclass属性がfield_with_errorsのdivタグで囲まれる。 CSSでdiv.field_with_errorsにデザインを記述すれば、エラーを起こした入力欄に色をつけられる。

div.field_with_errors {
background-color: #fcc;
padding: 2px;

Rubyのputsメソッド、printメソッドはto_sメソッドを定義すると

改訂3版基礎 Ruby on Rails (KS IMPRESS KISO SERIES)でどうしてもわからないことがあった。

untitled.rb

class Robot
  def initialize(name)
    @name = name
    @x = @y = 0
  end

  def move(x,y)
    @x += x; @y += y
  end

  def to_s
    "#{@name}: #{@x},#{@y}"
  end
end

robo1 = Robot.new("ロボ1号")
robo2 = Robot.new("ロボ2号")
puts robo1
robo2.move(10,20)
puts robo2

このコードを実行すると

$ ruby untitled.rb
ロボ1号: 0,0
ロボ2号: 10,20

と出力される。to_sメソッド呼び出してないけど、なんでto_sメソッド呼び出されているのかがわからなかった。 試しにpで出力させてみると表示が変わった。

#<Robot:0x007fdaaa0aa0f0 @name="ロボ1号", @y=0, @x=0>
#<Robot:0x007fdaaa0aa0a0 @name="ロボ2号", @y=20, @x=10>

もう少しググってみると答えがわかった。

www.task-notes.com

putsメソッドとprintメソッドはレシーバをto_sメソッドで文字列に変換してから出力する。 つまり、自分でto_sメソッドを定義すると、to_sメソッドの機能を上書きできてしまうようだ。 これを調べるのに1時間くらい時間がかかった。

素数を見つけるプログラムをrubyで

処理としては

  • 1.2.3.4.と連番の配列を用意する
  • 2から順番にその倍数を配列から削除していく
  • 削除するものがなくなったら終了。

これくらい簡単にかけるようになりたい。

引用元