2012-10-26 55 views
5

我是ruby和rails的新手,我希望尽可能遵循编码标准和约定,所以我不会选择任何坏习惯。我有两种模式:课程和地点。课程属于某个地点,因为课程只能有一个地点。位置has_many课程,作为一个位置可以由多个课程共享。努力了解模型和关联如何在rails中保存

创建课程时,可能已经存在可以通过其ID找到的位置。或者该位置可能还不存在,在这种情况下,必须创建新的位置记录。我的课程控制器具有以下创建操作。

def create 
    @course = Course.new(params[:course]) 

    if params[:course][:location][:id].blank? 
    @course.location = Location.create(params[:course][:location]) 
    else 
    @course.location = Location.find_by_id(params[:course][:location][:id]) 
    end 

    @course.save 

    respond_with @course 
end 

注意,这是一个REST API,只有使用JSON响应。发出请求的帖子一个JSON阵列相同的格式,将通过一个GET请求返回

{ 
    "course": 
    { 
    "title":"US History", 
    "credits":"3", 
    "max_students":"100", 
    "location": 
    { 
     "id":"", 
     "building":"Freedom Hall", 
     "room":"301" 
    } 
    } 
} 

or 

{ 
    "course": 
    { 
    "title":"US History", 
    "credits":"3", 
    "max_students":"100", 
    "location": 
    { 
     "id":"12", # this is the only difference 
     "building":"Freedom Hall", 
     "room":"301" 
    } 
    } 
} 
  1. 与所有我读过的例子相比,该代码看起来不那么优雅的JavaScript 。有更好的方法来分解它吗?
  2. 如果Location.create引发异常,@ course.save仍会被调用吗?我需要使用Location.create !?
  3. 同样,即使错误位于位置模型上,验证错误是否会以@ course.errors结尾?我是否需要从异常中拯救,以便将错误返回给客户端?

非常感谢您的帮助!

回答

2

您可以通过使用find_or_initialize_by_id清理一下。这应该工作:

def create 
    @course = Course.new(params[:course]) 
    @course.location = Location.find_or_initialize_by_id(params[:course][:location][:id], 
                 params[:course][:location]) 
    @course.save 
    respond_with @course 
end 

关于你提到的第二个问题,在你的代码,你拥有它@course.save不会,如果Location.create(或Location.find)抛出一个异常调用(因为他们会发生在前)。但是,我已经对上面的代码进行了编码,在调用save时,在代码中的相同位置会发生异常,此时关联也会保存。

+0

谢谢!我正在倾向于这样的事情,但我的脚很冷。你确认了我对异常处理的怀疑 - 我只是不知道幕后是否有任何事情发生,这可能会影响我的期望。这是否需要在我的课程模型中添加“accep_nested_attributes_for:location”? – glevine

+0

不客气。没有AFAIK,因为您明确设置了位置上的属性,所以您不必添加'acceptersted_attributes_for:location'来执行此操作。虽然,如果你有嵌套属性,我相信你可以用'@course = Course.new(params [:course])'初始化所有的东西','location'属性会自动设置。还没有测试过,虽然不确定它是否会在位置id设置时工作。 –

+0

我需要编写一些测试,但是一旦我做了,我会在我的发现中添加注释。我的担心是,如果在嵌套位置设置了id,但所有其他字段都是空的,那么rails实际上会更新匹配位置上的属性,将它们设置为空(假设空字段是有效的),并保存记录。这将导致清除位置记录中的数据。但我不禁想到铁轨足够聪明,知道该怎么做。就像我说的,一旦我知道它实际上是如何工作的,我会再次回复。 – glevine

1

试试这个,在你的控制器

def new 
    @course = Course.new 
    @location = @course.location.build # if one..many relationship 
    @location = @course.build_location # if one..one relationship 
end 

def create 
@course = Course.new(params[:course]) 
if @course.save 
    respond_with @course 
else 
    render :action => "new" 
end 
end 

更多nested_attributes

+0

感谢您的回复!这样做的好处是什么,而不是使用find_or_initialize_by_id?我需要了解更多关于嵌套模型的知识。我想我并没有将这些与嵌套相关的点联系起来。 – glevine