partial won't render in rails - ruby-on-rails

My partial, which is located in views/votes/_voter.html.erb, is not rendering in the browser and not triggering any errors when I place the rendering code in the answers/show.html.erb file. I've already combed through all of the questions and answers related to partials in rails on SO, and can't find anything exactly related to what is happening here. If anyone can help shed any light on the problem, I'd really appreciate it!
answers/show.html.erb file:
<p id="notice"><%= notice %></p>
<%= render partial: 'votes/voter', locals: { answer: #answer } %>
<p>
<strong>Body:</strong>
<%= #answer.body %>
</p>
<%= link_to 'Edit', edit_answer_path(#answer) %> |
<%= link_to 'Back', answers_path %>
views/votes/_voter.html.erb file:
<% if policy( Vote.new ).create? %>
<div class="vote-arrows pull-left">
<div>
<%= link_to " ",
post_up_vote_path(answer),
class: "glyphicon glyphicon-chevron-up #{(current_user.voted(answer) && current_user.voted(answer).up_vote?) ? 'voted' : '' }", method: :post %>
</div>
<div>
<strong><%= answer.points %></strong>
</div>
<div>
<%= link_to " ",
post_down_vote_path(answer),
class: "glyphicon glyphicon-chevron-down #{(current_user.voted(answer) && current_user.voted(answer).down_vote?) ? 'voted' : '' }" , method: :post%>
</div>
</div>
<% end %>
votes_controller.rb:
class VotesController < ApplicationController
before_action :load_answer_and_vote
def up_vote
if #vote
#vote.update_attribute(:value, 1)
else
#vote = current_user.votes.create(value: 1, answer: #answer)
end
redirect_to :back
end
def down_vote
if #vote
#vote.update_attribute(:value, -1)
else
#vote = current_user.votes.create(value: -1, answer: #answer)
end
redirect_to :back
end
private
def load_answer_and_vote
#question = Question.find(params[:question_id])
#vote = #question.votes.where(user_id: current_user.id).first
end
def update_vote(new_value)
if #vote
authorize #vote, :update?
#vote.update_attribute(:value, new_value)
else
#vote = current_user.votes.build(value: new_value, answer: #answer)
authorize #vote, :create?
#vote.save
end
end
end
vote.rb model:
class Vote < ActiveRecord::Base
belongs_to :user
belongs_to :answer, dependent: :destroy
default_scope { order('created_at DESC') }
validates :user, presence: true
validates :answer, presence: true
validates :value, inclusion: { in: [-1, 1], message: "%{value} is not a valid vote." }
after_save :update_answer
def up_vote?
value == 1
end
def down_vote?
value == -1
end
private
def update_post
answer.update_rank
end
end
routes.rb
Languagecheck::Application.routes.draw do
devise_for :users
resources :users
resources :languages do
resources :questions, except: [:index] do
resources :answers
post '/up-vote' => 'votes#up_vote', as: :up_vote
post '/down-vote' => 'votes#down_vote', as: :down_vote
end
end
resources :questions, only: [:index, :new, :create]
get 'about' => 'welcome#about'
root to: 'welcome#index'
end

It looks like you need to be signed in to view the partial.
<% if policy( Vote.new ).create? %>
Do you need to be signed in to vote? Are you signed in? If you are not you wouldn't see this partial.
The other place to check is your vote authorization policies to ensure they are set up correctly.

It turned out that I needed to render the partial in the views/questions/show.html file. Here is what I did to get the desired outcome:
<h3>Question</h3>
<div class="row">
<div class="col-md-8">
<p><%= #question.body %></p>
<small>
<%= image_tag(#question.user.avatar.tiny.url) if #question.user.avatar? %>
submitted <%= time_ago_in_words(#question.created_at) %> ago by
<%= #question.user.name %>
</small>
</div>
<div class="col-md-4">
<% if policy(#question).edit? %>
<%= link_to "Edit Question", edit_language_question_path(#language, #question), class: 'btn btn-success' %>
<% end %>
</div>
</div>
<br/>
<h3>Answers</h3>
<% #question.answers.each do |answer| %>
<%= render partial: 'votes/voter', locals: { answer: #answer } %>
<div>
<h3>
<%= pluralize(#answer.points, 'point') %>
</h3>
<small>
<%= pluralize(#answer.up_votes, 'up vote') %>
<%= pluralize(#answer.down_votes, 'down vote') %>
</small>
</div>
<%= simple_format answer.body %>
<small>
<%= image_tag(answer.user.avatar.tiny.url) if answer.user.avatar? %>
submitted <%= time_ago_in_words(answer.created_at) %> ago by
<%= answer.user.name %>
</small>
<% end %>
<br/>
<h4>Add an Answer</h4>
<%= render "answers/form" %>

Related

Is it possible somehow to create the form for each patrial on the index page in Rails without javascript?

invites_controller.rb
def index
#invites = Invites.all
end
invite.rb
has_one :answer
answers_controller.rb
def new
#invite = Invite.find(params[:invite_id])
#answer = #invite.build_answer
end
def create
#invite = Invite.find(params[:invite_id])
#answer = #invite.create_answer
redirect_to :back
end
answer.rb
belongs_to :invite
routes.rb
resources :invites, only: [:index] do
resources :answers, only: [:new, :create]
end
Is it possible to create invites/index.html where for each line-item will be exist working form for answer without any javascript?
With some logic like this:
<% #invites.each do |i| %>
<%= form_for(i, i.build_answer) do |f| %>
<%= f.hidden_field :accept, value: true %>
<%= f.submit "accept" %>
<% end %>
<% end %>
What are the routing and the rendering of forms will be?
ps: I can solve my problem by creating accept column at Invite model and simply updating each line item like this
<% #invites.each do |i| %>
<%= form_for(i) do |f| %>
<%= f.hidden_field :accept, value: true %>
<%= f.submit "accept" %>
<% end %>
<% end %>
but interesting about other way))
Yes, you can achieve it as
<% #invites.each do |i| %>
<%= form_for([i,i.answer.build]) do |f| %>
<%= f.text_field :name_of_you_answer_field %>
<%= f.submit %>
<% end %>
<% end %>

Rails4: How to pass dynamic array from view to controller

I have a problem creating Vote which contains value of points that user decided to give for a candidate (Borda Count Method). Values are in number_fields and I want them to be saved in Vote objects.
In my case I am only able to get value from the last number_field and I have no idea how to fix it. Other values are being overwritten so I came up with idea to create an array of points which contains values taken from many number_field_tag and pass them from view to controller.
Something about survey structure:
There is a Surv (survey) which contains many Polls (questions).
One Poll contains many Vote Options.
There are also Votes which save votes of user.
OUTPUT from params
{"utf8"=>"✓", "poll"=>{"id"=>"11"}, "9"=>"17", "arr"=>"1212", "pnts"=>"", "10"=>"20", "11"=>"22", "commit"=>"Zagłosuj", "controller"=>"votes", "action"=>"create"}
VIEW:
show.html.erb
<p id="notice"><%= notice %></p>
<h2>Twoja ankieta:</h2>
<h1>
<%= #surv.topic %>
</h1>
<h2>
<%= election_type %>
</h2>
<%= render 'voting_form' %>
<%= link_to 'Edit', edit_surv_path(#surv) %> |
_voting_form.html.erb
<%= form_tag votes_path, method: :post, remote: true, id: 'voting_form' do %>
<% if #surv.votingtype == "default" %>
<%# here is unnecessary code ... %>
<% elsif #surv.votingtype == "bordy" %> <%# BORDY %>
<% #polls.each do |poll| %>
<h2><%= poll.topic %></h2>
<h2>POLL ID: <%= poll.id %></h2>
<%= hidden_field_tag 'poll[id]', poll.id %>
<%= arr = [] %>
<%= i = 0 %>
<% poll.vote_options.each do |option| %>
<div class="form-group">
<%= content_tag(:label) do %>
<div class="select">
<%= option.title %>
<%= radio_button_tag option.poll_id, option.id %>
<%# if selected then vote is created %>
<%= number_field_tag :point %>
<%#= arr << :point %>
<%= hidden_field_tag 'pnts', arr %>
<%# some tries to pass params %>
</div>
<% end %>
<%= visualize_votes_for option %>
</div>
<% end %>
<p><b>Głosów razem: <%= poll.votes_summary %></b></p>
<% end %>
<% if current_user && current_user.voted_for3?(#surv) %>
<p>Twój głos został DO ANKIETY został zapisany.</p>
<% else %>
<%= submit_tag 'Zagłosuj', class: 'btn btn-lg btn-primary' %>
<% end %>
<% end %>
<% end %>
CONTROLLER:
votes_controller.rb
class VotesController < ApplicationController
def create
#poll = Poll.find_by_id(params[:poll][:id])
#surv = Surv.find_by_id(#poll.surv_id)
puts "Surv id:"
puts #surv.id
#surv.polls.each do |p|
puts "Poll ID (poll voted)."
puts p.id
puts "Vote option ID (vote option voted)"
puts params[p.id.to_s]
#option = p.vote_options.find_by_id(params[p.id.to_s])
if p && !current_user.voted_for?(p)
#here i would like to grab params specially specified for each poll
#vote = #option.votes.create({user_id: current_user.id, points: params[:pnts]})
##vote = #option.votes.create({user_id: current_user.id, points: params[:point]})
puts 'POINTS'
puts params.inspect
else
render js: 'alert(\'Glosowales juz w tej ankiecie!\');'
return
end
# end
end
#surv.update_attribute(:actual_votes, #surv.actual_votes+1)
if (#surv.maximum_votes > 0 && #surv.actual_votes >= #surv.maximum_votes)
respond_to do |format|
format.html { redirect_to terminate_surv_path(#surv), notice: 'Ostatni głos został oddany' }
format.js {render inline: "location.reload();" }
end
end
end
def vote_params
params.require(:vote).permit(:points)
end
end
MODEL:
vote_option.rb
class VoteOption < ActiveRecord::Base
belongs_to :surv
accepts_nested_attributes_for :surv
belongs_to :poll
accepts_nested_attributes_for :poll
has_many :votes, dependent: :destroy
has_many :users, through: :votes
validates :title, presence: true
end
vote.rb
class Vote < ActiveRecord::Base
belongs_to :user
belongs_to :vote_option
end
def surv_params
params.require(:surv).permit(:topic, :votingtype,
polls_attributes: [:id, :topic, :endtime, :endontime, :_destroy,
vote_options_attributes: [:id, :title, :_destroy]
])
end
Please let me know if you need some additional code or informations to help me fix my problem. Thank you in advance

Rails 4 routing error with nested comments form using nested resources

I was following this tutorial http://www.sitepoint.com/nested-comments-rails/ to implement nested comments for an image board. It worked fine until I made "comments" belong to "boards" and then had to nest my routes.
Here are my routes:
Rails.application.routes.draw do
root "boards#index"
devise_for :users do
get '/users/sign_out' => 'devise/sessions#destroy'
end
resources :boards do
resources :comments
get '/comments/new/(:parent_id)', to: 'comments#new', as: :new_comment
get '/comments/(:parent_id)', to: 'comments#destroy', as: :delete_comment
get '/comments/edit/(:parent_id)', to: 'comments#edit', as: :edit_comment
end
end
Here is my form:
<%= form_for [#board, #comment] do |f| %>
<% if #comment.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#comment.errors.count, "error") %> prohibited this comment from being saved:</h2>
<ul>
<% #comment.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<%= f.hidden_field :parent_id %>
<div class="form-group">
<% if #comment.parent_id == nil %>
<%= f.label :title %>
<%= f.text_field :title, class: 'form-control' %>
<% else %>
<% nil %>
<% end %>
</div>
<div class="form-group">
<%= f.radio_button(:user_id, current_user.id) %>
<%= f.label(:user_id, "I want to post as myself") %>
<%= f.radio_button(:user_id, nil) %>
<%= f.label(:user_id, "I want to post anonymously") %>
</div>
<div class="form-group">
<%= f.label :content %>
<%= f.text_area :content, class: 'form-control', required: true %>
</div>
<div class="form-group">
<%= f.label :image %>
<%= f.file_field :image %>
</div>
<%= f.submit class: 'btn btn-primary' %>
<% end %>
And here is my controller:
class CommentsController < ApplicationController
def index
#comments = Comment.hash_tree
end
def new
#comment = Comment.new(parent_id: params[:parent_id])
end
def edit
#comment = Comment.find(params[:parent_id])
end
def create
if params[:comment][:parent_id].to_i > 0
parent = Comment.find_by_id(params[:comment].delete(:parent_id))
#comment = parent.children.build(comment_params)
else
#comment = Comment.new(comment_params)
end
if #comment.save
redirect_to root_url
else
render 'new'
end
end
def update
#comment = Comment.find(params[:id])
if #comment.update(comment_params)
redirect_to #comment
else
render 'edit'
end
end
def make_parent
#comment.parent_id = nil
#comment.save
end
def destroy
#comment = Comment.find(params[:parent_id])
#comment.destroy
respond_to do |format|
format.html { redirect_to comments_url }
end
authorize! :destroy, #comment
end
private
def comment_params
params.require(:comment).permit(:title, :content, :user_id, :image)
end
end
I've tried setting a custom route in the form, this gets the form to at least appear, however when you hit the submit button it returns 'No route matches [POST] "/boards/1/comments/new"'. If I got to the controller and then change the corresponding "get" to a "post" then it causes the form to just reappear after pressing submit and nothing is added to the database. I've also experimented with shallow nesting my routes as per my instructors advice but this didn't work.
Your association between boards and comments must be:
board.rb
has_many :comments
comment.rb
belongs_to :user
routes.rb
resources :boards do
resources :comments, only: [:new, :edit, :destroy]
end
this will create a route
new_board_comment GET /boards/:board_id/comments/new(.:format) comments#new
edit_board_comment GET /boards/:board_id/comments/:id/edit(.:format) comments#edit
board_comment DELETE /boards/:board_id/comments/:id(.:format) comments#destroy

How to resolve NoMethodError in ror version 4

When I clicked on "display your data" link it is showing me the following error.
Error:
NoMethodError in Users#show
Showing C:/Site/new/app/views/users/show.html.erb where line #10 raised:
undefined method `email' for #<User::ActiveRecord_Relation:0x2bd81e8>
My code snippets are given below.
views/users/index.html.erb
<h1>Choose your option</h1>
<%= link_to "Enter your data",users_new_path %>
<%= link_to "Display your data",users_show_path %>
views/users/new.html.erb
<h1>Enter your data here</h1>
<%= form_for #user,:url => {:action => 'create'} do |f| %>
<% if #user.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#user.errors.count, "error") %> prohibited this post from being saved:</h2>
<ul>
<% #user.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<%= f.text_field:name,placeholder:"Enter your name" %><br>
<%= f.email_field:email,placeholder:"Enter your email" %><br>
<%= f.text_field:message,placeholder:"Enter your message"%><br>
<%= f.submit "Submit" %>
<% end %>
views/users/show.html.erb
<h1>Display your data</h1>
<ul>
<li>
<p>
<strong>Name:</strong>
<%= #user.name %>
</p>
<p>
<strong>Email:</strong>
<%= #user.email %>
</p>
<p>
<strong>Message:</strong>
<%= #user.message %>
</p>
</li>
</ul>
<%= link_to "Edit",users_edit_path(:id => t.id) %><%= link_to "Delete",users_delete_path(:id => t.id),data: { confirm: 'Are you sure to delete it ?' } %>
<%= link_to "Back",users_index_path %>
controller/users_controller.rb
class UsersController < ApplicationController
def index
end
def new
#user=User.new
end
def create
#user=User.new(users_params)
if #user.save
flash[:notice]="Your data is saved succesfully"
flash[:color]="valid"
redirect_to :action => 'index'
else
flash[:alert]="You are entering wrong data"
flash[:color]="invalid"
render :new
end
end
def show
#user=User.all
end
def delete
#user=User.find(params[:id])
#user.delete
end
def edit
#edit=User.find(params[:id])
#user=User.new
end
def update
#user=User.find(params[:id])
if #user.update_attributes(update_params)
flash[:notice]="Your data has updated successfully"
flash[:color]="valid"
redirect_to :action => 'index'
else
flash[:alert]="Your data could not update..check it.."
flash[:color]="invalid"
render :edit
end
end
private
def users_params
params.require(:user).permit(:name, :email, :message,pets_attributes: [:name, :email,:message])
end
def update_params
params.require (:user).permit(:name,:email,:message,pets_attributes: [:name,:email,:message])
end
end
model/user.rb
class User < ActiveRecord::Base
has_many :pets
accepts_nested_attributes_for :pets
EMAIL_REGEX = /\A[A-Z0-9._%+-]+#[A-Z0-9.-]+\.[A-Z]{2,4}\z/i
validates :name, :presence => true,:length => { :minimum => 5 }
validates :email, :presence => true, :uniqueness => true, :format => EMAIL_REGEX
validates :message, :presence => true
end
You should fix your show action from:
def show
#user = User.all
end
to:
def show
#user = User.find(params[:id])
end
In show action, you have
#user = User.all
which assigns relation with all users to #user variable. That's why you have this error, because you can't query whole relation for email. You should have:
#user = User.find(params[:id])
User.find(params[:id]) returns single User instance.
def show
#user=User.all
end
This will return array of users instead of user, so in order to call email on it you have to iterate loop over it.
<% user in #users %> <!-- I have change #user to #users in show method -->
<h1>Display your data</h1>
<ul>
<li>
<p>
<strong>Name:</strong>
<%= user.name %>
</p>
<p>
<strong>Email:</strong>
<%= user.email %>
</p>
<p>
<strong>Message:</strong>
<%= user.message %>
</p>
</li>
</ul>
<%= link_to "Edit",users_edit_path(:id => t.id) %><%= link_to "Delete",users_delete_path(:id => t.id),data: { confirm: 'Are you sure to delete it ?' } %>
<%= link_to "Back",users_index_path %>
<% end %>
Or just change show method
#user = User.find(params[:id])
fix your show action.
replace
#user = User.all
with
#user = User.find(params[:id])

unable to create or update a belongs_to record in Rails 4

I'm new to Rails and struggling to get my belongs_to association right. I have an app where a painting belongs to an artist and an artist can have_many paintings. I can create and edit my paintings, however I can not edit or create artists except through the console. Through much Googling I feel I have got myself turned around. Any help would be much appreciated!
Here's my routes.rb file:
MuseumApp::Application.routes.draw do
resources :paintings
resources :paintings do
resources :artists
resources :museums
end
root 'paintings#index'
end
Here's my paintings Controller
def show
#painting = Painting.find params[:id]
end
def new
#painting = Painting.new
##artist = Artist.new
end
def create
safe_painting_params = params.require(:painting).permit(:title, :image)
#painting = Painting.new safe_painting_params
if #painting.save
redirect_to #painting
else
render :new
end
end
def destroy
#painting = Painting.find(params[:id])
#painting.destroy
redirect_to action: :index
end
def edit
#painting = Painting.find(params[:id])
end
def update
#painting = Painting.find(params[:id])
if #painting.update_attributes(params[:painting].permit(:title, :image)) #safe_params
redirect_to #painting
else
render :edit
end
end
Here's the form in my paintings view:
<%= form_for(#painting) do |f| %>
<fieldset>
<legend>painting</legend>
<div>
<%= f.label :title %>
<%= f.text_field :title %>
</div>
<div>
<%= f.label :image %>
<%= f.text_field :image %>
</div>
<%= form_for([#painting,#painting.create_artist]) do |f| %>
<div>
<%= f.label :Artist %>
<%= f.text_field :name %>
</div>
</fieldset>
<%= f.submit %>
<% end %>
<% end %>
Artists Controller:
class ArtistsController < ApplicationController
def index
#artists = Artist.all
#artists = params[:q] ? Artist.search_for(params[:q]) : Artist.all
end
def show
#artist = Artist.find params[:id]
end
def new
#artist = Artist.new
end
def create
#painting = Painting.find(params[:painting_id])
#artist = #painting.create_artist(artist_params)
redirect_to painting_path(#painting)
end
def destroy
#artist = Artist.find(params[:id])
#Artist.destroy
redirect_to action: :index
end
def edit
#artist = Artist.find(params[:id])
end
def update
#painting = Painting.find(params[:painting_id])
#artist = #artist.update_attributes(artist_params)
redirect_to painting_path(#painting)
end
end
private
def artist_params
params.require(:artist).permit(:name)
end
Index view:
<h1> Hello and Welcome to Museum App</h1>
<h3><%= link_to "+ Add To Your Collection", new_painting_artist_path %></h3>
<%= form_tag '/', method: :get do %>
<%= search_field_tag :q, params[:q] %>
<%= submit_tag "Search" %>
<% end %>
<br>
<div id="paintings">
<ul>
<% #paintings.each do |painting| %>
<li><%= link_to painting.title, {action: :show, id:painting.id} %> by <%= painting.artist_name %></li>
<div id = "img">
<br><%= link_to (image_tag painting.image), painting.image %><br>
</div>
<%= link_to "Edit", edit_painting_path(id: painting.id) %>
||
<%= link_to 'Destroy', {action: :destroy, id: painting.id},method: :delete, data: {confirm: 'Are you sure?'} %>
<% end %>
</ul>
</div>
In your case you should use accepts_nested_attributes_for and fields_for to achieve this.
Artist
has_many :paintings, :dependent => :destroy
accepts_nested_attributes_for :paintings
Painting
belongs_to :artist
And also you should try creating artist with paintings like this
form_for(#artist) do |f| %>
<fieldset>
<legend>Artist</legend>
<%= f.label :Artist %>
<%= f.text_field :name %>
<%= fields_for :paintings, #artist.paintings do |artist_paintings| %>
<%= artist_paintings.label :title %>
<%= artist_paintings.text_field :title %>
<%= artist_paintings.label :image %>
<%= artsist_paintings.text_field :image %>
</fieldset>
<%= f.submit %>
<% end %>
Note:
You should be having your Artist Controller with at least new,create,edit and update methods defined in it to achieve this.
Edit
Try the reverse
Artist
has_many :paintings, :dependent => :destroy
Painting
belongs_to :artist
accepts_nested_attributes_for :paintings
form_for(#painting) do |f| %>
<fieldset>
<legend>Painting</legend>
<%= f.label :title %>
<%= f.text_field :title %>
<%= f.label :image %>
<%= f.text_field :image %>
<%= fields_for :artists, #painting.artists do |ff| %>
<%= ff.label :Artist %>
<%= ff.text_field :name %>
</fieldset>
<%= f.submit %>
<% end %>
Put this form in paintings views.

Resources