How can I only display an add review form if a user hasn't already submited a review?
Hi I'm a super beginner and working on my first app, I have a table of venues and users can add reviews to the venues. I would like to be able to hide the review form to users once they have submitted a review, to stop them from submitting more.
This is what I have now:
add review form on venue show page
<% if reviewed? %>
<%= form_for [@venue, @review], :class => 'rating_ballot' do |f| %>
<%= f.label("value_1", content_tag(:span, '1'), {:class=>"rating", :id=>"1"}) %>
<%= radio_button_tag("review[rating]", 1, :class => 'rating_button') %>
<%= f.label("value_2", content_tag(:span, '2'), {:class=>"rating", :id=>"2"}) %>
<%= radio_button_tag("review[rating]", 2, :class => 'rating_button') %>
<%= f.label("value_3", content_tag(:span, '3'), {:class=>"rating", :id=>"3"}) %>
<%= radio_button_tag("review[rating]", 3, :class => 'rating_button') %>
<%= f.label("value_4", content_tag(:span, '4'), {:class=>"rating", :id=>"4"}) %>
<%= radio_button_tag("review[rating]", 4, :class => 'rating_button') %>
<%= f.label("value_5", content_tag(:span, '5'), {:class=>"rating", :id=>"5"}) %>
<%= radio_button_tag("review[rating]", 5, :class => 'rating_button') %> <br>
<p>title: <br>
<%= f.text_field :title %></p><br>
<%= submit_tag %>
<% end %>
<% end %>
application controller
class ApplicationController < ActionController::Base
helper :all # include all helpers, all the time
protect_from_forgery # See ActionController::RequestForgeryProtection for details
helper_method :reviewed?
protected
def reviewed?
true
end
private
def current_user
@current_user ||= User.find(session[:user_id]) if session[:user_id]
end
end
I cant figure out what the reviewed? helper should be to allow me to do this, any help is greatly appreciated!
edit
I've added the has_reviewed helper to the application controller, it now shows this error:
Called id for nil, which would mistakenly be 4 -- if you really wanted the id of nil, use object_id
Extracted source (around line #79):
76: <%= render :partial => 'reviews/review', :collection => @venue.reviews %>
77: </div>
78:
79: <% if reviewed? %>
application controller
class ApplicationController < ActionController::Base
helper :all # include all helpers, all the time
protect_from_forgery # See ActionController::RequestForgeryProtection for details
helper_method :current_user
helper_method :has_reviewed
helper_method :reviewed?
protected
def reviewed?
Review.has_reviewed(@current_user.id, venue.id)
end
def has_reviewed
!Review.where(:user_id=>user,:venue_id=>venue).blank?
end
private
def current_user
@current_user ||= User.find(session[:user_id]) if session[:user_id]
end
end
another edit
I've changed the reviewed? helper method to:
def reviewed?
if current_user
Review.has_reviewed(@current_user.id, @venue.id)
else
nil
end
end
but it gives undefined method `has_reviewed' for # error
schema
A venue has many reviews
A user has many reviews
A review开发者_如何转开发 belongs to a user and a venue
the routes looks like this:
App::Application.routes.draw do
resources :sessions
resources :users
resources :venues do
resources :reviews
end
end
Presuming you make the change as suggested by Wes, the reviewed?
method would look in the database to see if this user has made a review.
The reviews table will need to have a column for the user that made the review and the venue it reviewed.
So the code would look something like this...
EDITED to reflect schema recently added
In the controller
def reviewed?
if current_user
@current_user.has_reviewed(@venue.id)
else
nil
end
end
In the User model...
class User < ...
has_many :reviews
def has_reviewed(venueid)
reviews.exists?(:venue_id => venueid)
end
...
end
Basically I think the has_reviewed is better off in the User model as the user has_many reviews, and then it can check if the user has reviewed the given venue. I am presuming that the Model Review has a foreign key to venue called venue_id, as a Review belongs_to a Venue and that would be the standard thing.
<% unless reviewed? %>
[...]
<% end %>
精彩评论