将查询从视图移动到模型

时间:2011-08-27 11:57:47

标签: ruby ruby-on-rails-3

我有两个非附加模型 - 里程碑和用户。 (我的里程碑实际上属于公司,公司有许多里程碑。)

每个里程碑都有一个负责它的用户 - 以我的里程碑形式,我使用以下内容来查找和选择用户:

<%= f.input :milestone_user, :as => :select, :collection => User.find(:all, :order => "name ASC") %>

这给了我一个user_id,我在一个视图中将其转换为如下名称:

<%= User.find(milestone.milestone_user).name %>

这很好但我现在想在几个视图中使用它,并且不喜欢在我的视图中查询。

我试图将其移到我的用户模型中,但我不知道如何去做。我在模型中试过这个:

  scope :username, lambda { where("id = milestone_user")}

这在我看来:

<%= User.username.first_name %>

但它抱怨first_name的未定义方法..

提前致谢

4 个答案:

答案 0 :(得分:5)

将此添加到您的Milestone型号:

def username
  User.find(milestone_user).try :name
end

并在您的视图中使用它:

<%= milestone.username %>

但这不是有效的,更好的方法是将belongs_to :user, :foreign_key => "milestone_user", :class_name => "User"粘贴到Milestone模型中。您不必填写关联,您仍然可以在没有分配用户的情况下创建里程碑。

belongs_to还允许您在视图中使用这样的代码:

<%= milestone.user.name %>

无需为您要访问的每个用户属性创建其他方法。

答案 1 :(得分:1)

在相关控制器的操作中移动查询:

@milestone_user=User.find(milestone.milestone_user)

然后在视图中使用try

<%= @milestone_user.try(:name) %>

答案 2 :(得分:1)

将模型设置为default_scope => :order('name asc')

在您的控制器中执行@users = User.all

在您的观看中,将collection_select@users

一起使用

e.g。 collection_select(:milestone,:user_id,@ users,:id,:name)

有关

的更多信息,请参阅http://api.rubyonrails.org/classes/ActionView/Helpers/FormOptionsHelper.html#method-i-collection_select

collection_select,grouped_collection_select,grouped_options_for_select以及其他包含

等选项的帮助者

'grouped_collection_select(object,method,collection,group_method,group_label_method,option_key_method,option_value_method,options = {},html_options = {})'

答案 3 :(得分:0)

我认为协会应该是这样的:

class Milestone < ActiveRecord::Base
  belongs_to :company
  has_one :user
end

class Company < ActiveRecord::Base
  has_many :milestones
end

class User < ActiveRecord::Base
  has_one :milestone
end

如果您像上面那样进行关联,那么在视图方面您只需编写

<%= @milestone.user.firstname%>

否则你可以修改你的范围:

  scope :milestone_user, lambda { |user_id|
    where("id = ?",user_id)
  }

这里我只修改了范围的名称。

并通过传递参数从视图调用。

<%= User.milestone_user(milestone.milestone_user).first_name %>

您也可以使用委托方法。