应该在哪里的ActiveRecord :: Base.transaction是什么? [英] where should ActiveRecord::Base.transaction be?

查看:336
本文介绍了应该在哪里的ActiveRecord :: Base.transaction是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有三个型号:列表,食品和数量。列表和食物都通过数量通过的has_many关联:通过。因此,每个产品数量有三个PARAMS:food_id,list_id和金额(整数)

我的目标是创建一个新的数量(与该列表相关联)创建一个列表中的每个时间。我希望使用事务,使所有对象都必须成功创建,否则没有人会要做到这一点。

我的主要问题是:凡在我code,我应该写这个交易?我想应该是在列表模式,但我不知道;如果它应该在列表模式,我不知道哪里会的的列表模式。我认为它不应该出现在列表中的控制器,而且我发现意见在马克·达格特的博客评论的,它可能是一个独立的数据访问对象,但我不知道该怎么做。

其次:交易本身。这是很难说,如果我的错误是在交易或只是它的位置。

在情况下,它是相关的,我来到了这个问题,下面的<一个href="http://stackoverflow.com/questions/31299163/has-many-through-creating-child-after-save-actionviewtemplateerror">answers另一个问题,但我认为这应该是一个新的问题,因为我没有找到类似的一个专门有关事务。

我的列表模式,在该交易目前的生活:

 类List&LT;的ActiveRecord :: Base的
  的has_many:数量
  的has_many:食品:通过=&GT; :数量

  before_save {self.name = name.downcase}

  验证:天,presence:真正的,:numericality =&GT; {:greater_than =&GT; 0}
  验证:名称,长度:{最大:140},唯一性:{CASE_SENSITIVE:假}
结束

的ActiveRecord :: Base.transaction做
      @list = List.create
      @a = Food.all.sample(1)
      Quantity.create(food_id:@a,list_id:@ list.id,数量:兰特(6))
结束
 

没有错误,但新的数量还没有生成,这让我觉得我在做正确的事情,除了至少有一点是错误的。

我也试过

  List.transaction办
 

而不是

 的ActiveRecord :: Base.transaction做
 

,得到了相同的结果。

我会AP preciate任何方向或者说,我认为从一个非常基本点(如此基本,我无法找到它的的文档)。谢谢你。

Rails的4.2.3,Cloud9。开发数据库= sqlite3的,生产数据库=的Heroku Postgres的。

解决方案

由于宜兰berci告诉上面,有可能是你没有看到的错误。当使用事务,是一个很好的做法使用的方法嘭版本保存记录,这样你会得到一个异常时,任何验证不通过,然后交易将被rollbacked。

至于你的第一个问题,有什么地方把复杂Rails项目的讨论。几年前,座右铭是瘦控制器,脂肪模型,意思是一个人应该提取复杂的模型,使得控制器,这是更难以测试并在应用程序的流量必须是显而易见的,更具可读性。我preFER哲学的骨感一切:有没有绝对的规则,你可以把所有的东西在任何地方,但一旦它开始变得有点复杂,解压到一类是只负责一个或很少的东西。让事情小,操作简便,测试,并在需要时组合它们。

在你的情况,你可以创建一个服务或使用的情况下,简单地用它的控制器:

 类CreateList
  DEF创造!
    的ActiveRecord :: Base.transaction做
      @list = List.create!
      @food = Food.all.sample(1)
      Quantity.create!(食品:@food,列表:@list,数量:兰特(6))
    结束
  结束
结束
 

正如你所看到的,这是非常简单的测试这个类!大多数的正确的方式只能说明他们与体验真正的价值,而且也从来没有做的事情一个独特的,正确的方法,所以不断尝试不同的技术,直到你能掌握你自己的方式来解决问题!

I have three models: List, Food, and Quantity. List and Food are associated through Quantity via has_many :through. So each Quantity has three params: food_id, list_id, and amount (an integer).

My aim is to create a new Quantity (associated with that list) each time a list is created. I wish to do this using a transaction so that all objects must be successfully created or else none will be.

My main question is: where in my code should I write this transaction? I think it should be in the List model, but I'm not sure; and if it should be in the List model, I don't know where it would be within the List model. I think it should not be in the List controller, and I found advice on a comment on Mark Daggett's blog that it could be in an independent data access object, but I'm not sure how to do that.

Secondarily: the transaction itself. It is hard to tell if my mistake is in the transaction or just its location.

In case it is relevant, I came to have this question following answers to another question, but I thought this should be a new question since I didn't find a similar one specifically about transactions.

My List model, where the transaction currently lives:

class List < ActiveRecord::Base
  has_many :quantities
  has_many :foods, :through => :quantities

  before_save { self.name = name.downcase }

  validates :days, presence: true, :numericality => { :greater_than => 0 }
  validates :name, length: { maximum: 140 }, uniqueness: { case_sensitive: false }
end

ActiveRecord::Base.transaction do
      @list = List.create
      @a = Food.all.sample(1) 
      Quantity.create(food_id: @a, list_id: @list.id, amount: rand(6))
end

There is no error, but the new Quantity doesn't get created, which makes me think that I'm doing something right in addition to at least one thing wrong.

I also tried

List.transaction do

instead of

ActiveRecord::Base.transaction do

and got the same result.

I would appreciate any direction or hints on this problem that I assume stems from a misunderstanding of a very basic point (so basic that I couldn't find anything about it in the docs). Thank you.

Rails 4.2.3, Cloud9. Development database = SQLite3, production database = postgres heroku.

解决方案

As ilan berci told above, there's probably errors that you're not seeing. When using a transaction, is a good practice to save the records using the bang version of the methods, this way you'll get an exception when any validation doesn't pass, and then the transaction will be rollbacked.

As for for your first question, there's much discussion about where to put complexity in a Rails project. A few years ago, the motto was "skinny controllers, fat models", meaning one should extract complexity to models, making the controllers, which are more difficult to test and where the application's flow must be evident, more readable. I prefer a philosophy of "skinny everything": there's no absolute rule, you can put everything anywhere, but once it starts to get a little complex, extract it to a class that's responsible for only one or very few things. Keep things small, simple, tested, and compose them when needed.

In your case, you could create a service or use case, and simply use it in the controller:

class CreateList
  def create!
    ActiveRecord::Base.transaction do
      @list = List.create!
      @food = Food.all.sample(1) 
      Quantity.create!(food: @food, list: @list, amount: rand(6))
    end
  end
end

As you can see, it's extremely simple to test this class! Most of the "right ways" only show their real value with experience, and there's never a unique, correct way to do things, so keep trying different techniques until you can grasp your own way to solve a problem!

这篇关于应该在哪里的ActiveRecord :: Base.transaction是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