如何将数据库操作从控制器移动到模型

时间:2013-03-16 17:06:31

标签: ruby-on-rails-3 ruby-on-rails-3.2

我已经开始使用新工具处理旧项目了。这一次 - Ruby上的Rails。我设法取得了一些进展,现在我想改进我的代码中的一个元素。

整个项目是关于跟踪所有跟踪错误的完整历史记录的错误跟踪。现在我正处于用户输入错误的阶段。每个bug都属于属于项目的表。

只有问题 - 现在 - 是在我使用全新名称时自动完成表名(使用已存在于数据库中的表,它正常工作,在Bug条目中填充table_id)。

负责输入(或从现有中选择)表的部分视图如下所示:

<div class="control-group">
  <%= f.label :table_name, :class => 'control-label' %>
  <div class="controls">
    <%= f.autocomplete_field :table_name, autocomplete_table_name_bugs_path %>
  </div>
</div>

没什么不寻常的。这个去了模型(Bug.rb)

class Bug < ActiveRecord::Base
  attr_accessible :bugid, :fixdate, :fixnote, :fixstate_id, :milestone, :newtarget, :notes, :oldtarget, :project_id, :bugreason, :reason_id, :regressiondate, :regressionstate_id, :source, :stringid, :table_id

  belongs_to :project
  belongs_to :table
  belongs_to :reason
  belongs_to :state

  def table_name
     table.name if table
  end

  #def table_name=(name)
  #  self.table = Table.find_or_create_by_name(name) unless name.blank?
  #end

end

现在没有验证,你可以看到。 table_name =(name)注释,因为它显然在我的代码中什么也没做。

这适用于bug控制器(bugs_controller.rb)

def create
  if params[:bug][:table_id].nil?
    if Table.find_or_create_by_name(params[:bug][:table_name])
      params[:bug][:table_id] = Table.find_by_name(params[:bug][:table_name]).id
      params[:bug].delete :table_name
    end

  end

  @bug = Bug.new(params[:bug])

  respond_to do |format|
    if @bug.save
      format.html { redirect_to bugs_path, notice: 'Bug was successfully created.' }
      format.json { render json: @bug, status: :created, location: @bug }
    else
      format.html { render action: "new" }
      format.json { render json: @bug.errors, status: :unprocessable_entity }
    end
  end
end

我在这里只负责保存新错误的部分,当我正确执行此部分时,我将设法处理更新部分。

我想改进的是第一部分。现在它不仅负责将table_name更改为table_id,而且还负责创建新表(如果它不存在)。我知道这个部分应该由模型处理,但我不知道如何做到这一点,可以使用一些帮助。

另一部分,如顺便说一句。是我的下拉菜单,用户可以在其中选择活动项目。它由部分处理:

<% @projects.each do |project| %>
    <% if project.id == session[:current_project].to_i %>
        <li class="disabled"><%= link_to project.name, '#' %></li>
    <% else %>
        <li><%= link_to project.name, choose_project_path(project.id) %></li>
    <% end %>
<% end %>

但只有在项目控制器中使用它才能正常工作。怎么 - 通过这本书 - 我可以从其他控制器处理这个?确切地说,我希望它在整个项目中以相同的方式工作。

现在我正在通过每个控制器中的片段处理它,但我很确定RoR众神对我不满意。

  before_filter :projects

  def projects
    @projects = Project.all
  end

应该如何以正确的方式完成? :)

1 个答案:

答案 0 :(得分:0)

所以我设法将逻辑从控制器转移到模型。此外,在创建新表时,它将我需要的所有数据 - table_id保存到bugs表和project_id(存储在会话中)到表表。

因此表单渲染的一部分不会改变:

<div class="control-group">
  <%= f.label :table_name, :class => 'control-label' %>
  <div class="controls">
    <%= f.autocomplete_field :table_name, autocomplete_table_name_bugs_path %>
  </div>
</div>

模型现在看起来像这样:

class Bug < ActiveRecord::Base
  attr_accessible :table_name, :bugid, :fixdate, :fixnote, :fixstate_id, :milestone, :newtarget, :notes, :oldtarget, :project_id, :bugreason, :reason_id, :regressiondate, :regressionstate_id, :source, :stringid, :table_id

  belongs_to :project
  belongs_to :table
  belongs_to :reason
  belongs_to :state

  def table_name
     table.name if table
  end

  def table_name=(name)
    self.table = Table.find_or_create_by_name(name, project_id: self.project_id ) unless name.blank?
  end

end

因此,只有更改是取消注释table_name =方法并将project_id添加到新表的创建(缺少project_id是它之前没有工作的原因)。

控制器看起来像这样:

  def create

    @bug = Bug.new(params[:bug])
    @bug.project_id = session[:current_project]

    respond_to do |format|
      if @bug.save
        format.html { redirect_to bugs_path, notice: 'Bug was successfully created.' }
        format.json { render json: @bug, status: :created, location: @bug }
      else
        format.html { render action: "new" }
        format.json { render json: @bug.errors, status: :unprocessable_entity }
      end
    end
  end

它像魅力一样工作。我仍然质疑剩下的问题,但会将其作为单独的问题发布。