Rails renderuje partial z pusta kolekcja

Witam,

w widoku mam ponizszy kod:

<% if @post.comments.any? %> <%= render @post.comments %> <% else %> <strong>Nobody comments on this post</strong> <% end %>
partial:

[code]

<%= comment.commenter %>
<%= comment.created_at.to_s %>

Email: <%= comment.email %>
Website: <%= comment.website %>

<%= comment.body %>

<%= link_to 'Destroy Comment', [comment.post, comment], method: :delete, data: { confirm: 'Are you sure?' } %>

[/code] Mimo warunku @post.comments.any w widoku wyswietlaja sie pola komentarza z pustymi wartosciami

@post.comments zwraca 0 wiec nie istnieja w bazie danych zadne przypisane komentarze do postu.

a czy w kontrolerze nie budujesz gdzieś pustego komentarza w stylu @post.comments.build ?

Nie buduje w kontrolerze pustego komentarza. Formularz z komentarzem jest umieszczony w akcji show kontrolera post.

Problem w tym ze partial komentarza jest renderowany pomimo ze warunek zwraca false:

Post Load (2.1ms) SELECT "posts".* FROM "posts" WHERE "posts"."id" = ? LIMIT 1 [["id", 5]] => #<Post id: 5, title: "dasdasd", introduction: "dsadas", ingredients_title: "dasdasdas", ingredients: "ddasdas\r\ndasdasd", preparation_title: "dasdsa", preparation: "dasdas\r\ndasdas", created_at: "2013-10-09 22:41:51", updated_at: "2013-10-09 22:41:51"> 2.0.0p247 :002 > @post.comments.any? Comment Exists (0.2ms) SELECT 1 AS one FROM "comments" WHERE "comments"."post_id" = ? LIMIT 1 [["post_id", 5]] => false 2.0.0p247 :003 >
Kod w widoku:

<!-- the comments --> <% if @post.comments.any? %> <%= render @post.comments %> <% else %> <strong>Nobody comments on this post</strong> <% end %>
Logi:

Started GET "/posts/5" for 127.0.0.1 at 2013-10-10 21:02:21 +0200 ActiveRecord::SchemaMigration Load (0.1ms) SELECT "schema_migrations".* FROM "schema_migrations" Processing by PostsController#show as HTML Parameters: {"id"=>"5"} Post Load (0.2ms) SELECT "posts".* FROM "posts" WHERE "posts"."id" = ? LIMIT 1 [["id", "5"]] Asset Load (2.0ms) SELECT "assets".* FROM "assets" WHERE "assets"."post_id" = ? ORDER BY "assets"."id" ASC LIMIT 1 [["post_id", 5]] Asset Load (0.3ms) SELECT "assets".* FROM "assets" WHERE "assets"."post_id" = ? [["post_id", 5]] Rendered comments/_form.html.erb (82.4ms) Comment Load (0.3ms) SELECT "comments".* FROM "comments" WHERE "comments"."post_id" = ? [["post_id", 5]] Post Load (0.2ms) SELECT "posts".* FROM "posts" WHERE "posts"."id" = ? ORDER BY "posts"."id" ASC LIMIT 1 [["id", 5]] Rendered comments/_comment.html.erb (3.8ms) Rendered posts/show.html.erb within layouts/application (176.1ms) Completed 200 OK in 579ms (Views: 491.7ms | ActiveRecord: 4.0ms)

Czyli w tej akcji, której logi pokazujesz? Możesz umieścić cały kod widoku?

Hej, wrzucam widok:

[code]

<%= @post.title %>

by Admin


Posted <%= distance_of_time_in_words(@post.created_at, Time.now, include_seconds: true) %>

<% if @post.assets.any? %>
<%= image_tag @post.assets.first.image(:banner), class: "img-responsive" %>
<% end %>

<%= @post.introduction %>

<%= @post.ingredients_title %>:

    <% @post.ingredients.split("\r\n").map do |ingredient| %>
  • <%= ingredient %>
  • <% end %>

<%= @post.preparation_title %>

    <% @post.preparation.split("\r\n").map do |step| %>
  • <%= step %>
  • <% end %>

<% @post.assets.each do |asset| %>
<%= link_to image_tag asset.image.url(:thumb), class: "thumbnail" %>
<% end %>

<%= render 'comments/form' %>
<% if @post.comments.any? %> <%= render @post.comments %> <% else %> Nobody comments on this post <% end %>

<%= link_to ‘Back’, posts_path %>
| <%= link_to ‘Edit’, edit_post_path(@post) %>[/code]

