ActiveRecord - problemy poczatkujacego :)

Witam.

Jestem zupelnie poczatkujacym userem Railsow.
Zakupilem sobie ksiazke “Rails. Wprowadzenie” i realizuje po kolei przyklady.
Jestem na rozdziale nt. Active Record.
Baza danych stworzona, wykonuje komendy w konsoli Rails:

show.Slideshow.find 1
…(wypisuje odpowiedni rekord z bazy)

show.slides.each {|slide| puts slide.photo.filename}
i tu nastepuje szereg bledow zaczynajacych sie od:
NoMethodError: undefined method ‘photo’ for #Slide:0x4799bc8
from (i tu lista sciezek do plikow konfiguracyjnych activeRecord, w ktorych nic nie zimenialem.)

Program wykonany poprawnie powinien wypisac liste plikow z bazy.

I w tym momencie koncza mi sie pomysly, bo probowalem w tej komendzie wpisywac nazwy wielkimi literami, dobierac nazwy pol w bazie (np zamiast ‘photo’ pisalem ‘photo_id’) itd. Nic to jednak nie dalo.

Bede wdzieczny za jakies naprowadzenie na przyczyne tego bledu.

#############################################################
Dodatkowo, wklejam tutaj zawartosci pliku ‘slide.rb’
#############################################################
class Slide < ActiveRecord::Base
belongs_to :slideshows
acts_as_list :scope => “slideshow_id”
belongs_to :photos
end

#############################################################
i ‘photo.rb’
#############################################################
class Photo < ActiveRecord::Base
validates_presence_of :filename
has_many :slides
has_and_belongs_to_many :categories
end
#############################################################

#############################################################
‘slideshow.rb’
#############################################################
class Slideshow < ActiveRecord::Base
has_many :slides, :order => :position
end

i jeszcze migracje:
#############################################################
create_slides.rb
#############################################################
class CreateSlides < ActiveRecord::Migration
def self.up
create_table :slides do |t|
t.column “position”, :integer
t.column “photo_id”, :integer
t.column “slideshow_id”, :integer
end
end

def self.down
drop_table :slides
end
end

#############################################################
create_photos.rb
#############################################################
class CreatePhotos < ActiveRecord::Migration
def self.up
create_table :photos do |photo|
photo.column “filename”, :string
end
end

def self.down
drop_table :photos
end
end

Nie znam przykładów z tej książki ale na pierwszy rzut oka wygląda na błąd w:

class Slide < ActiveRecord::Base belongs_to :slideshows acts_as_list :scope => "slideshow_id" belongs_to :photos end
powinno być:

class Slide < ActiveRecord::Base belongs_to :slideshow acts_as_list :scope => "slideshow_id" belongs_to :photo end
Jeśli Photo ma wiele slajdów, to Slide należy do jednego Photo więc powinno być belongs_to :photo a nie :photos. Potwierdzają to też wstępnie migracje, które wkleiłeś. Spróbuj z tymi poprawkami i napisz czy pomogło.

wielkie dzieki!
pomoglo.

Witam postanowilem dopisac tu swoj problem

gdyz tez dotyczy Active Record w tej ksiazce

Otoz nie dziala mi automatyczne utworzenie kategorii Category ‘All’
do ktorej nalezec maja wszystkie zdjecia ( photo )

O to moj create_categories.rb

[code]class CreateCategories < ActiveRecord::Migration
def self.up
create_table “categories” do |t|
t.column “name”, :string
t.column “parent_id”, :integer
end

create_table("categories_photos", :id=>false) do |t|
  t.column "category_id", :integer
  t.column "photo_id", :integer
end

Category.new do |category|
  category.name = "All"
  Photo.find(:all).each do |photo|
    photo.categories <<  category
    photo.save
  end
end

end

def self.down
drop_table “categories”
drop_table “categories_photos”
end
end[/code]

all = Category.find :first

zwraca wartosc nil

wczesniej zostal do bazy zaladowany skrypt

insert into slideshows values (1, 'Interesting pictures', now()); insert into slides values (1, 1, 1, 1); insert into slides values (2, 2, 2, 1); insert into slides values (3, 3, 3, 1); insert into slides values (4, 4, 4, 1); insert into slides values (5, 5, 5, 1); insert into slides values (6, 6, 6, 1); insert into slides values (7, 7, 7, 1); insert into slides values (8, 8, 8, 1); insert into slides values (9, 9, 9, 1); insert into photos values (1, "balboa_park.jpg"); insert into photos values (2, "camel.jpg"); insert into photos values (3, "cat_and_candles.jpg"); insert into photos values (4, "hut.jpg"); insert into photos values (5, "mosaic.jpg"); insert into photos values (6, "polar_bear.jpg"); insert into photos values (7, "police.jpg"); insert into photos values (8, "sleeping_dog.jpg"); insert into photos values (9, "stairs.jpg");
rowniez storzenie nowego zdjecia

photo = Photo.new

nie tworzy kategorii All

Pokaż definicję modeli Category i Photo.

