在Rails中执行此操作的正确方法是什么?

时间:2014-06-13 14:44:07

标签: ruby-on-rails rails-activerecord

所以我从Model,a和b得到了两条记录。我想这样做:

def do_codependant_stuff(a,b)
    a.attribute += b.attribute2
    b.attribute = b.stuff+a.stuff
end

我一直听到胖模型,瘦调控制器,视图中没有业务逻辑,所以我把它放在我的Model模型中。根据用户在我的一个视图中点击的内容,我想调用do_codependant_stuff(a,b)或do_codependant_stuff(b,a)。

到目前为止,我一直在使用基本的crud控制器操作,而且我不太确定如何实现这一点。我是否将此逻辑添加到我的ModelController更新操作中?因为它在技术上更新它们,只是以更具体的方式。或者在控制器中再做一次动作?我怎么称呼它/设置它?大多数默认的新版本,更新版本等都是根据各自的观点在幕后调用的。

并且一次更新两件坏事吗?我应该将do_codependant_stuff方法拆分为两个实例方法,并在每个记录上调用它们,另一个作为参数吗?

感谢阅读。

编辑: 好吧,现实世界的代码。我在我的应用程序的主页上显示两张图片。用户选择他们最喜欢的那个。这些图片的评级基于国际象棋排名算法而改变。这是我的图片类的相关部分。

 class Picture < ActiveRecord::Base
   ...
   ...
        def expected_first_beats_second(picture first, picture second)
            1/(1+10**((second.rating-first.rating)/400))
        end
        def first_beat_second(picA,picB)
            Ea = expected_first_beats_second(picA,picB)
            picA.rating += 50*(1-Ea)
            picB.rating += 50*(-(1-Ea))

        end
    end

用于视图的部分I到目前为止随机显示两张图片

<% picA = Picture.offset(rand(Picture.count)).first %>
<% picB = Picture.offset(rand(Picture.count)).first %>

<div class = "row">
    <div class = "col-md-5">
        <%= image_tag picA.url, :class => "thumbnail" %>
    </div>
    <div class = "col-md-5">
        <%= image_tag picB.url, :class => "thumbnail" %>
    </div>
</div>

我需要以某种方式将这些图像的onclick链接到模型中的方法。

1 个答案:

答案 0 :(得分:1)

这里有一些代码可以帮助您入门。请注意评论,它们是ruby和rails最佳实践

控制器:

class PC < AC
  ...
  def compare
    # count query once, save the number
    count = Picture.count
    @pic_a = Picture.offset(rand(count)).first
    @pic_b = Picture.offset(rand(count)).first
  end

  def compare_submit
    # Note variables are snake cased, not camel cased
    pic_a = Picture.find(params[:winner_id])
    pic_b = Picture.find(params[:loser_id])
    pic_a.beats(pic_b)
    redirect to compare_pictures_path # Or wherever
  end
  ...
end

任何类型的查询都应该在控制器或模型中完成。您基本上不应该直接访问视图中的模型。此时,您的视图可以访问控制器中设置的实例变量:@pic_a@pic_b

查看:

<%= link_to compare_submit_pictures_path(winner_id: @pic_a.id, loser_id: @pic_b.id) do %>
  <%= image_tag @pic_a.url, :class => "thumbnail" %>
<% end %>

<%= link_to compare_submit_pictures_path(winner_id: @pic_b.id, loser_id: @pic_a.id) do %>
  <%= image_tag @pic_b.url, :class => "thumbnail" %>
<% end %>

所以我们只是链接到一个新路径(请参阅下面的路线),它会传递两个参数:winner_idloser_id因此,无论用户点击哪一张图片,您都会知道他们选择哪一个以及哪个一个他们没有选择。

型号:

class Picture < AR::Base
  # Method arguments don't need a type declaration
  def beats(loser)
    # Always lowercase variables
    ea = 1/(1+10**((loser.rating-self.rating)/400))
    self.rating += 50*(1-ea)
    loser.rating += 50*(-(1-ea))
    self.save
    loser.save       
  end
end

为明确起见,明确使用self,这不是必需的。调用saverating = ...会自动调用它,因为我们处于图片模型的实例方法的上下文中。

路线:

resource :pictures do
  collection do
    get :compare
    get :compare_submit
  end
end