<!-- the comment form --> <%= render 'comments/form' %>
A za co innego odpowiada ten formularz, jak nie za inicjalizację nowego komentarza? :wink:

Więc drążymy temat dalej: co siedzi w partialu formularza? :smiley:

Może warto w kontrolerze przygotować sobie zmienne i ich używać na widokach:

@post = Post.find(params[:id]) @comments = @post.comments @comment = @post.comments.build

A może po prostu pokaż

Post Load (2.1ms) SELECT "posts".* FROM "posts" WHERE "posts"."id" = ? LIMIT 1 [["id", 5]] => #<Post id: 5, title: "dasdasd", introduction: "dsadas", ingredients_title: "dasdasdas", ingredients: "ddasdas\r\ndasdasd", preparation_title: "dasdsa", preparation: "dasdas\r\ndasdas", created_at: "2013-10-09 22:41:51", updated_at: "2013-10-09 22:41:51"> 2.0.0p247 :002 > @post.comments.any? Comment Exists (0.2ms) SELECT 1 AS one FROM "comments" WHERE "comments"."post_id" = ? LIMIT 1 [["post_id", 5]] => false 2.0.0p247 :003 >
@post.comments

Czy to w ogóle zwraca jakiś obiekt, który nie jest nilem, pustą tablicą?

IMHO na widoku (ewentualnie w kontrolerze) się coś krzaczy, więc testy w konsoli raczej nie odzwierciedlają rzeczywistości i nie pozwolą na zreprodukowanie problemu.

Formularz nie jest tutaj przyczyna, formularz wyswietla sie poprawnie. Problemem jest ponizszy kod:

<!-- the comments --> <% if @post.comments.any? %> <%= render @post.comments %> <% else %> <strong>Nobody comments on this post</strong> <% end %>
Zamiast wyswietlac komunikat: “Nobody comments on this post”
partial ten wyswietla pusty komentarz z metoda ‘Destroy’ ktora mam w formularzu. Nie moge nawet skasowac tego komentarza poniewaz on nie istnieje :slight_smile:

Mógłbyś jednak wkleić tutaj kod tego formularza?

pewnie

[code]

Leave a Comment:

<%= form_for [@post, Comment.new] do |f| %>
<%= f.label :commenter %>
<%= f.text_field :commenter, class: "form-control" %>
<%= f.label :email %>
<%= f.text_field :email, class: "form-control" %>
<%= f.label :website %>
<%= f.text_field :website, class: "form-control" %>
<%= f.label :body %>
<%= f.text_area :body, class: "form-control" %>

<%= f.submit 'Submit', :class => "btn btn-primary" %>

<% end %>
[/code]

Na pewno nigdzie nie tworzysz nowego komentarza dla posta…? Przeglądnij jeszcze raz before_filter itp., bo zachowanie aplikacji na to by wskazywało.

@post.comments.build @post.comments.count # => 0 @post.comments.any? # => true

[quote=wlodi]pewnie

<%= form_for [@post, Comment.new] do |f| %>

[/quote]
A ta linijka nie tworzy czasem komentarza do posta?

Osobiście preferowałbym:

[code]<%= form_for Comment.new do |f| %>

<%= f.hidden_field :post_id, @post.id %>[/code]

Faktycznie, ciężko wyjaśnić to dziwne zachowanie inaczej niż sugerowałem ja i ddknapik. Ale odwoływanie się w widokach bezpośrednio do modelu jest mało eleganckie. wlodi, spróbuj przerobić to tak jak proponowałem kilka postów wyżej, problem powinien się rozwiązać (uwaga na kolejność ustawiania tych zmiennych, jest ważna).

OK, dzieki wielke za sugestie. Poprawie to i moze problem sie rozwiaze.

Hej,

poprawilem metode show w kontrolerze post na:

[code]before_action :find_post, only: [:show]

def show
@comments = @post.comments
@comment = Comment.new(post: @post)
end

private

def find_post
@post = Post.find(params[:id])
end[/code]
formularz:

[code]

Leave a Comment:

<%= form_for [@post, @comment] do |f| %>
<%= f.label :commenter %>
<%= f.text_field :commenter, class: "form-control" %>
<%= f.label :email %>
<%= f.text_field :email, class: "form-control" %>
<%= f.label :website %>
<%= f.text_field :website, class: "form-control" %>
<%= f.label :body %>
<%= f.text_area :body, class: "form-control" %>

<%= f.submit 'Submit', :class => "btn btn-primary" %>

<% end %>
[/code]

I działa chociaż teraz dobrze? :smiley:

Tak, i nie mam pustego komentarza w widoku :slight_smile: