Как Rails может получить доступ к предыдущей записи в серии? - PullRequest
1 голос
/ 07 ноября 2010

Скажем, у меня есть Statement модель, которая has_many :months. С отчетом всегда связано 12 месяцев, но первый месяц может варьироваться (например, месяцы = [март, апрель, май ... январь, февраль])

Учитывая определенный месяц, как MVC может найти предыдущий месяц?

Я получаю доступ к нему через statement, который кажется грязным:

# statement.rb
has_many :months

def previous_month(month)
  if months.index(month) == 0
    return nil
  else
    return months[months.index(month) - 1]
  end
end

# blergh
prev_month = month.statement.previous_month(month)

Должен ли я иметь столбец previous_month_id в моей базе данных? Как бы вы реализовали эту функциональность? Я использую Rails 2.3.x.

Ответы [ 3 ]

1 голос
/ 08 ноября 2010

Я бы определил это для модели Month, чтобы сократить круговые поездки.

# month.rb
class Month < ActiveRecord::Base
  belongs_to :statement, :include => :months

  def previous
    return nil if self.index == 0
    find_or_create_by_index_and_statement_id(self.index - 1, self.statement.id)
  end

  def index
    statement.months.index self
  end
end

, чтобы вы могли получить june.previous.Это должно работать даже на несохраненных записях.

0 голосов
/ 24 ноября 2010

Чтобы сделать это способом MVC, я бы, вероятно, применил эту логику к тому, что «владеет» операторами.Ведь утверждение обычно принадлежит чему-то.После прочтения комментариев, похоже, это унаследованный проект.Если нет, то вам нужно спросить, почему у вас есть отношения «месяцев», когда в заявлении есть столбец created_at, к которому вы можете привязать?Вот то, что я придумал, это может быть не полезно для вас.Хотя сделайте заказ Date::MONTHNAMES, по крайней мере, это может быть полезно для вас.

describe User do
  before(:each) do
    @user = User.create!
  end

  it "should know about months" do
    Statement.create(:user => @user)
    @user.statements.last.month_name.should == "November"
  end

  it "should report last months statement as nil when there is no statement" do
    @user.last_months_statement.should be_nil
  end

  it "should report last months statement as nil if there is only one for this month" do
    Statement.create(:user => @user)
    @user.last_months_statement.should be_nil
  end

  it "should report a statement from the previous month if there is one"  do
    target = Statement.create(:user => @user, :created_at => 1.month.ago)
    Statement.create(:user => @user)
    @user.last_months_statement.should == target
  end

  it "should report last months statement if there a several" do
    Statement.create(:user => @user, :created_at => 1.month.ago)
    Statement.create(:user => @user)
    Statement.create(:user => @user, :created_at => 2.months.ago)
    @user.last_months_statement.month_name.should == "October"
  end
end

class User < ActiveRecord::Base
  has_many :statements, :order => "created_at"

  def last_months_statement
    if statements.size <= 1 || statements.last.created_at.month < Time.now.month
      nil
    else
      index = statements.index(statements.last)
      statements[index - 1]
    end
  end
end

class Statement < ActiveRecord::Base
  belongs_to :user

  def month
    created_at.month
  end

  def month_name
    Date::MONTHNAMES[created_at.month]
  end
end
0 голосов
/ 07 ноября 2010

Как складываются эти месяцы? Если они добавляются отдельно в хронологическом порядке месяцев, то вы можете просто делать то, что у вас есть, но вы должны определить порядок в отношениях.

#statement.rb

has_many :months, :order => 'created_at ASC'

Если они добавлены другим способом, то вам, возможно, придется подумать о наличии столбца заказа и использовании actions_as_list для поддержания заказа.

...