2015-07-11 86 views
1

我正在尝试使用Rails构建一个小型2人回合制游戏,初始化游戏时只需要1名玩家设置该字段,然后另一名玩家可以加入。在游戏中的每个玩家都会有,它可以包含建筑物的土地,如下它们之间的关系:Rails手动提交记录

#Game 
has_many :lands 
#Land 
belongs_to :game 
has_many :buildings 
#Building 
belongs_to :game 

只有游戏控制器,因为这是他们所有的高手,所以当一个游戏是要初始化请求将包含创建土地和建筑物的信息,并且所有都被视为一个,所以如果其中一个记录失败,我不想提交任何内容。我想过使用building.save if land.save,但它会产生错误,因为我正在将建筑物保存到不会退出的土地,但如果我先保存土地并且建筑物失败,那么我需要删除土地和游戏,随着多个建筑物的进行以及来自多个地点的各种错误来处理所有这些情况而变得复杂。

我可以用其他什么方法来达到这个目的?

编辑: 游戏控制器将是这样的:

class GamesController < ApplicationController 
    def create 
    #generate new land to contain buildings 
    land = Land.new(user: @current_user) 
    #generate new buildings from array of hashes, contains coords+land_id 
    buildings = [] 
    params[:buildings].each do |building| 
     buildings.push Building.new(building.merge!({land: land})) 
    end 
    game = Game.new(user_1: @current_user, land_1: land) 
    land.game = game #set the game it belongs to 
    #some code here to save land+game+buildings 
    #if one of them failed then nothing is saved at all. 
    end 
end 

还有,我救不了这样的比赛,因为它证明了土地的存在,并不能节约土地的问题,因为它验证游戏的存在,同样适用于他们验证土地存在的建筑物。所以我需要一个能够一次性保存它们的代码,并且仍然能够成功验证它们。

+0

你能在这里添加一些实际的代码吗?它比你试图描述你的控制器中发生了什么更容易阅读。 – max

+0

我还没有编写游戏控制器,这是我坚持如何写在一个方式来实现所提到的,我会尝试用一般形式更新我如何认为它会出现。 –

+0

你认为你可以改变你的问题吗?这听起来像是你正在寻找交易,然后我再次只能理解问题的1/10。 – max

回答

0

你可以用查询在交易:

ActiveRecord::Base.transaction do 
    # put your calls here 
end 

而且你应该使用.save!方法,使通过验证的创建异常抛出,否则查询失败默默。

+0

我会看看这个,这将验证所有记录没有错误? –

+0

没有事务就像数据库中的撤消功能。您可以执行多个SQL语句,然后在任何时候回滚(撤消),直到事务提交。您可以将它与验证一起使用,但它们实际上是分开的概念。 – max

0

在Rails可以使用accepts_nested_attributes_for从相同的形式创建嵌套模式:

class User < ActiveRecord::Base 
    has_many :pets 
    accepts_nested_attributes_for :pets 
    validates_associated :pet 
end 

class UserController < ApplicationController 

    def new 
    @user = User.new 
    @user.pets.build 
    end 

    def create 
    @user 
    end 

    def pet_params 
    params.require(:user).permit(pets_attributes: [:name, :type]) 
    end 
end 

你也有可以使用,如果以后条件未能插入记录到数据库中,并回滚事务。

class OrdersController < ApplicationController 
    def create 
    @order = Order.new(order_params) 

    Order.transaction do 
     @payment = Payment.new(customer: @order.customer, amount: order.amount) 
     raise ActiveRecord::Rollback unless @order.save && @payment.save 
    end 
    end 
end 

但更重要的是不要试图在一个控制器操作中做所有事情。它导致非常脆弱和过于复杂的设计。

相反,您可能需要在多个步骤中完成游戏设置。

  1. 用户1创建游戏POST /games
  2. 用户1被重定向到GET /games/1
  3. 由于没有陆地用户1将通过在形式和职位,以/games/1/lands填充创建的土地。然后他被重定向回/games/1
  4. 用户现在可以看到我们刚刚在游戏视图中创建的土地。
  5. 用户1决定在Land 1中建立一个猪笔。他按下发送一个POST /lands/1/buildings的按钮。但用户1没有足够的资源,因此对于构建的验证失败。我们向用户显示错误消息。

正如您可能猜到的一样 - 浏览器游戏设计需要广泛使用ajax和javascript。构建服务器端API只是一小部分。

+0

我正在研究嵌套属性,它似乎是与事务结合的最佳解决方案。 我不想使用多个步骤,因为用户不允许编辑他创建的游戏并在游戏过程中阻止编辑。 –