说我有一个Statement
模型,has_many :months
。声明总共有12个月,但第一个月可能会有所不同(例如月份= [3月,4月,5月... 1月,2月])
鉴于某个月,找到上个月的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
。
答案 0 :(得分:1)
我会在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
。这应该适用于未保存的记录。
答案 1 :(得分:0)
这几个月是如何添加的?如果它们按照几个月的时间顺序单独添加,那么你可以简单地做你所拥有的,但你应该在关系中定义顺序。
#statement.rb
has_many :months, :order => 'created_at ASC'
如果他们以其他方式添加,那么您可能需要考虑订购列并使用acts_as_list维护订单。
答案 2 :(得分:0)
要做到这一点的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