2012-10-26 11 views
5

Jestem nowy w rubinach i szynach i chcę zachować standardy kodowania i konwencje najlepiej jak to możliwe, więc nie wychwycę żadnych złych nawyków. Mam dwa modele: kurs i lokalizację. Kurs należy do lokalizacji, ponieważ kurs może mieć tylko jedno miejsce. Lokalizacja ma wiele kursów, ponieważ lokalizacja może być współużytkowana przez więcej niż jeden kurs.usiłuje zrozumieć, w jaki sposób modele i asocjacje są zapisywane w szynach

Podczas tworzenia kursu może już istnieć lokalizacja znaleziona przez jego identyfikator. Lub lokalizacja może jeszcze nie istnieć, w takim przypadku należy utworzyć nowy rekord lokalizacji. Kontroler My Course ma następującą akcję tworzenia.

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 

Należy zauważyć, że jest to REST API, który reaguje tylko z JSON. Javascript, który sprawia, że ​​posty zażądać tablicą JSON w tym samym formacie, który zostanie zwrócony przez żądanie 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. W porównaniu ze wszystkimi przykładami czytałem, ten kod nie wygląda tak elegancko . Czy istnieje lepszy sposób na zliczenie tego?
  2. Jeśli obiekt Location.create zgłasza wyjątek, czy funkcja @ course.save będzie nadal wywoływana? Czy muszę używać Location.create !?
  3. Czy błędy sprawdzania poprawności pojawią się w @ course.errors, mimo że błędy wystąpiły w modelu lokalizacji? Czy muszę uratować się od wyjątku, aby móc zwrócić błędy klientowi?

Dziękuję bardzo za wszelką pomoc!

Odpowiedz

2

można czyścić, że nawet przy użyciu find_or_initialize_by_id. To powinno działać:

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 

Odnośnie drugiego pytania, w kodzie, jak masz to @course.save nie zostanie wywołana jeżeli Location.create (lub Location.find) podnosi wyjątek (bo zdarzają się na początku). Jednak sposób, w jaki to zakodowałem powyżej, wyjątek miałby miejsce w tym samym punkcie kodu, gdy jest wywoływany save, w którym to momencie skojarzenie jest również zapisywane.

+0

Dziękujemy! Pochylałem się ku czemuś podobnemu, ale miałem zimne stopy. I potwierdziłeś moje podejrzenia dotyczące obsługi wyjątków - po prostu nie wiedziałem, czy coś dzieje się za kulisami, co może wpłynąć na moje oczekiwania. Czy to wymaga dodania 'accepts_nested_attributes_for: location' do mojego modelu kursu? – glevine

+0

Nie ma za co. Bez AFAIK nie powinieneś dodawać 'accepts_nested_attributes_for: location', aby to zrobić, ponieważ jawnie ustawiasz atrybuty w tej lokalizacji. Chociaż, gdybyś miał zagnieżdżone atrybuty, wierzę, że byłbyś w stanie zainicjować wszystko za pomocą '@course = Course.new (params [: course])', a atrybuty 'location' byłyby ustawione automatycznie. Nie testowałem tego, więc nie jestem pewien, czy zadziała, gdy ustawi się 'id' lokalizacji. –

+0

Będę musiał napisać kilka testów, ale gdy to zrobię, dodam komentarz z moimi odkryciami.Obawiam się, że jeśli w lokalizacji zagnieżdżonej ustawione jest 'id', ale wszystkie pozostałe pola są puste, to szyny zaktualizują atrybuty w dopasowanej lokalizacji, ustawiając je jako puste (zakładając, że puste pola są prawidłowe) i zapisując rekord. To spowoduje wymazanie danych z rekordu lokalizacji. Ale nie mogę przestać myśleć, że szyny są wystarczająco inteligentne, aby wiedzieć, co robić. Tak jak powiedziałem, odpowiem jeszcze raz, gdy tylko będę wiedział, jak to działa. – glevine

1

Spróbuj tego, w kontrolerze

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 

więcej o nested_attributes

+0

Dzięki za odpowiedź! Jaka jest korzyść z tego, w przeciwieństwie do używania find_or_initialize_by_id? Muszę dowiedzieć się więcej o modelach zagnieżdżonych. Chyba nie połączyłem kropek z tym związanym z zagnieżdżaniem. – glevine

Powiązane problemy