Rails 3.1.3
I am making a simple site where people can share short stories and can rate those stories on a 5 Star rating system. The Star rating system is the problem. I can get it to work fine in the stories/show.html view, but not on the indexed home page. Here is my code:
home.html.erb
<% content_for(:scripts) do %>
<%= javascript_include_tag 'rating_ballot'%>
<% end %>
<div id="talesFeedHome">
<p class="notice"><%= notice %></p>
<%= render #tales.sort_by { |tale| tale.created_at }.reverse %>
</div>
<p class="clear"> </p>
tales/_tale.html.erb
<% if signed_in? %>
<div id="homeTales">
<ul>
<div id="taleShow">
<div id="controlPanel">
<li id="taleUserName"><%= tale.user.name %></li>
<li id="averageRating"> Your Rating:<br /><%= render "tales/stars" %></li>
</div>
<div id="taleDisplay">
<li><%= link_to(tale) do %>
<span><%= tale.title %> </span>
<span><%= tale.content %></span>
<% end %>
</li> <br />
</div>
</div>
</ul>
</div>
<% else %>
...
tales/_stars.html.erb
<div id="starRating">
<%= form_for(rating_ballot, :remote => true, :html => { :class => 'rating_ballot' }) do |f| %>
<%= f.label("value_1", content_tag(:span, '1'), {:class=>"rating", :id=>"1"}) %>
<%= radio_button_tag("rating[value]", 1, current_user_rating == 1, :class => 'rating_button') %>
<%= f.label("value_2", content_tag(:span, '2'), {:class=>"rating", :id=>"2"}) %>
<%= radio_button_tag("rating[value]", 2, current_user_rating == 2, :class => 'rating_button') %>
<%= f.label("value_3", content_tag(:span, '3'), {:class=>"rating", :id=>"3"}) %>
<%= radio_button_tag("rating[value]", 3, current_user_rating == 3, :class => 'rating_button') %>
<%= f.label("value_4", content_tag(:span, '4'), {:class=>"rating", :id=>"4"}) %>
<%= radio_button_tag("rating[value]", 4, current_user_rating == 4, :class => 'rating_button') %>
<%= f.label("value_5", content_tag(:span, '5'), {:class=>"rating", :id=>"5"}) %>
<%= radio_button_tag("rating[value]", 5, current_user_rating == 5, :class => 'rating_button') %>
<%= hidden_field_tag(:tale_id, #tale.id) %>
<% end %>
</div>
It is at this point, in the hidden field tag, that I get this error:
Called id for nil, which would mistakenly be 4 -- if you really wanted the id of nil, use object_id
Here are the 3 relevant controllers:
pages_controller.rb
class PagesController < ApplicationController
def home
#tales = Tale.all
end
end
tales_controller.rb
class TalesController < ApplicationController
respond_to :html, :js
def new
#tale = Tale.new
end
def show
#tale = Tale.find(params[:id])
end
def index
#tales = Tale.all
#tale = Tale.find(params[:id])
end
...
ratings_controller.rb
class RatingsController < ApplicationController
before_filter :authenticate_user!
respond_to :html, :js
def create
#tale = Tale.find_by_id(params[:tale_id])
#rating = Rating.new(params[:rating])
#rating.tale_id = #tale.id
#rating.user_id = current_user.id
if #rating.save
respond_to do |format|
format.html { redirect_to #tale, :notice => "Your rating has been saved" }
format.js
end
end
end
def update
#rating = current_user.ratings.find_by_tale_id(params[:tale_id])
#tale = #rating.tale
if #tale and #rating.update_attributes(params[:rating])
respond_to do |format|
format.html { redirect_to #tale, :notice => "Your rating has been updated" }
format.js
end
end
end
end
The problem is here somewhere. Somehow when rendering #tales on the home page, this invalidates the #tale.id on the _stars partial. I can not figure out how to solve this. Thank You.
ok, I think your value of #tales is nil so please do the following things and let me know what would be the result
first put raise #tales.Inspect in your home method in your PagesController
second <%= raise tale.inspect%> in _tale.html.erb.
want to check weather value of tale is null or not.
Related
I'm newbee in rails, so could you explain why method survey_type works for this (attempts/new):
<h2 class="survey-title">
<%= #survey.name %>
<p><small><%= #attempt.survey.description %></small></p>
</h2>
<%= form_for(#attempt, url: attempt_scope(#attempt)) do |f| %>
<%= hidden_field_tag :survey_id, #survey.id %>
<ol class="questions">
<% if is_multanswer?(#survey.survey_type) %>
<%= f.fields_for :answers, get_answer_fields(#attempt) do |answer_fields| %>
<li>
<% question = answer_fields.object.question %>
<p class="question"><%= question.text %></p>
<ul class="options">
<%= collection_check_boxes('survey_attempt[answers_attributes]', question.id, question.options, :id, :text) do |b| %>
<li class="checkbox">
<%= b.label { b.check_box + b.text } %>
</li>
<% end %>
</ul>
</li>
<% end -%>
<% else %>
<%= f.fields_for :answers, get_answer_fields(#attempt) do |answer_fields| %>
<li>
<% question = answer_fields.object.question %>
<p class="question"><%= question.text %></p>
<ul class="options">
<%= collection_radio_buttons('survey_attempt[answers_attributes]', question.id, question.options, :id, :text) do |b| %>
<li class="radio">
<%= b.label { b.radio_button + b.text } %>
</li>
<% end %>
</ul>
</li>
<% end -%>
<% end %>
</ol>
<%= f.submit "Submit", class: 'btn btn-default' %>
<% end -%>
and do not work for this (attempts/show):
<div class="container">
<h2 class="survey-title">
<%= #attempt.survey.name %>
<p><small><%= #attempt.survey.description %></small></p>
</h2>
<ol class="questions">
<% if is_multanswer?(#survey.survey_type) %>
<% #attempt.answers.each do |answer| %>
<li>
<p class="question"> <%= answer.question.text %> </p>
<ul class="options">
<% answer.question.options.each do |option| %>
<li class="checkbox">
<label>
<%= check_box_tag '', '', the_chosen_one?(answer, option), disabled: true %>
<% color = get_color_of_option(answer, option) %>
<span class="<%= color %> <%= the_chosen_one?(answer, option) %>"> <%= option.text %> <%= get_weight(option) %> </span>
</label>
<p class="answers-number"> <%= number_of_people_who_also_answered(option.id) %> </p>
</li>
<% end %>
</ul>
</li>
<% end %>
<% else %>
<% #attempt.answers.each do |answer| %>
<li>
<p class="question"> <%= answer.question.text %> </p>
<ul class="options">
<% answer.question.options.each do |option| %>
<li class="radio">
<label>
<%= radio_button_tag '', '', the_chosen_one?(answer, option), disabled: true %>
<% color = get_color_of_option(answer, option) %>
<span class="<%= color %> <%= the_chosen_one?(answer, option) %>"> <%= option.text %> <%= get_weight(option) %> </span>
</label>
<p class="answers-number"> <%= number_of_people_who_also_answered(option.id) %> </p>
</li>
<% end %>
</ul>
</li>
<% end %>
<% end %>
here is controllers:
attempts_controller
class AttemptsController < ApplicationController
helper 'surveys'
before_filter :load_survey, only: [:new, :create]
def index
#surveys = Survey::Survey.active
end
def show
#attempt = Survey::Attempt.find_by(id: params[:id])
render :access_error if current_user.id != #attempt.participant_id
end
def new
#participant = current_user
unless #survey.nil?
#attempt = #survey.attempts.new
#attempt.answers.build
end
end
def create
#attempt = #survey.attempts.new(params_whitelist)
#attempt.participant = current_user
if #attempt.valid? && #attempt.save
correct_options_text = #survey.correct_options.present? ? 'Bellow are the correct answers marked in green' : ''
redirect_to attempt_path(#attempt.id), notice: "Thank you for answering #{#survey.name}! #{correct_options_text}"
else
build_flash(#attempt)
#participant = current_user
render :new
end
end
def delete_user_attempts
Survey::Attempt.where(participant_id: params[:user_id], survey_id: params[:survey_id]).destroy_all
redirect_to new_attempt_path(survey_id: params[:survey_id])
end
private
def load_survey
#survey = Survey::Survey.find_by(id: params[:survey_id])
end
def params_whitelist
if params[:survey_attempt]
params[:survey_attempt][:answers_attributes] = params[:survey_attempt][:answers_attributes].map { |attrs| { question_id: attrs.first, option_id: attrs.last } }
params.require(:survey_attempt).permit(Survey::Attempt::AccessibleAttributes)
end
end
def current_user
view_context.current_user
end
end
and surveys_controller:
class SurveysController < ApplicationController
before_filter :load_survey, only: [:show, :edit, :update, :destroy]
def index
type = view_context.get_survey_type(params[:type])
query = if type then Survey::Survey.where(survey_type: type) else Survey::Survey end
#surveys = query.order(created_at: :desc).page(params[:page]).per(15)
end
def new
#survey = Survey::Survey.new(survey_type: view_context.get_survey_type(params[:type]))
end
def create
#survey = Survey::Survey.new(params_whitelist)
if #survey.valid? && #survey.save
default_redirect
else
build_flash(#survey)
render :new
end
end
def edit
end
def show
end
def update
if #survey.update_attributes(params_whitelist)
default_redirect
else
build_flash(#survey)
render :edit
end
end
def destroy
#survey.destroy
default_redirect
end
private
def default_redirect
redirect_to surveys_path, notice: I18n.t("surveys_controller.#{action_name}")
end
def load_survey
#survey = Survey::Survey.find(params[:id])
end
def params_whitelist
params.require(:survey_survey).permit(Survey::Survey::AccessibleAttributes << :survey_type)
end
end
and helpers:
def get_color_of_option answer, option
if is_quiz?(answer.question.survey.survey_type)
if option.correct
'bg-success'
elsif the_chosen_one?(answer, option)
'bg-danger'
end
elsif is_score?(answer.question.survey.survey_type)
get_weight_html_class option
end
end
def get_survey_type survey_type
get_survey_types[survey_type] || get_survey_types.invert[survey_type]
end
def get_survey_types
{ 0 => 'quiz',
1 => 'score',
2 => 'poll',
3 => 'multanswer'
}
end
def is_quiz? something
something == 0 || something == 'quiz'
end
def is_score? something
something == 1 || something == 'score'
end
def is_poll? something
something == 2 || something == 'poll'
end
def is_multanswer? something
something == 3 || something == 'multanswer'
end
Thanks in advance!
In your AttemptsController you have
before_filter :load_survey, only: [:new, :create]
that sets the #survey variable for your new action, but doesn't get called for show, so that action never gets the variable set.
You can add :show into your :only conditions
before_filter :load_survey, only: [:new, :create, :show]
and that should fix things
I am able to post an event but when I select the user to post as, the dropdown menu shows empty spaces where the user (venue name) should be. I have tried everything that I can think of. Any ideas would be greatly appreciated.
I am on rails 4. I am using devise as well.
here are my files:
show.html.erb:
<p id="notice"><%= notice %></p>
<p>
<b>Name:</b>
<%= #gig.user.venue_name %>
</p>
<p>
<strong>Event:</strong>
<%= #gig.event %>
</p>
<p>
<strong>Date:</strong>
<%= #gig.date %>
</p>
<p>
<strong>Doors:</strong>
<%= #gig.doors %>
</p>
<p>
<strong>Showtime:</strong>
<%= #gig.showtime %>
</p>
<p>
<strong>Age:</strong>
<%= #gig.age %>
</p>
<p>
<strong>Price:</strong>
<%= #gig.price %>
</p>
<p>
<strong>Description:</strong>
<%= #gig.description %>
</p>
<%= link_to 'Edit', edit_gig_path(#gig) %> |
<%= link_to 'Back', gigs_path %>
index.html.erb:
<p id="notice"><%= notice %></p>
<div class="page-header">
<h1>All Gigs</h1>
</div>
<% #gigs.each do |gig| %>
<div class="gig">
<strong><%= gig.user.venue_name %></strong>
<p><%= gig.event %></p>
<p><%= gig.date %></p>
<p><%= gig.doors %></p>
<p><%= gig.showtime %></p>
<p><%= gig.age %></p>
<p><%= gig.price %></p>
<p><%= gig.description %></p>
<div class="meta">
<%= link_to time_ago_in_words(gig.created_at) + " ago", gig %>
<span class="admin">
| <%= link_to 'Edit', edit_gig_path(gig) %> |
<%= link_to 'Delete', gig, method: :delete, data: { confirm: 'Are you sure?' } %>
</span>
</div>
</div>
<% end %>
</tbody>
</table>
gig.rb:
class Gig < ActiveRecord::Base
belongs_to :user
end
user.rb:
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :gigs
end
_form.html.erb:
<%= simple_form_for(#gig, html: {class: "form-horizontal"}) do |f| %>
<% if #gig.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#gig.errors.count, "error") %> prohibited this gig from being saved:</h2>
<ul>
<% #gig.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<%= f.input :user_id, collection: User.all, label_method: :venue_name %>
<%= f.input :event %>
<%= f.input :date %>
<%= f.input :doors %>
<%= f.input :showtime %>
<%= f.input :age %>
<%= f.input :price %>
<%= f.input :description %>
<div class="form-actions">
<%= f.button :submit %>
</div>
db migrate add user id to gig
class AddUserIdToGigs < ActiveRecord::Migration
def change
add_column :gigs, :user_id, :integer
add_index :gigs, :user_id
remove_column :gigs, :name
end
end
gigs_controller.rb
class GigsController < ApplicationController
before_action :set_gig, only: [:show, :edit, :update, :destroy]
# GET /gigs
# GET /gigs.json
def index
#gigs = Gig.all
end
# GET /gigs/1
# GET /gigs/1.json
def show
end
# GET /gigs/new
def new
#gig = Gig.new
end
# GET /gigs/1/edit
def edit
end
# POST /gigs
# POST /gigs.json
def create
#gig = Gig.new(gig_params)
respond_to do |format|
if #gig.save
format.html { redirect_to #gig, notice: 'Gig was successfully created.' }
format.json { render :show, status: :created, location: #gig }
else
format.html { render :new }
format.json { render json: #gig.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /gigs/1
# PATCH/PUT /gigs/1.json
def update
respond_to do |format|
if #gig.update(gig_params)
format.html { redirect_to #gig, notice: 'Gig was successfully updated.' }
format.json { render :show, status: :ok, location: #gig }
else
format.html { render :edit }
format.json { render json: #gig.errors, status: :unprocessable_entity }
end
end
end
# DELETE /gigs/1
# DELETE /gigs/1.json
def destroy
#gig.destroy
respond_to do |format|
format.html { redirect_to gigs_url, notice: 'Gig was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_gig
#gig = Gig.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def gig_params
params.require(:gig).permit(:name, :event, :date, :doors, :showtime, :age, :price, :description, :user_id)
end
end
Solved it:
After running irb, I noticed that venues was null in the db. Therefore, I realized that I had to as venues in devise by creating new forms.
Question: How to access hidden field value post_id from file view/comments/_comment.html.erb and use it in controllers/dashboards_controller.rb?
- there are 2 controllers - dashboard and comments, and using gem act_as_commentable_with_threading
Now I get: ActiveRecord::RecordNotFound in DashboardsController#index Couldn't find Post without an ID
config/routes.rb
resources :comments, :only => [:create, :destroy]
controllers/dashboards_controller.rb
class DashboardsController < ApplicationController
def index
#post = Post.new
#user = current_user
#newest_users = User.newest_players
#feed_posts = Post.paginate(:page => params[:page], :per_page => 8)
#last_clubs = Club.last_clubs
#commented_post = Post.find(params[:post_id])
# trying to access params from view/comments/_comment.html.erb
# comments is another controller...
# do other operations with #commented_post
#comments = #commented_post.comment_threads.order('created_at desc')
#new_comment = Comment.build_from(#commented_post, current_user, '')
end
end
view/comments/_comment.html.erb
Add comment
place for a comment form
<div class="comment-form">
<%= form_for :comment, :remote => true do |f| %>
<%=f.hidden_field 'post_id', post.id %>
# need to use this value in dasboard controller
<%=f.text_field :body %>
<% end %>
</div>
view/dashboards/_feed_post.html.erb
<ul class="post-items">
<%if #feed_posts.any? %>
<% #feed_posts.each do |post| %>
<li>
<span class="image"><%= image_tag post.image.url(:message) if post.image?%></span>
<span class="content"><%= post.text_html %></span>
<span class="tags">Tags:<%= post.tag_list %></span>
<span class="meta">
Posted <%= time_ago_in_words(post.created_at) %> ago.
| <%= post.user.full_name %>
</span>
<%= render 'comments/form' ,:locals => { :comment => #new_comment, :post_id => post.id } %>
<%= render 'comments/comment', :collection => #comments, :as => :comment, :post_id => post.id %>
</li>
<% end %>
<% end %>
</ul>
view/dashboards/index
<div class="row">
<div class="span7">
<!--form for creating a new post-->
<section>
<%= render :template => 'posts/new' %>
</section>
<!--dashboard feed_post-->
<section>
<%= render :partial => 'dashboards/feed_post' %>
</section>
</div>
you are using f.hidden_field so you will get
<%=f.hidden_field 'post_id', post.id %>
will create following html ref hidden_field
<input type="hidden" id="comment_post_id" name="comment[post_id]" value="#{comment.post_id}" />
so you can access this as following in your controller
params[:comment][:post_id]
so use following instead
#commented_post = Post.find(params[:comment][:post_id])
if you want 'post_id' in params[:post_id] use hidden_field_tag like following
<%= hidden_field_tag 'post_id', post.id %>
I am passing a collection (#feed_items) to a _feed_item partial via the :collection option and converting it to dailypost with :as => :dailypost.
Inside the _feed_item partial I rendered another partial for _like_button, and i used :locals to continue using dailypost.
Everything works fine with the database. Likes get added and taken out :) BUT
I am trying to use (AJAX) to create.js.erb & destroy.js.erb the like button.
For some reason only the top post gets updated correctly and i have to refresh the page to see the ones below it.
I know the solution involves assigning a unique post id to each "like" element, say "like-123", but that is where i am stuck.......
I also know that the problem may be in _feed_items.html.erb because i am passing two ids....any suggestions??
Views
_feed.html.erb
<% if #feed_items.any? %>
<ol>
<%= render partial: 'shared/feed_item', collection: #feed_items, :as => :dailypost %>
</ol>
<% end %>
_feed_items.html.erb
<li id="<%= #dailypost.id %>">
<span class="user">
<%= link_to dailypost.user.name, dailypost.user %>
<span class="content"><%= dailypost.content_html %></span>
<div id="like">
<%= render :partial => 'likes/like_button', :locals =>{:dailypost => dailypost} %>
</div>
</li>
_like_button.html.erb
<% if like = current_user.likes.find_by_dailypost_id(dailypost.id) %>
<%= form_for like, :html => { :method => :delete }, :remote => true do |f| %>
<%= f.submit "Unlike" %>
<% end %>
<% else %>
<%= form_for current_user.likes.build, :remote => true do |f| %>
<div><%= f.hidden_field :dailypost_id, value: dailypost.id %></div>
<%= f.hidden_field :user_id %>
<%= f.submit "Like" %>
<% end %>
<% end %>
create.js.erb
$("#like").html("<%= escape_javascript(render :partial => 'like_button', :locals => {:dailypost => #dailypost}) %>");
destroy.js.erb
$("#like").html("<%= escape_javascript(render :partial => 'like_button', :locals => {:dailypost => #dailypost}) %>");
Controller
class LikesController < ApplicationController
respond_to :html, :js
def create
#like = Like.create(params[:like])
#dailypost = #like.dailypost
respond_to do |format|
format.js
format.html { redirect_to :back }
end
end
def destroy
like = Like.find(params[:id]).destroy
#dailypost = like.dailypost
respond_to do |format|
format.js
format.html { redirect_to :back }
end
end
end
Hmmm.Replace the first-line in _feed_items.html.erb with this.
<li id="dailypost<%= dailypost.id %>">
and In create.js.erb and destroy.js.erb, make changes
$("#like").html(...)
To
$("#dailypost<%= dailypost.id%> #like").html(...)
This should Work.
I', working on a Ruby On Rails App, and I am getting the following error when I attempt to call the Save method from Active Record to populate a new link to the database. This is code that goes wrong, its in the Create method in my LinksController class:
def create
#link = Link.new(params[:link])
respond_to do |format|
if #product.save
format.html { render :action => "create" }
format.json { render :json => #link }
else
format.html { render :action => "new" }
format.json { render :json => #product.errors, :status => :unprocessable_entity }
end
end
end
When I go to
http://localhost:3000/links/new
And attempt to create a new link with this form:
<%= form_for(#link) do |f| %>
<% if #link.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#link.errors.count, "error") %> prohibited this link from being saved:</h2>
<ul>
<% #link.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :title %><br />
<%= f.text_field :title %>
</div>
<div class="field">
<%= f.label :url %><br />
<%= f.text_field :url %>
</div>
<div class="actions">
<%= f.submit %>
</div>
and click submit, I get the following error:
undefined method `save' for nil:NilClass
I have no idea what is going on, so if anyone has an answer, or even pointers, I would really appreciate it. Thanks.
#link = Link.new(params[:link])
respond_to do |format|
if #product.save
so where did #productcome from?