Rails 4将数据从控制器传递给模型attr_accessor

时间:2014-02-15 10:48:55

标签: ruby-on-rails

好的,我很困惑,有点卡在这里,我试图通过attr_accessor将数据传递给我的模型,但我找不到正确的方法。这是我到目前为止的设置:

class ApplicationController < ActionController::Base
  before_filter :current_league

  protected

  def current_league
    @current_league ||= Conf.all.order('updated_at ASC').last.league
  end
end

class HerosController < ApplicationController
  def index
    @heros = Hero.all.order(:name)
  end
end

class Hero < ActiveRecord::Base
  attr_accessor :current_league

  def some_method
    puts current_league
  end
end

<% @heros.each do |hero| %>
  <tr>
    <td><%= hero.some_method %></td>
  </tr>
<% end %>

现在如何在我的模型中设置@current_league?我知道我的模型中可以有attr_accessor,但这仅适用于此模型的实例,但据我所知,索引操作不会创建实例。也许有人可以指出我正确的方向。提前谢谢。

1 个答案:

答案 0 :(得分:2)

@heros变量是Hero实例的集合。您可以循环浏览它们并根据需要进行设置。

class HerosController < ApplicationController
  def index
    @heros = Hero.all.order(:name).each do |hero|
      hero.current_league = current_league
    end
  end
end

虽然它有效,但我觉得这个答案并不那么优雅。当然,我不知道你正在做的事情的完整范围,但根据这里的代码,我将创建一个复合对象。像这样:

class HeroInLeague

  attr_reader :league, :hero

  def initialize(league, hero)
    @league = league
    @hero = hero
  end

  def some_method
    # ...
  end

end

然后您可以在控制器中创建这些对象:

class HerosController < ApplicationController
  def index
    @heros_in_league = Hero.all.order(:name).map { |hero|
      HeroInLeague.new(current_league, hero)
    }
  end
end

现在,您已经创建了一个与英雄和联盟相关的方法。为什么这很重要?好吧,使用之前的方法,你可能最终会使用Hero上的方法,这些方法在没有现有联盟时没有任何意义。 (比如some_method方法)。这让英雄级别变得有点乱。现在,您已经创建了一个放置some_method及其所有朋友的地方。

您可以使用delegators使HeroInLeague的界面更加友好,因此您无需执行hero_in_league.hero.foo,但可以直接致电hero_in_league.foo