undefined method `hirahana_value' for nil:NilClass - ruby-on-rails

I try to understand what my buddy has coded to call in a show#view some instance variable. I have a problem to understand his code and call the method hirahana_value.
Here is my controller
class SymbolesController < ApplicationController
before_action :set_symbole, only: [:show, :edit, :update, :destroy, :load_form, :load_attributes_form]
def index
#symboles = Symbole.all
end
def show
end
def new
#symbole = Symbole.new
end
def edit
end
def create
#symbole = Symbole.new()
if symbole_params[:symbole_type].present?
#symbole.build_kanji_attribute if symbole_params[:symbole_type] == "kanji"
#symbole.build_hiragana_and_katagana_attribute if symbole_params[:symbole_type] == "hiragana_and_katagana"
end
#symbole.assign_attributes(symbole_params)
respond_to do |format|
if #symbole.save
format.html { redirect_to #symbole, notice: 'Symbole was successfully created.' }
format.json { render :show, status: :created, location: #symbole }
else
format.html { render :new }
format.json { render json: #symbole.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #symbole.update(symbole_params)
format.html { redirect_to #symbole, notice: 'Symbole was successfully updated.' }
format.json { render :show, status: :ok, location: #symbole }
else
format.html { render :edit }
format.json { render json: #symbole.errors, status: :unprocessable_entity }
end
end
end
def destroy
#symbole.destroy
respond_to do |format|
format.html { redirect_to symboles_url, notice: 'Symbole was successfully destroyed.' }
format.json { head :no_content }
end
end
def load_form
#symbole = Symbole.new if #symbole.nil?
if params[:form_name].present?
respond_to do |format|
format.js { render "ajax_form_"+params[:form_name] }
end
end
end
def load_attributes_form
#symbole = Symbole.new if #symbole.nil?
if params[:form_name].present?
respond_to do |format|
format.js { render "ajax_form_"+params[:form_name] }
end
end
end
private
def set_symbole
if params[:id].present?
#symbole = Symbole.find(params[:id])
else
#symbole = Symbole.new
end
end
def symbole_params
params.require(:symbole).permit(:lang, :example_fr, :symbole_type, :css_class, kanji_attribute_attributes: [:value,:concept, :fr],
hiragana_and_katagana_attribute_attributes: [:hirahana_value,:katagana_value, :fr]
)
end
end
And here is the new#view to create my object
<%= simple_form_for #symbole, :defaults => {:required => true} do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<%= f.hidden_field :lang, value: "Japonais"%>
<%= f.select :symbole_type, options_for_select([["Kanji", "kanji"], ["Hiragana/Katagana", "hiragana_and_katagana"]]) , {:prompt => "Type de symbole", selected: #symbole.symbole_type}, {required: true} %>
<div id="specific_attributes">
</div>
<%= f.input :example_fr, placeholder: "Exemple", label: "Exemple" %>
<%= f.input :css_class, placeholder: "Nom de la classe css" , label: "Classe"%>
</div>
<div class="form-actions">
<%= f.button :submit, "Valider" %>
</div>
<% end %>
here is the show#view, I just want to call
<ul class="list-inline text-center card-frame">
<li>
<div class="card">
<div class="front">
<!-- PARAMETRER LE RESPONSIVE BOOTSTRAP -->
<!-- <div class="col-sm- col-xs-4 col-md-3"> -->
<div class="card-hiragana hiragana-<%=#hiragana_and_katagana_attributes.hirahana_value.downcase.last%>">
<h1><b><%= #hiragana_and_katagana_attributes.hirahana_value %></b></h1>
</div>
<div class="card-katakana">
<p><%= #hiragana_and_katagana_attributes.hirahana_value %></p>
</div>
<!-- </div> -->
</div>
<div class="back">
<div class="col-sm-3 col-xs-4 col-md-3 containerbackcards-<%=#hiragana_and_katagana_attributes.hirahana_value.downcase.last%>">
<div class="backcard-hiragana">
<h1><b><%= #hiragana_and_katagana_attributes.hirahana_value %></b></h1>
</div>
<div class="card-bigletter">
<p><%= #hiragana_and_katagana_attributes.hirahana_value %></p>
</div>
</div>
</div>
</div>
</li>
</ul>
<div class="text-center buttons-view-post">
<% if current_user.try(:admin?) %>
<%= link_to "Modifier l'hiragana", edit_hiragana_path(#hiragana), class: "btn btn-default btn-md" %>
<% end %>
<%= link_to "Voir tous les hiraganas", hiraganas_path, class: "btn btn-default btn-md" %>
</div>
</div>
</div>
</div>
</div>

The controller instance variable #hiragana_and_katagana_attributes has not been given a value within the context of the #show action, at least not in a way that's immediately visible. Wherever you are expecting this object to get instantiated, that's not happening.

Related

Undefined method `errors' for nil:NilClass - when I click on Form Submit