Czy na pewno sprawdzasz odpowiednią bazę danych (production lub development)?

Photo.new

Masz rację, to nie działa. Aby stworzyć dowiązania nowego zdjęcia do categorii ‘All’ przy jego tworzeniu, w modelu Photo musisz użyć callback’a after_create.

class Category < ActiveRecord::Base has_and_belongs_to_many :photos acts_as_tree end

[code]class Photo < ActiveRecord::Base
validates_presence_of :filename

has_many :slides
has_and_belongs_to_many :categories
end[/code]
myslalem ze sprawe automatycznego dodania do kategorii All zalatwia to :

Category.new do |category| category.name = "All" Photo.find(:all).each do |photo| photo.categories << category photo.save end end

Niestety nie załatwia, ten kod jest ok, z tym, że photo.save nie jest potrzebne. Zapis powiązania następuje już w photo.categories << category. Kod ten jednorazowo przypisuje zdjęcia istniejące już w bazie do kategorii All.

Uruchom script/console, a na drugiej konsoli tail -f log/development.log i wypróbuj tą serię wywołań na pustej bazie. Po każdym z nich obserwuj log i sprawdzaj czy SQL jest ok:

p = Photo.create!(:filename => 'woods.jpg') p.categories # [] c = Category.create!(:name => 'All') p.categories << c p = Photo.find_by_filename('woods.jpg') # załadowanie zdjęcia prosto z bazy dla pewności ;) p.categories # [#<Category:0xb71397fc @attributes={"name"=>"All", "id"=>"1", "category_id"=>"1", "photo_id"=>"3"}>]
Po # jest wartość która powinna zostać zwrócona. Jak widzisz u mnie to działa, mam identyczne modele, jak Twoje.

Dzieki rozjasnilo mi sie teraz

i wszystko mi dziala

pozdr …wracam do pracy

Nie ma sprawy. :slight_smile:

W przyszłości ktoś może spotkać się z podobnym problemem, więc napisz co było nie tak w Twoim przypadku.

Wszystko bylo niby ok

Stworzenie zdjecia i nadanie mu kategorii dziala

Nie dziala tylko ten kod ktory w czasie migracji mial dodawac istniejace zdjecia
do kategorii All

ale w sumie nie jest mi potrzebny

witam , mam pytanie .<równierz jestem poczatkujacym w sprawie rubyego>
równierz ide wedlug ksiazki O’REILEY

Mam problem mianowice : kiedy wchodze do konsoli ruby script/console

wedlug ksiazki moge podgladnac dzialanie modelu /klasy

wpisujac slide = slideshow.find 1

wyskakuje mi błąd

NoMethodError: undefined method ‘slide’ for #Slide:0x4799bc8

zawartosc modelu slide.rb

class Slide < ActiveRecord::Base
belongs_to :slideshows
belongs_to :photos
end

według ksiazki powinienem miec mozliwosc wprowadzenia zaleznosci w konsoli.
Prosze o pomoc

[quote=beny18241]wpisujac slide = slideshow.find 1

wyskakuje mi błąd

NoMethodError: undefined method ‘slide’ for #Slide:0x4799bc8

zawartosc modelu slide.rb

class Slide < ActiveRecord::Base
belongs_to :slideshows
belongs_to :photos
end[/quote]
Przeczytaj caly watek.

Powinno byc:

class Slide < ActiveRecord::Base belongs_to :slideshow belongs_to :photo end
wielkosc liter w Ruby ma znaczenie zatem w konsoli wpisz: slide = Slideshow.find(1), chociaz na pierwszy rzut oka to wyszuka Tobie Slideshow a nie Slide (patrz: nazwa Twojej zmiennej)

ok dzieki za pomoc. ale mam jedno pytanko
kiedy wpisuje ta linijke

slide = Slide.find(1)

wyskakuje mi taka informacja:

#<Slide:048xa2b50 @attributes={“slideshow_id”=>“1”, “id” => “1” , “photo_id”=>“1” , “position”=>“1”}>

według ksiazki :slight_smile: idac krok po kroku powinenem wprowadzac wiersze polecen np. slide.photo.filename.

Ja wiem ze ta informacja wyskakujaca od rubiego w zasadzie mi to przedstawia, czy to jest błąd ? czy coz robie zle ? naprawde nie wiem bo nigdzie nie moge znalezc tej informacji.
prosze o małą podpowiedz .

To nie tyle Ruby, co irb (interaktywna konsola Rubiego), na którym oparty jest skrypt console, wypisuje na ekran te informacje. A jest to zawsze wartość ostatniego wyrażenia. Na przykład wpisujesz w konsolę: 1 + 2, normalnie nic by się nie stało, ale irb Ci wypisze 3, żebyś wiedział jaką wartość otrzymałeś. Jednakże jeśli wartością jest jakiś obiekt to domyślnie komunikat ma postać: #<NazwaKlasy:adres_szesnastkowy @atrybut1=wartość1, @atrybut2=wartość2…>.
Jeśli chcesz to możesz przedefiniować sposób w jaki wyświetlane są te komunikaty. Pobaw się metodą “inspect”, która to jest wykorzystywana przez irb.

