Sessions

I’m trying to make it so each user can only vote once. By making an if
statement in the view that looks at the boolean of session[:voted] and
then decides weather to display the content. However, the problem is the
boolean resets itself every time it reloads the show action. How do I
fix this?

def show
@school = School.find(params[:id])
@courses = Course.find_all_by_school_id(params[:id])

session[:voted] = false

respond_to do |format|
  format.html # show.html.erb
  format.xml  { render :xml => @school }
end

end

def mark_one
@school = School.find(params[:id])
@school.update_attribute :rating_sum, @school.rating_sum += 1
@school.update_attribute :rating_num, @school.rating_num += 1
session[:voted] = true

respond_to do |format|
  if @school.save
    flash[:notice] = 'School was successfully rated.'
    format.html { redirect_to school_url(@school) }
    format.xml  { head :created, :location => school_url(@school) }
  else
    format.html { redirect_to school_url(@school) }
    format.xml  { render :xml => @school.errors.to_xml }
  end
end

end

Try session[:voted] ||= false

This will only set voted to false if voted is not set.

Ok, that worked great thanks. However, there is more than one School in
my collection. Changing session[:voted] affects how it behaves for all
schools. How do I make it specific to each school?

Ryan wrote:

Try session[:voted] ||= false

This will only set voted to false if voted is not set.

Here’s where it gets tricky.

People can clear sessions and then vote more than once for schools. The
Large Majority ™ don’t know how to do that, but we have to be careful
for
The Large Minority ™ that can teach them how to!

You can either:

Store it as a session variable:

session[:voted] ||= {}
session[:voted][@school.id] = true

Or store it as a table, which is so messy I would rather you do it in a
session variable.

On Dec 5, 2007 1:38 PM, Ellis B. [email protected]
wrote:


Posted via http://www.ruby-forum.com/.


Ryan B.

Yes.

You might want to put:

session[:voted] ||= {}

Somewhere were it will always be set.

On Dec 5, 2007 2:44 PM, Ellis B. [email protected]
wrote:

Would this make going directly to /schools/1/mark_rating_as_one come up
as an error because the session hash is not instantiated?

Posted via http://www.ruby-forum.com/.


Ryan B.

Would this make going directly to /schools/1/mark_rating_as_one come up
as an error because the session hash is not instantiated?

<% if session[:voted][:school_id] == false %>
<%= link_to “1”, mark_one_school_path(@school), :method => :put %>
<%= link_to “2”, mark_two_school_path(@school), :method => :put %>
<%= link_to “3”, mark_three_school_path(@school), :method => :put %>
<%= link_to “4”, mark_four_school_path(@school), :method => :put %>
<%= link_to “5”, mark_five_school_path(@school), :method => :put %>
<% end %>

is my view

def show
session[:voted] ||= {}
session[:voted][@school.id] = false

end

def mark_as_one
session[:voted][@school.id] = true

end

This does not work.

It is actually a very big design issue that there be no users. What
other solutions are we looking at?

Do users log into your site? Perhaps it would be better to store it in a
votes table with just two fields, a school_id and a user_id. That way we
don’t get the nasty session hash errors when the hash isn’t defined.

school.rb:

has_many :votes

user.rb

belongs_to :vote

Then you should be able to go

<% if current_user.vote.nil? %>

instead of relying on the unreliable session.

On Dec 5, 2007 2:59 PM, Ellis B. [email protected]
wrote:

This does not work.

Posted via http://www.ruby-forum.com/.


Ryan B.

instead of storing user_ids store IP addresses. This is easier to
maintain
as you really only have to define one relationship (the one on the
school).
You have two fields in the votes table still, school_id and ip_address.
To
get an IP address you can do request.remote_addr.

On Dec 5, 2007 3:07 PM, Ellis B. [email protected]
wrote:

It is actually a very big design issue that there be no users. What
other solutions are we looking at?

Posted via http://www.ruby-forum.com/.


Ryan B.

Is this as concise as I can get it?

def mark_five
Vote.create(:school_id => @school.id, :ip_address =>
request.remote_addr)

end

def show
@school = School.find(params[:id])
@course = Course.new
@courses = Course.find_all_by_school_id(params[:id])
@votes = Vote.find_all_by_school_id(params[:id])
@vote = false

for vote in @votes
  if vote.ip_address == request.remote_addr
    @vote = true
    break
  else
    @vote = false
  end
end

end

<% if @vote = false %>

Everything up to the for seems good.

The for could be improved right down to one line.

@vote = Vote.find_all_by_school_id(params[:id]).detect { |v|
v.ip_address ==
request.remote_addr }

Here, @vote will either be nil (indicating no vote), or the first (and
hopefully only) vote object it comes across matching that IP address.

Your if statement should check to see:

<% if @vote.nil? %>

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs