Rails手动提交记录

时间:2015-07-11 21:27:06

标签: ruby-on-rails

我试图使用Rails构建一个小型2玩家回合制游戏,初始化游戏只需要1个玩家,他们将设置该区域,然后另一个玩家可以加入。游戏中的每个玩家将拥有一个可以包含建筑物的土地,它们之间的关系如下:

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

只有游戏有一个控制器,因为它是所有游戏的主人,所以当游戏初始化时,请求将包含创建土地和建筑物的信息,并且所有都被视为一个,所以如果其中一个记录失败我不想做任何事情。我想过使用building.save if land.save但是它会产生错误,因为我将建筑物保存到一块没有退出的土地上,但是如果我先保存土地并且建筑物失败那么我就#&# 39; ll需要删除土地和游戏,它会变得复杂,有多个建筑物进入,并且来自多个地方的各种错误可以处理所有这些条件。

我可以使用哪些其他选项来实现这一目标?

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

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

还有一个问题是我无法保存这样的游戏,因为它可以验证土地的存在,并且无法保存土地,因为它可以验证游戏的存在,同样适用于他们验证的建筑物土地的存在。因此,我需要一个能够一次性保存它们的代码,并且仍能成功验证它们。

2 个答案:

答案 0 :(得分:1)

您可以将查询包装在事务中:

stream file Usage: STREAM FILE <filename> <escape digits> [sample offset]

Send the given file, allowing playback to be interrupted by the given digits, if any.

Use double quotes for the digits if you wish none to be permitted.

If sample offset is provided then the audio will seek to sample offset before play starts.

Remember, the file extension must not be included in the filename.

Returns: failure: 200 result=-1 endpos=<sample offset> failure on open: 200 result=0 endpos=0 success: 200 result=0 endpos=<offset> digit pressed: 200 result=<digit> endpos=<offset>

您应该使用ActiveRecord::Base.transaction do # put your calls here end 方法,以便抛出验证创建的异常,否则查询将无声地失败。

答案 1 :(得分: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没有足够的资源,因此构建验证失败。我们向用户显示错误消息。
  6. 正如您可能猜到的那样 - 浏览器游戏设计需要广泛使用ajax和javascript。构建服务器端API只是一小部分。