我有一个Map
模型,它定义了MUD中给定区域的ASCII艺术地图的详细信息。我希望能够使用其名称而不是ID来访问每个地图的页面,因此,如果我有西方Ithmia地图,我希望能够从/maps/western_ithmia
访问它(还有{{1} })。
我有第二个模型/maps/withmia
,其中包含可用于到达地图的路径中的所有现有短名称。外键与每个别名一起存储,引用其关联的MapAlias
的ID。
我想要做的是与每个新创建的Map
同时创建一个新的MapAlias
。不幸的是,我似乎无法获取新的Map
ID,直到它被保存为止,但在我验证/保存新的Map
之前我不想保存它。 。更糟糕的是,我希望每个MapAlias
知道哪个Map
是其主要别名,即生成链接所引用的别名。这似乎是对我的循环依赖...
我还是Rails的新手,所以我不确定我应该做什么,但是我已经探索了模型回调钩子(比如before_save),只取得了有限的成功 - 我仍然有循环依赖来处理。有任何想法吗? = /
答案 0 :(得分:1)
在数据库事务中包装所有内容:
Map.transaction do
# ... save all your stuff ...
end
不要尝试使用回调重新实现事务...让数据库做它擅长的事情。它会全部被保存,或者没有一个被保存。
答案 1 :(得分:0)
我通常做的是同时手动创建两个模型。也就是说,如果我有两个模型,原因和结果,那么我创建我查看可以创建原因的所有方法(通常来自控制器),并包括一个创建一个效果的行,如果创建原因,传入原因中的相应参数..这样,即使它没有保存,我也可以访问它的ID(因为该对象仍然存在于方法中,即使它没有保存)。
它可能不像before_save方法那样自动,但我希望能够看到发生了什么,以及什么时候,没有在方法之前/之后生根。
答案 2 :(得分:0)
如果您尝试通过html表单进行此操作,可以在控制器上的新build
实例上调用Map
。
# maps_controller.rb
def new
@map = Map.new
@map_alias = @map.map_aliases.build
end
还有更多内容(创建虚拟属性),但您可以查看此截屏视频以获取一些想法: http://railscasts.com/episodes/75-complex-forms-part-3
答案 3 :(得分:0)
好的,经过一段时间后,我认为我有一个有效的解决方案。当我写这个问题时,Map has_many MapAlias'es,每个MapAlias属于一个Map。我最近意识到我想要的是另一个关联:一个Map belongs_to它的主要名称,网站在该地图的链接中使用它。我添加了三个钩子 - 两个before_validation_on_ *用于设置/创建别名,一个after_create用于设置别名的原始关联的map_id外键 - 它就像一个魅力。
对于控制器来说,它只是一个Map.save调用,但在内部,别名首先被保存:
belongs_to :shortname, :class_name => "MapAlias" # primary name
before_validation_on_create :add_map_alias
def add_map_alias
self.create_shortname(:title => self.title)
@alias_failed = !(self.shortname.errors.empty?)
nil
end
before_validation_on_update :set_map_alias
def set_map_alias
self.shortname.title = self.title
self.shortname.save(false)
@alias_failed = !(self.shortname.errors.empty?)
nil
end
after_create :set_alias_map_id
def set_alias_map_id
self.shortname.update_attribute :map_id, self.id
nil
end
它可能不是最理想的解决方案,但它适用于我的目的。无论如何,谢谢大家的建议!