I have added validation to the form FORM. So whenever I click on the create employee with all the details it works but when I do not put the values I get this error. I have even changed to #employee in form_with.
I just want validations to be seen. How do I handle this?
Employees Controller:
class EmployeesController < ApplicationController
before_action :set_employee, only: %i[ show edit update destroy]
# GET /employees or /employees.json
def index
#employees = Employee.all
end
# GET /employees/1 or /employees/1.json
def show
end
# GET /employees/new
def new
#employee = Employee.new
end
# GET /employees/1/edit
def edit
end
# POST /employees or /employees.json
def create
employee_service = EmployeeCreationService.new(employee_params)
respond_to do |format|
if employee_service.execute!
format.html { redirect_to employee_service.employee}
# format.json { render :show, status: :created, location: #employee }
else
format.html { render :new, status: :unprocessable_entity }
# format.json { render json: #employee.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /employees/1 or /employees/1.json
def update
respond_to do |format|
if #employee.update(employee_params)
format.html { redirect_to #employee}
# format.json { render :show, status: :ok, location: #employee }
else
format.html { render :edit, status: :unprocessable_entity }
# format.json { render json: #employee.errors, status: :unprocessable_entity }
end
end
end
# DELETE /employees/1 or /employees/1.json
def destroy
#employee.destroy
respond_to do |format|
format.html { redirect_to employees_url}
# format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_employee
#employee = Employee.find(params[:id])
end
# Only allow a list of trusted parameters through.
def employee_params
params.require(:employee).permit(:name, :phone, :designation_id, :email, :password)
end
end
Form:
<%= form_with(model: employee, local: true) do |form| %>
<% if employee.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(employee.errors.count, "error") %> prohibited this employee from being saved:</h2>
<ul>
<% employee.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="form-group row">
<%= form.label :name,class:"col-sm-2 col-form-label" %>
<div class="col-sm-10">
<%= form.text_field :name %>
</div>
</div>
<div class="form-group row">
<%= form.label :phone,class:"col-sm-2 col-form-label" %>
<div class="col-sm-10">
<%= form.text_field :phone %>
</div>
</div>
<div class="form-group row">
<%= form.label :designation_id,class:"col-sm-2 col-form-label" %>
<div class="col-sm-10">
<%= form.select :designation_id, [["SOFTWARE ENGINEER", "2"], ["SERVICE ENGINEER", "3"]] %>
</div>
</div>
<div class="form-group row">
<%= form.label :Email,class:"col-sm-2 col-form-label" %>
<div class="col-sm-10">
<%= email_field_tag 'employee[email]' %>
</div>
</div>
<div class="form-group row">
<%= form.label :Password,class:"col-sm-2 col-form-label" %>
<div class="col-sm-10">
<%= password_field_tag 'employee[password]' %>
</div>
</div>
<br />
<div class='form-group'>
<div class="align-left">
<h5 align="left">
<%= form.submit class:"btn btn-dark"%>
</h5></button>
</div>
<div class="align">
<div >
<%= link_to 'Go Back', employees_path , class:"btn btn-primary btn-sm"%>
</div>
</div>
</div>
<% end %>
Service - to create employee and User simultaneously(Using Devise):
class EmployeeCreationService
attr_reader :employee
def initialize(employee_params)
#employee_params = employee_params.except(:email, :password)
#user_params = employee_params.slice(:email, :password)
end
def execute!
begin
#employee = Employee.create!(#employee_params)
User.create!(#user_params.merge(employee: employee))
rescue => exception
#ex = exception
return false
end
true
end
end
I suppose the problem in the create action in else branch of condition:
The form needs that #employee variable should be set but it isn't for this case.
You need to have the ability to have an instance of the Employee class from your service. Something like this:
#employee = employee_service.execute!
if #employee.valid?
redirect_to
else
render
def create
#employee = Employee.new(employee_valid)
employee_service = EmployeeCreationService.new(employee_params)
respond_to do |format|
if employee_service.execute!
format.html { redirect_to employee_service.employee}
else
format.html { render :new, status: :unprocessable_entity }
end
end
end
Made these changes and it works fine now. For the validations, I have added JS.
Also slice employeee params with only the name phone and designation.

Rails app - extra record displaying

I have an app that allows users to add albums they like to a database. Anyone can then come along and write a review for that album. Pretty simple.
I am running into a problem where an extra record appears to be created for the reviews on each album's show page. Every album, even if it has not ever been reviewed, has an additional, seemingly empty review being displayed when I use .each to display each review in the album show page. I want to get rid of that.
Here is an image of the problem. I have used CSS to highlight reviews in red. As you can see, there is an empty review at the bottom. When I inspect the review in question, it's raty title is "Not reviewed yet!"
Here is my albums_controller:
class AlbumsController < ApplicationController
before_action :set_album, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!, only: [:edit, :new, :update, :destroy]
def index
#albums = Album.all
if params[:search].nil?
#albums = Album.all.order(year: :desc).order(title: :asc).paginate(:page => params[:page], :per_page => 24)
else
#albums = #albums.where("albums.title || albums.year || albums.artist LIKE ?", "%#{params[:search]}%").order(year: :desc).order(title: :asc).paginate(:page => params[:page], :per_page => 24)
end
end
def show
if #album.reviews.blank?
#average_review = 0
else
#average_review = #album.reviews.average(:rating).round(2)
end
#review = #album.reviews.build
end
def new
#album = Album.new
end
def edit
end
def create
#album = current_user.albums.build(album_params)
respond_to do |format|
if #album.save
format.html { redirect_to #album, notice: 'Album was successfully created.' }
format.json { render :show, status: :created, location: #album }
else
format.html { render :new }
format.json { render json: #album.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #album.update(album_params)
format.html { redirect_to #album, notice: 'Album was successfully updated.' }
format.json { render :show, status: :ok, location: #album }
else
format.html { render :edit }
format.json { render json: #album.errors, status: :unprocessable_entity }
end
end
end
def destroy
#album.destroy
respond_to do |format|
format.html { redirect_to albums_url, notice: 'Album was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_album
#album = Album.find(params[:id])
end
def album_params
params.require(:album).permit(:title, :artist, :year, :cover)
end
end
Here is the album show page, which is where the extra review is being displayed:
<div class="row">
<div class="col-xs-10 col-md-6 col-md-push-3 col-xs-push-1 top bottom">
<%= image_tag #album.cover, class: 'show_image' %>
<h2><%= #album.title %></h2>
<h4><%= #album.artist %></h4>
<h5><%= #album.year %></h5>
<p class="white">Average Review<div class="average-review-rating" data-score=<%= #average_review %>></div></p>
<% if user_signed_in? %>
<% if #album.user_id == current_user.id %>
<%= link_to 'Edit', edit_album_path(#album), class: 'grey' %>
| <%= link_to 'Delete', album_path, method: :delete, data: {confirm: "Are you sure?"}, class: 'grey' %>
<% end %>
<% end %>
<br /><br />
<h4>Reviews</h4>
<% if user_signed_in? %>
<p class="grey">Write a review</p>
<%= form_for [#album, #review] do |r| %>
<div class="form-group">
<div id="rating-form">
<label>Rating</label>
</div>
</div>
<div class="form-group">
<%= r.text_area :comment, class: 'form-control', placeholder: "Write a comment" %>
</div>
<div class="form-group">
<%= r.submit "Create", class: 'btn btn-success' %>
</div>
<% end %>
<% end %>
<br />
<% #album.reviews.each do |r| %>
<div class="red">
<div class="review-rating" data-number="<%= r.rating %>">
</div>
<p class="white"><%= r.comment %></p>
<% if user_signed_in? %>
<% if current_user.id == r.user_id %>
<%= link_to 'Edit', edit_album_review_path(#album, r.id), class: 'grey' %> |
<%= link_to 'Delete', album_review_path(#album, r.id), method: :delete, data: {confirm: "Are you sure?"}, class: 'grey' %>
<% end %>
<% end %>
<br /><br />
</div>
<% end %>
</div>
</div>
<script>
$('.review-rating').raty({
readOnly: true,
score: function() {
return $(this).attr('data-number');
},
path: '/assets/'
});
$('#rating-form').raty({
path: '/assets/',
scoreName: 'review[rating]'
});
$('.average-review-rating').raty({
readOnly: true,
path: '/assets/',
score: function() {
return $(this).attr('data-score')
}
});
</script>
Any help would be very appreciated!
The problem here is on the last line of your show method: #review = #album.reviews.build. This line not only creates a new Review instance and assigns it to #review, but it also adds that instance to the array in #album.reviews. So, in your view, when you iterate over #album.reviews, you will see all of the persisted reviews as well as the one new, not persisted review that was built with build.
The easiest way to fix this would be to add this line in your view:
<% #album.reviews.each do |r| %>
<% next unless r.persisted? %>
Another solution would be to associate the new review with the album, but not on the #album instance. In the controller:
#review = Review.new(album: #album)
I think it could be because of last line in show.
#review = #album.reviews.build
It builds an empty review.

Flash messages (ajax)

Is it possible to show the errors of the form in the flash messages in ajax? I want to show the errors of the form when is not possible to save a record due to unique field.
my index
<!--<p id="notice"><%= notice %></p>-->
<h1>Empresas</h1>
<style>
.container {
}
</style>
<div class="container">
<div class="row">
<div class="text-center">
<!-- Button trigger modal -->
<button type="button" class="btn btn-primary btn-lg" data-toggle="modal" data-target="#mynewempresa">
Nueva empresa
</button>
</div>
</div>
<br>
<br>
<table id="empresas" class="display"><!--el id empresas es de datatables referenciado en empresas.coffe y display class es una clase de datatables-->
<thead>
<tr><!--active es para sombrear la fila-->
<th>Clave</th>
<th>Empresa</th>
<th>Acción</th>
<th></th>
</tr>
</thead>
<tbody id="container_empresas">
<%= render #empresas %><!--carga todos los empresas-->
</tbody>
</table>
<!-- Modal create action -->
<%= form_for(#empresa, remote: true, html: {class: "form-horizontal formulario-validado-create"}) do |f| %> <!--ajax remote: true-->
<div class="modal fade" id="mynewempresa" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="myModalLabel">Agregar empresa</h4>
</div>
<div class="modal-body">
<div id="flash_messages_placeholder" >
</div>
<div class="form-group">
<%= f.label :IdEmpresa, "Clave:", class: "control-label col-md-2 " %>
<div class="col-md-3">
<%= f.text_field :IdEmpresa, class: "form-control empresa_clave",autofocus: true, minlength: "1", required: "true" %>
</div>
<%= f.label :Empresa, "Empresa:", class: "control-label col-md-2" %>
<div class="col-md-5">
<%= f.text_field :Empresa, class: "form-control empresa_empresa",minlength: "4", required: "true" %>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal" id="mynewempresaclose">Cerrar</button>
<%= submit_tag "Crear", class: "btn btn-primary"%>
</div>
</div>
</div>
</div>
<%end%>
</div>
my controller
class EmpresasController < ApplicationController
before_action :set_empresa, only: [:show, :edit, :update, :destroy]
before_action :authenticate_usuario!
# GET /empresas
# GET /empresas.json
def index
#empresas = Empresa.all
#empresa = Empresa.new
respond_to do |format|
format.html
format.csv { send_data #empresas.to_csv}
format.xls #{ send_data #empresas.to_csv(col_sep: "\t") }
end
end
def import
Empresa.import(params[:file])
redirect_to empresas_path, notice: "Sucursales importadas."
end
# GET /empresas/1
# GET /empresas/1.json
def show
end
# GET /empresas/new
def new
#empresa = Empresa.new
end
# GET /empresas/1/edit
def edit
end
# POST /empresas
# POST /empresas.json
def create
#empresa = Empresa.new(empresa_params)
format.js { render 'shared/error_messages_js'}
respond_to do |format|
if #empresa.save
format.html { redirect_to #empresa, notice: 'Empresa was successfully created.' }
format.json { render :show, status: :created, location: #empresa }
format.js {flash.now[:notice] = 'La Sucursal se ha creado de forma exitosa.'} #ajax
else
format.html { render :new }
format.json { render json: #empresa.errors, status: :unprocessable_entity }
format.js {flash.now[:alert] = 'Error al crear la sucursal.'} #ajax
end
end
end
# PATCH/PUT /empresas/1
# PATCH/PUT /empresas/1.json
def update
respond_to do |format|
##use locals if multiple models
##add model errors
flash.now[:error] = #empresa.errors.full_messages
##flash.now[:error] = #model.errors.full_messages.to_sentence
if #empresa.update(empresa_params)
format.html { redirect_to #empresa, notice: 'Empresa was successfully updated.' }
format.json { render :show, status: :ok, location: #empresa }
format.js {flash.now[:notice] = 'La Sucursal se ha actualizado de forma exitosa.'} #ajax
else
format.html { render :edit }
format.json { render json: #empresa.errors, status: :unprocessable_entity }
format.js {flash.now[:alert] = 'Error al actualizar la sucursal.'} #ajax
end
end
end
# DELETE /empresas/1
# DELETE /empresas/1.json
def destroy
#empresa.destroy
respond_to do |format|
format.html { redirect_to empresas_url, notice: 'Empresa was successfully destroyed.' }
format.json { head :no_content }
format.js {flash.now[:notice] = 'La Sucursal se ha borrado de forma exitosa.'} #ajax
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_empresa
#empresa = Empresa.find(params[:idempresa])
end
# Never trust parameters from the scary internet, only allow the white list through.
def empresa_params
params.require(:empresa).permit(:IdEmpresa, :Empresa)
end
end
my application helper:
module ApplicationHelper
###application_helper.rb
def flash_display
Rails.logger.info "show flash message ajax======== "
response = ""
flash.each do |name, msg|
msg=msg ###"<i class='fa fa-quote-left fa-border'></i>"+msg+"<i class='fa fa-quote-right fa-border'></i>"+"<button type='button' class='close' title='hide' data-dismiss='alert'><i class='fa-times-circle-o fa pull-right'></i></button>".html_safe
response = response +
content_tag(:div, msg, :id => "flash_#{name}",:class=>"alert alert-danger") do
"#{msg}".html_safe
end
end
flash.discard
response
end
end
##views/shared/error_messages_js.erb
$('#flash_messages_placeholder').html("<%= escape_javascript raw(flash_display) %>");
Yes..its possible..
firstly,create a helper method that can be used to show flash messages on the view.
###application_helper.rb
def flash_display
Rails.logger.info "show flash message ajax======== "
response = ""
flash.each do |name, msg|
msg=msg ###"<i class='fa fa-quote-left fa-border'></i>"+msg+"<i class='fa fa-quote-right fa-border'></i>"+"<button type='button' class='close' title='hide' data-dismiss='alert'><i class='fa-times-circle-o fa pull-right'></i></button>".html_safe
response = response +
content_tag(:div, msg, :id => "flash_#{name}",:class=>"alert alert-danger") do
"#{msg}".html_safe
end
end
flash.discard
response
end
Secondly,In your controller code where you post data using remote=true,handle js response as shown below.
respond_to do |format|
##use locals if multiple models
##add model errors
##flash.now[:error] = #model.errors.full_messages
##flash.now[:error] = #model.errors.full_messages.to_sentence
flash.now[:error]="You cannot edit this Page"
format.js { render 'shared/error_messages_js'}
end
##views/shared/error_messages_js.erb
$('#flash_messages_placeholder').html("<%= escape_javascript raw(flash_display) %>");
So,the above js.erb file will look for an empty placeholder to show flash messages.So your form must also have a placeholder
###_form.html.erb
<form action="<%= post_data_path(current_user)%>" method="post" data-remote="true">
<div id="flash_messages_placeholder" > </div>
##input fields/submit button goes here
<%end%>
Hope it helps :)

how to get hanzq/youtube_addy gem working?

So, I have a rails app that allows users to submit youtube links and rank the songs/links using the thumbs up gem.
However, users must physically copy and paste the link into the browser to listen to the song after the link is uploaded. For a better UX I'm going to use this gem to dynamically embed the YouTube video into my app once the users upload the link.
However, I'm not quite sure how this can be done?
I was thinkin' of doing something like this in the index:
<%= YouTubeAddy.extract_video_id('song.url)' %> <%= YouTubeAddy.youtube_embed_url('song.url') %> ?
or would it have to be in the controller? and if so how?
song#new.html.erb:
<%= form_for #song, :html => { :multipart => true } do |f| %>
<% if #song.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#song.errors.count, "error") %> prohibited this song from being saved:</h2>
<ul>
<% #song.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="row">
<div class="large-6 columns">
<div class="field">
<%= f.label :title %>
<%= f.text_field :title %>
</div>
<div class="field">
<%= f.label 'website url' %>
<%= f.text_area :url %>
</div>
<div class="field">
<%= f.label :tag_list, "Genres (separated by commas)" %><br />
<%= f.text_field :tag_list %>
</div>
<p>
<%= f.file_field :track%>
</p>
<div class="actions">
<%= f.submit value: "Upload" %>
</div>
<% end %>
</div>
song_controller.rb
class SongsController < ApplicationController
before_filter :authenticate_user!, only: [:create ,:edit, :update, :destroy, :vote_for_song]
before_action :set_song, only: [:show, :edit, :update, :destroy, :vote_for_song]
def vote_for
#song = Song.find(params[:id])
current_user.vote_for(#song)
#song.plusminus = #song.votes_for
#song.save
respond_to do |format|
format.js { render 'update_votes' }
end
end
def vote_against
#song = Song.find(params[:id])
current_user.vote_against(#song)
respond_to do |format|
format.js { render 'update_votes' }
end
end
def new_songs
#songs = Song.order "id DESC"
end
# GET /Songs
# GET /Songs.json
def index
if params[:genre]
#songs = Song.tagged_with(params[:genre]).paginate(:page => params[:page], :per_page => 15)
else
#songs = Song.order('plusminus').paginate(:page => params[:page], :per_page => 15)
end
end
# GET /Songs/1
# GET /Songs/1.json
def show
#comment = Comment.new(song: #song)
end
# GET /Songs/new
def new
#song = Song.new
end
# GET /Songs/1/edit
def edit
end
# POST /Songs
# POST /Songs.json
def create
#song = Song.new(song_params)
respond_to do |format|
if #song.save
format.html { redirect_to #song, notice: 'Song was successfully created.' }
format.json { render action: 'show', status: :created, location: #song }
else
format.html { render action: 'new' }
format.json { render json: #song.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /Songs/1
# PATCH/PUT /Songs/1.json
def update
respond_to do |format|
if #song.update(song_params)
format.html { redirect_to #song, notice: 'Song was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #song.errors, status: :unprocessable_entity }
end
end
end
# Song /Songs/1
# Song /Songs/1.json
def destroy
#song.destroy
respond_to do |format|
format.html { redirect_to songs_url }
format.json { head :no_content }
end
end
private
def set_song
#song = Song.find(params[:id])
end
def song_params
params.require(:song).permit(:title, :artist, :url, :track, :user_id, :tag_list)
end
end
index.html.erb
<h6>Top ranked songs</h6>
<hr>
<ol><% #songs.each do |song| %>
<span class="title">
<li><%=link_to image_tag('thumbs.png', size: '16x50'), vote_for_song_path(song), :remote => true, :method => :put %> <%= link_to song.title, song %><span class="subtext"> (<%= song.url %>)<br></li></span>
<%#=link_to '&#9660'.html_safe, vote_against_song_path(song), :remote => true, :method => :put %>
<span class="subtext"><span class="votes_<%= song.id %>"><%= pluralize(song.votes.count, 'like') %>,</span>
posted <%= time_ago_in_words(song.created_at) + " ago" %>
<small><span class="comments"></small> | <%= pluralize(song.comments.size, 'comment') %></span></small><br /></span>
<%#= link_to 'Show', song, class: "button small secondary" %>
<%= link_to('Edit', edit_song_path(song), class: "button small secondary") if can? :update, song %>
<%= link_to('Destroy', song, method: :delete, data: {confirm: 'Are you sure?'}, class: "button small secondary") if can? :destroy, song %>
<% end %>
</ol>
<div class="pagination-centered">
<ul class="pagination">
<%#= will_paginate #songs %>
<!-- or custom pagination -->
<% if #songs.previous_page %>
<%= link_to "Back", params.merge(page: #songs.previous_page) %>
<% end %>
<% if #songs.next_page %>
<%= link_to "More", params.merge(page: #songs.next_page) %>
<% end %>
</ul></div>
YouTubeAddy.youtube_embed_url('song.url') generates a string of iframe tag, so it should be used in your view exactly where you want an embedded video to be placed. But note that you should return an html safe string. So in your view you have:
<%=raw YouTubeAddy.youtube_embed_url('song.url') %>
More about unescaping html.

SyntaxError in SongsController#index

Not sure why I seem to be getting this error as I have the appropriate amount of ends. The app was working - and then I installed devise and it went to hell. I un-installed devise to go back to the working version but now I seem to be getting the error shown below.
Error msg
SyntaxError in SongsController#index
/Users/user/Sites/leap2/leap2/app/controllers/songs_controller.rb:13: syntax error, unexpected end-of-input, expecting keyword_end
Songs_controller.rb
class SongsController < ApplicationController
before_action :set_song, only: [:show, :edit, :update, :destroy]
def index
#songs = Song.all
end
def new
#song = Song.new
end
def show
end
def edit
end
def create
#song = Song.new(song_params)
respond_to do |format|
if #song.save
format.html { redirect_to #song, notice: 'Song was added successully'}
format.json {render action: 'show', status: :created, location: #song}
else
format.html { render action: 'new' }
format.json { render json: #song.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #song.update(song_params)
format.html {redirect_to #song, notice: 'Song was successfully updated.' }
format.json {head :no_content }
else
format.html {render action: 'edit' }
format.json {render json: #song.errors, status: :unprocessible_entity }
end
end
end
def destroy
#song.destroy
respond_to do |format|
format.html { redirect_to songs_url }
format.json { head :no_content }
end
end
private
def set_song
#song = Song.find(params[:id])
end
def song_params
params.require(:song).permit(:title, :artist, :bio, :track)
end
end
show.html.erb
<p id="notice"><%= notice %>
<p>
<strong>Title:</strong>
<%= #song.title %>
</p>
<p>
<strong>Bio:</strong>
<%= #song.bio %>
</p>
<p>
<strong>Audio:</strong>
<%= audio_tag (#song.track.url), controls: "controls" %>
</p>
<br /><br />
<%= link_to 'Edit', edit_song_path(#song), class: "button small secondary"%>
<%= link_to 'Back', songs_path, class: "button small secondary" %>
_form.html_erb
<%= form_for #song, :html => { :multipart => true } do |f| %>
<% if #song.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#song.errors.count, "error") %> prohibited this song from being saved:</h2>
<ul>
<% #song.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="row">
<div class="large-6 columns">
<div class="field">
<%= f.label :title %>
<%= f.text_field :title %>
</div>
<div class="field">
<%= f.label :bio %>
<%= f.text_area :bio %>
</div>
<p>
<%= f.file_field :track%>
</p>
<div class="actions">
<%= f.submit value: "Upload" %>
</div>
<% end %>
</div>
<div class="large-6 columns"><h3>Submit your own song or a personal favourite and watch it climb the charts! </h3>
</div>
</div>
in application_controller.rb you had one extra end.
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
def authorize
redirect_to new_user_session_path, notice: "You have to be logged in to submit."
if current_user.nil?
end
end
end

Resources