ale chyba jednak to cos nie działa <na poczatek moje pliki .rb> -> Prosze pomozcie naprawde duzo czasu spedzam nad tym i nie moge wpasc a rozwiazanie.

photo.rb

class Photo < ActiveRecord::Base
has_many :slides
validates_presence_of :filename
end

slide.rb

class Slide < ActiveRecord::Base
belongs_to :slideshow
belongs_to :photos
end

slideshow.rb

class Slideshow < ActiveRecord::Base
has_many :slides
end
wpisujac

slide = Slides.find 1

wyskakuje:

#<Slide:0x48a2b50 @attributes={“slideshow_id”=>“1”, “id” => “1” , “photo_id”=>“1” , “position”=>“1”}>

a potem

slideshow = slide.slideshow

wyskakuje:

#<Slideshow:0x48b7208 @attributes={“name”=>“interesjace obrazki”, “id” => “1” , “created_in”=>“2007-09-25 21:30:39” }>

na koncu

slideshow.slides.each {|slide| puts slide.Photo.filename}

i znowu wypada

NoMethod Errror:undefined method ‘Photo’ for <#Slide:048a3640>

w powinno sie otrzymac liste slajdów.

jak komus to pomoze w namierzaniu to ksiazka “ruby on Rails” O’reilly na stronie 50 - 52.
Naprawde robie krok po kroku.prosze jeszcze raz o pomoc.

kkempin już raz poprawił ten błąd w pliku slide.rb

class Slide < ActiveRecord::Base belongs_to :slideshow belongs_to :photos end
Skup się nad tym fragmentem. Podpowiem, że belongs_to lubi nazwy w liczbie pojedynczej.

dzieki , naprawde nie wiem skad mi sie znowu wziela liczba mnoga w slide.rb
, dzieki wam bardzo.wracam do pracy

Książka książką, ale myśleć też trzeba :). Programowanie (a także jego nauka) nie polega na bezmyślnym przepisywaniu kodu - w ten sposób nic się nie nauczysz. Świadoma nauka i myślenie najczęściej pomaga już w trakcie nauki w wykrywaniu błędów, które zawsze mogą się pojawić w książkach (wiem to z doświadczenia).

[quote=beny18241]photo.rb

class Photo < ActiveRecord::Base
has_many :slides
validates_presence_of :filename
end

slide.rb

class Slide < ActiveRecord::Base
belongs_to :slideshow
belongs_to :photos
end

slideshow.rb

class Slideshow < ActiveRecord::Base
has_many :slides
end
wpisujac

slide = Slides.find 1

wyskakuje:

#<Slide:0x48a2b50 @attributes={“slideshow_id”=>“1”, “id” => “1” , “photo_id”=>“1” , “position”=>“1”}>[/quote]
Napisałem Ci wyżej, “czemu to wyskakuje”. To nie jest błąd. To informacja, że wykonanie Twojego kodu zwróciło taką wartość. Obiekt Slide został pobrany z bazy, a patrząc “na to co wyskoczyło” można zauważyć, że jest to obiekt o takich i takich atrybutach.

[quote=beny18241]a potem

slideshow = slide.slideshow

wyskakuje:

#<Slideshow:0x48b7208 @attributes={“name”=>“interesjace obrazki”, “id” => “1” , “created_in”=>“2007-09-25 21:30:39” }>[/quote]
To samo co wyżej.

[quote=beny18241]na koncu

slideshow.slides.each {|slide| puts slide.Photo.filename}

i znowu wypada

NoMethod Errror:undefined method ‘Photo’ for <#Slide:048a3640>[/quote]
Czy chociaż czytasz to “co Ci wyskakuje”? Jak widać tu rzeczywiście jest błąd, ale trzeba to przeczytać. “NoMethod Errror:undefined method ‘Photo’ for <#Slide:048a3640>”, czyli “Niezdefiniowana metoda ‘Photo’ dla obiektu Slide”.

[quote=beny18241]w powinno sie otrzymac liste slajdów.

jak komus to pomoze w namierzaniu to ksiazka “ruby on Rails” O’reilly na stronie 50 - 52.
Naprawde robie krok po kroku.prosze jeszcze raz o pomoc.[/quote]
Kod z książki:

[code]>> slide = Slide.find 1

slideshow = slide.slideshow

slideshow.slides.each {|slide| puts slide.photo.filename}[/code]
Masz u siebie ‘photo’ z dużej litery. Jeśli nie wiesz dlaczego raz jest z dużej (class Photo < …, Photo.find(…)) a raz z małej (slide.photo) to proponuję odłożyć książkę i wpierw nauczyć się czystego Rubiego.

I jeszcze na koniec cytat z książki, rozdział 2.4.2. The Rails Console:

[quote]We’ll use the console to create some new objects, and save them to the database:[*]

[*] After each statement you type, the console will print the value of object.inspect for the last object returned.[/quote]