代码之家  ›  专栏  ›  技术社区  ›  nfm

Rails是如何访问一个系列中的前一个记录的?

  •  1
  • nfm  · 技术社区  · 14 年前

    说我有一个 Statement 模型,其中 has_many :months 第一个月可能不同 (例如月数=[三月、四月、五月…一月、二月])

    给定一个月,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 数据库中的列?您将如何实现此功能?我在用铁轨 2.3.x .

    3 回复  |  直到 11 年前
        1
  •  1
  •   edgerunner    14 年前

    我会在 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

        2
  •  0
  •   mark    14 年前

    这些月是怎么加的?如果它们是按照月份的时间顺序单独添加的,那么您可以简单地执行已有的操作,但是您应该定义关系中的顺序。

    #statement.rb
    
    has_many :months, :order => 'created_at ASC'
    

    如果它们是以其他方式添加的,那么您可能需要考虑使用order列和 acts_as_list 维持秩序。

        3
  •  0
  •   Jed Schneider    14 年前

    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