CRUD db entity from other controller - ruby-on-rails

I want to create, edit and delete db entity from other controller than generated by scaffold. I want to have validation, create and deletion without redirection. I don't want to use generated controller because i want to create at least 2 types of entities from one controller.
For now i have create without redirect but i don't have notification about entity creation.
This controller should support crud operations:
class SmartHomeController < ApplicationController
layout 'smart_home'
def index
#name = 'Home';
end
def settings
#name = 'Settings';
#place = Place.new;
#all_places = Place.all;
respond_to do |format|
if #place.save
format.html { redirect_to #place, :notice => 'A was successfully created.' }
else
# render new with validation errors
format.html { render :action => "settings" }
end
end
end
end
scaffold generated controller:
class PlacesController < ApplicationController
before_action :set_place, only: [:show, :edit, :update, :destroy]
# GET /places
# GET /places.json
def index
#places = Place.all
end
# GET /places/1
# GET /places/1.json
def show
end
# GET /places/new
def new
#place = Place.new
end
# GET /places/1/edit
def edit
end
# POST /places
# POST /places.json
def create
#place = Place.new(place_params)
respond_to do |format|
if #place.save
format.html { redirect_to smart_home_settings_path, notice: 'Place was successfully created.' }
format.json { render :show, status: :created, location: #place }
else
format.html { render :new }
format.json { render json: #place.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /places/1
# PATCH/PUT /places/1.json
def update
respond_to do |format|
if #place.update(place_params)
format.html { redirect_to #place, notice: 'Place was successfully updated.' }
format.json { render :show, status: :ok, location: #place }
else
format.html { render :edit }
format.json { render json: #place.errors, status: :unprocessable_entity }
end
end
end
# DELETE /places/1
# DELETE /places/1.json
def destroy
#place.destroy
respond_to do |format|
format.html { redirect_to places_url, notice: 'Place was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_place
#place = Place.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def place_params
params.require(:place).permit(:name, :hw)
end
end
Could you guide me how to achieve that?
Edit. New code.
Page:
<div class="demo-cards mdl-cell mdl-cell--4-col mdl-cell--8-col-tablet mdl-grid mdl-grid--no-spacing"
style="width: 420px">
<div class="demo-updates mdl-card mdl-shadow--2dp mdl-cell mdl-cell--4-col mdl-cell--4-col-tablet mdl-cell--12-col-desktop">
<div class="mdl-card__title mdl-card--expand mdl-color--teal-300">
<h2 class="mdl-card__title-text">All places</h2>
</div>
<div class="mdl-card__supporting-text mdl-color-text--grey-600">
<ul class="demo-list-item mdl-list">
<% #all_places.each do |place| %>
<li class="mdl-list__item">
<span class="mdl-list__item-primary-content">
<%= place.name %>: <%= place.hw %> <%= link_to 'Destroy', place, controller: 'smart_home', action: 'delete_place', data: { confirm: 'Are you sure?' } %>
</span>
</li>
<% end %>
</ul>
</div>
</div>
</div>
<div class="demo-cards mdl-cell mdl-cell--4-col mdl-cell--8-col-tablet mdl-grid mdl-grid--no-spacing"
style="width: 420px">
<div class="demo-updates mdl-card mdl-shadow--2dp mdl-cell mdl-cell--4-col mdl-cell--4-col-tablet mdl-cell--12-col-desktop">
<div class="mdl-card__title mdl-card--expand mdl-color--teal-300">
<h2 class="mdl-card__title-text">Create place</h2>
</div>
<div class="mdl-card__supporting-text mdl-color-text--grey-600">
<table class="mdl-data-table mdl-js-data-table mdl-data-table--selectable mdl-shadow--2dp create-place-table">
<%= form_for #place, url: smart_home_create_path do |f| %>
<tr>
<td>
<div class="mdl-textfield mdl-js-textfield">
<%= f.label :name, 'Name', class: 'mdl-textfield__label' %>
<%= f.text_field :name, class: 'mdl-textfield__input' %>
</div>
</td>
</tr>
<tr>
<td>
<div class="mdl-textfield mdl-js-textfield">
<%= f.label :hw, class: 'mdl-textfield__label' %>
<%= f.text_field :hw, class: 'mdl-textfield__input' %>
</div>
</td>
</tr>
<tr>
<td>
<%= f.submit "Create", class: 'mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect' %>
</td>
</tr>
<% end %>
</table>
</div>
</div>
</div>
Controller:
class PlacesController < ApplicationController
before_action :set_place, only: [:show, :edit, :update, :destroy]
# GET /places
# GET /places.json
def index
#places = Place.all
end
# GET /places/1
# GET /places/1.json
def show
end
# GET /places/new
def new
#place = Place.new
end
# GET /places/1/edit
def edit
end
# POST /places
# POST /places.json
def create
#place = Place.new(place_params)
respond_to do |format|
if #place.save
format.html { redirect_to smart_home_settings_path, notice: 'Place was successfully created.' }
format.json { render :show, status: :created, location: #place }
else
format.html { render :new }
format.json { render json: #place.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /places/1
# PATCH/PUT /places/1.json
def update
respond_to do |format|
if #place.update(place_params)
format.html { redirect_to #place, notice: 'Place was successfully updated.' }
format.json { render :show, status: :ok, location: #place }
else
format.html { render :edit }
format.json { render json: #place.errors, status: :unprocessable_entity }
end
end
end
# DELETE /places/1
# DELETE /places/1.json
def destroy
#place.destroy
respond_to do |format|
format.html { redirect_to smart_home_settings_path, notice: 'Place was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_place
#place = Place.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def place_params
params.require(:place).permit(:name, :hw)
end
end
Deletion works but no confirm:
Page:
<%= link_to 'Destroy', delete_place_path(id: place.id), data: {:confirm => 'Are you sure?'}, :method => :delete %>
Controller:
def delete_place
place = Place.find(params[:id])
place.destroy
respond_to do |format|
format.html { redirect_to smart_home_settings_path, notice: 'Place was successfully destroyed.' }
format.json { head :no_content }
end
end
Routes:
get 'delete_place/:id' => 'smart_home#delete_place', as: :delete_place
Edit:
Javascript include was missed
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %>
<%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
<%= csrf_meta_tags %>

Related

Can't submit a Review into a Place - Rails Directory Website app

I am following a Rails tutorial where I have to create a directory website of places in which an user can submit a review.
Right now, here's the thing:
I can register an user and I am able to login. Once I am logged in, I also can create a new place into the database. I also can access the webpage of each place I have created.
I have a problem though. On each place page, I can't submit the review of the place.
All places have an address, a phone number, a website, a description and a map with the location of that place. On that same page I have a form to submit a review, however, once I click on the create review button nothing happens. I can't see the review on the page and when I go to the rails console I can definitely see that there's not a single review created.
Inside my app/views/reviews/_form.html.erb I have this code:
<div class="form-inputs">
<%= f.input :content, required: true %>
<%= f.hidden_field :place_id, required: true, value: #place_id %>
</div>
<div class="form-actions">
<%= f.button :submit %>
</div>
<% end %>
Inside my app/views/reviews/_review.html.erb I have this code:
<p>
<%= gravatar_tag review.user.email, size: 20 %><%= review.content %> by <%= review.user.name %>
</p>
Inside my app/views/places/show.html.erb I have this code:
<div class="row">
<div class="col-md-3">
<h3><%= #place.name %></h3>
<p><strong>Adress</strong><%= #place.address %></p>
<p><strong>Phone</strong><%= #place.phone %></p>
<p><strong>Website</strong><%= #place.website %></p>
<p><strong>Description</strong><%= #place.description %></p>
<div id="map-canvas" style = "width:230px; height:230px"></div>
</div>
<div class="col-md-9">
<h3>Reviews by People</h3>
<% if current_user %>
<h5>New Review</h5>
<%= render 'reviews/form' %>
<h5>All Reviews</h5>
<%= render #reviews %>
<% end %>
</div>
</div>
On my places_controller.rb I have:
class PlacesController < ApplicationController
before_action :authenticate_user!, only: [:new, :edit, :create, :update, :destroy]
before_action :set_place, only: [:show, :edit, :update, :destroy]
# GET /places
# GET /places.json
def index
#places = Place.all
end
# GET /places/1
# GET /places/1.json
def show
#reviews = #place.reviews
#review = Review.new
end
# GET /places/new
def new
#place = Place.new
end
# GET /places/1/edit
def edit
end
# POST /places
# POST /places.json
def create
#place = current_user.places.new(place_params)
respond_to do |format|
if #place.save
format.html { redirect_to #place, notice: 'Place was successfully created.' }
format.json { render :show, status: :created, location: #place }
else
format.html { render :new }
format.json { render json: #place.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /places/1
# PATCH/PUT /places/1.json
def update
respond_to do |format|
if #place.update(place_params)
format.html { redirect_to #place, notice: 'Place was successfully updated.' }
format.json { render :show, status: :ok, location: #place }
else
format.html { render :edit }
format.json { render json: #place.errors, status: :unprocessable_entity }
end
end
end
# DELETE /places/1
# DELETE /places/1.json
def destroy
#place.destroy
respond_to do |format|
format.html { redirect_to places_url, notice: 'Place was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_place
#place = Place.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def place_params
params.require(:place).permit(:name, :address, :description, :phone, :website)
end
end
Also, so far... here is my reviews.controller.rb code:
class ReviewsController <ApplicationController
before_action :authenticate_user!
before_action :set_review, only: [:edit, :update, :destroy]
def edit
end
def create
#review = current_user.reviews.new(review_params)
respond_to do |format|
if #review.save
format.html { redirect_to place_path(#review.place) , notice: 'Review was successfully created.' }
else
format.html { render :new }
end
end
end
def update
respond_to do |format|
if #review.update(review_params)
format.html { redirect_to place_path(#review.place), notice: 'Review was successfully updated.' }
else
format.html { render :edit }
end
end
end
def destroy
#review.destroy
respond_to do |format|
format.html { redirect_to place_path(#review.place), notice: 'Review was successfully destroyed.' }
end
end
private
def set_review
#review = Review.find(params[:id])
end
def review_params
params.require(:review).permit(:content, :place_id)
end
end
Any insight of why I can't save reviews of a place?
Your form should your form be like this:-
<div class="form-inputs">
<%= f.input :content, required: true %>
<%= f.hidden_field :place_id, required: true, value: #place.id %>
</div>
You are setting instance variable #place in controller. So you need to use #place.id in your rendered views. You have not set #place_id anywhere

How to show nested database

Hello I have a nested database "processing" which belongst to "shopping_process". However I want somehow to see the messages, which are saved in processing. How can I do that? If I go to http://localhost:3000/processings/index the Error: Couldn't find Processing with 'id'=index appears. Has somebody an idea?
processings_controller.rb
class ProcessingsController < ApplicationController
before_action :set_processing, only: [:show, :edit, :update, :destroy]
# GET /processings
# GET /processings.json
def index
#processings = Processing.all
end
# GET /processings/1
# GET /processings/1.json
def show
end
# GET /processings/new
def new
#processing = Processing.new
end
# GET /processings/1/edit
def edit
end
# POST /processings
# POST /processings.json
def create
#processing = Processing.new(processing_params)
respond_to do |format|
if #processing.save
format.html { redirect_to #processing, notice: 'Processing was successfully created.' }
format.json { render :show, status: :created, location: #processing }
else
format.html { render :new }
format.json { render json: #processing.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /processings/1
# PATCH/PUT /processings/1.json
def update
respond_to do |format|
if #processing.update(processing_params)
format.html { redirect_to #processing, notice: 'Processing was successfully updated.' }
format.json { render :show, status: :ok, location: #processing }
else
format.html { render :edit }
format.json { render json: #processing.errors, status: :unprocessable_entity }
end
end
end
# DELETE /processings/1
# DELETE /processings/1.json
def destroy
#processing.destroy
respond_to do |format|
format.html { redirect_to processings_url, notice: 'Processing was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_processing
#processing = Processing.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def processing_params
params.require(:processing).permit(:shopping_process_id, :shopping_list_id, :accepted, :responded, :message)
end
end
view/processings/index.html.erb
<p id="notice"><%= notice %></p>
<h1>Processings</h1>
<table>
<thead>
<tr>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% #Processing.all.each do |processing| %>
<tr>
<td><%= link_to 'Show', processing %></td>
<td><%= link_to 'Edit', edit_processing_path(processing) %></td>
<td><%= link_to 'Destroy', processing, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
</table>
<br>
<%= link_to 'New Processing', new_processing_path %>
models/processing.rb
class Processing < ApplicationRecord
# db associations
belongs_to :shopping_process
belongs_to :shopping_list
# validations
validates :shopping_list, :presence => true
end
Now here comes the code for the database "shopping_processes"
shopping_processes_controller.rb
class ShoppingProcessesController < ApplicationController
load_and_authorize_resource
layout 'shopping_process', only: [:shopper_show, :senior_show]
# GET /shopping_processes/1
# GET /shopping_processes/1.json
def show
end
# POST /shopping_processes
# POST /shopping_processes.json
def create
#shopping_process.status =nil
#shopping_process.processed = nil
puts params.inspect
respond_to do |format|
if #shopping_process.save
format.html { redirect_to #shopping_process, notice: 'Shopping process was successfully created.' }
format.json { render :show, status: :created, location: #shopping_process }
else
format.html { render :new }
format.json { render json: #shopping_process.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /shopping_processes/1
# PATCH/PUT /shopping_processes/1.json
def update
respond_to do |format|
if #shopping_process.update(shopping_process_params)
format.html { redirect_to #shopping_process, notice: 'Shopping process was successfully updated.' }
format.json { render :show, status: :ok, location: #shopping_process }
else
format.html { render :edit }
format.json { render json: #shopping_process.errors, status: :unprocessable_entity }
end
end
end
# DELETE /shopping_processes/1
# DELETE /shopping_processes/1.json
def destroy
#shopping_process.destroy
respond_to do |format|
format.html { redirect_to shopping_processes_url, notice: 'Shopping process was successfully destroyed.' }
format.json { head :no_content }
end
end
def shopper_show
#shopping_process = ShoppingProcess.find(params[:id])
#users = {}
first = true
#shopping_process.shopping_lists.each do |shopping_list|
user = shopping_list.user
#users[user.id] = {color: (first ? 'blue' : 'yellow'), name: user.firstname + ' ' + user.lastname}
first = false
end
end
def senior_show
#shopping_process = ShoppingProcess.find(params[:id])
#shopping_process.shopping_lists.each do |shopping_list|
#if shopping_list.user == current_user
# #shopping_list = shopping_list
#end
#shopping_list = shopping_list
#to show the correct shopping list uncomment the block above and remove the declartion underneath it
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_shopping_process
#shopping_process = ShoppingProcess.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def shopping_process_params
params.require(:shopping_process).permit(:user_id, :status, :appointed, :processed, :shopping_list_id, processings_attributes: [ :shopping_list_id, :message ])
end
end
views/shopping_processes/form.html.erb
<%= form_for(shopping_process) do |f| %>
<% if shopping_process.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(shopping_process.errors.count, "error") %> prohibited this shopping_process from being saved:</h2>
<ul>
<% shopping_process.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :appointed %>
<%= f.datetime_select :appointed %>
</div>
<div class="field">
<%= f.label :shopper %>
<%= f.text_field :user_id, value: current_user.id, :readonly => true%>
</div>
<div class="field">
<%= f.label :shopping_list_id %>
<%= f.select :shopping_list_id, ShoppingList.accessible_by(current_ability).map{ |sl| [sl.name, sl.id] } %>
</div>
<!-- SUB FORM FOR NESTED RESOURCE : PROCESSINGS -->
<%= f.fields_for :processings, #shopping_process.processings.build do |ff| %>
<div>
<%= ff.label :Begleiter %>
<%= ff.select :shopping_list_id, ShoppingList.all.map{ |sl| [sl.user.firstname, sl.id]} , {:prompt => true} %>
</div>
<div>
<%= ff.label :message %>
<%= ff.text_field :message%>
</div>
<% end %>
<!-- Submit-->
<div class="actions">
<%= f.submit %>
</div>
<% end %>

Action Controller Exception w/ building "Multiple files upload with nested resource using Paperclip in Rails"

I'm trying to implement this rails cook solution for multiple images found here and am having issues with an action controller exception. I'm sure it's something I have over looked.
Here are my .rb files:
class Picture < ActiveRecord::Base
belongs_to :gallery
has_attached_file :image,
:path => ":rails_root/public/images/:id/:filename",
:url => "/images/:id/:filename"
do_not_validate_attachment_file_type :image
end
class Gallery < ActiveRecord::Base
has_many :pictures, :dependent => :destroy
end
And my pictures controller
class PicturesController < ApplicationController
before_action :set_picture, only: [:show, :edit, :update, :destroy]
# GET /pictures
# GET /pictures.json
def index
#pictures = Picture.all
end
# GET /pictures/1
# GET /pictures/1.json
def show
end
# GET /pictures/new
def new
#picture = Picture.new
end
# GET /pictures/1/edit
def edit
end
# POST /pictures
# POST /pictures.json
def create
#picture = Picture.new(picture_params)
#document = Document.new(:name) # :name is a symbol, not
respond_to do |format|
if #picture.save
format.html { redirect_to #picture, notice: 'Picture was successfully created.' }
format.json { render :show, status: :created, location: #picture }
else
format.html { render :new }
format.json { render json: #picture.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /pictures/1
# PATCH/PUT /pictures/1.json
def update
respond_to do |format|
if #picture.update(picture_params)
format.html { redirect_to #picture, notice: 'Picture was successfully updated.' }
format.json { render :show, status: :ok, location: #picture }
else
format.html { render :edit }
format.json { render json: #picture.errors, status: :unprocessable_entity }
end
end
end
# DELETE /pictures/1
# DELETE /pictures/1.json
def destroy
#picture.destroy
respond_to do |format|
format.html { redirect_to pictures_url, notice: 'Picture was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_picture
#picture = Picture.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def picture_params
params[:picture]
end
end
And here is my form
<!-- app/views/galleries/_form.html.erb -->
<%= form_for #gallery, :html => { :class => 'form-horizontal', multipart: true } do |f| %>
<div class="control-group">
<%= f.label :name, :class => 'control-label' %>
<div class="controls">
<%= f.text_field :name, :class => 'text_field' %>
</div>
</div>
<div class="control-group">
<%= f.label :description, :class => 'control-label' %>
<div class="controls">
<%= f.text_field :description, :class => 'text_field' %>
</div>
</div>
<div class="control-group">
<%= f.label :pictures, :class => 'control-label' %>
<div class="controls">
<!-- The magic is coming ...look at my eyes....shazammmm -->
<!-- Use HTML5 multiple attribute to enable multiple selection
and pass back to controller all files as an array, ready
for paperclip!!
file_field_tag, since images is not a gallery attribute
-->
<%= file_field_tag "images[]", type: :file, multiple: true %>
</div>
</div>
<div class="form-actions">
<%= f.submit nil, :class => 'btn btn-primary' %>
<%= link_to t('.cancel', :default => t("helpers.links.cancel")),
galleries_path, :class => 'btn btn-mini' %>
</div>
<% end %>
And here is my gallery controller
class GalleriesController < ApplicationController
before_action :set_gallery, only: [:show, :edit, :update, :destroy]
# GET /galleries
# GET /galleries.json
def index
#galleries = Gallery.all
end
# GET /galleries/1
# GET /galleries/1.json
def show
end
# GET /galleries/new
def new
#gallery = Gallery.new
end
# GET /galleries/1/edit
def edit
end
# POST /galleries
# POST /galleries.json
def create
#gallery = Gallery.new(gallery_params)
respond_to do |format|
if #gallery.save
if params[:images]
#===== The magic is here ;)
params[:images].each { |image|
#gallery.pictures.create(image: image)
}
end
format.html { redirect_to #gallery, notice: 'Gallery was successfully created.' }
format.json { render json: #gallery, status: :created, location: #gallery }
else
format.html { render action: "new" }
format.json { render json: #gallery.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /galleries/1
# PATCH/PUT /galleries/1.json
def update
respond_to do |format|
if #gallery.update(gallery_params)
format.html { redirect_to #gallery, notice: 'Gallery was successfully updated.' }
format.json { render :show, status: :ok, location: #gallery }
else
format.html { render :edit }
format.json { render json: #gallery.errors, status: :unprocessable_entity }
end
end
end
# DELETE /galleries/1
# DELETE /galleries/1.json
def destroy
#gallery.destroy
respond_to do |format|
format.html { redirect_to galleries_url, notice: 'Gallery was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_gallery
#gallery = Gallery.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def gallery_params
params.require(:gallery).permit(:gallery_id, :picture)
end
end
And here is my error
Your picture_params method may be causing the problem. Try modifying it to use the following format:
def picture_params
params.require(:picture).permit(:whitelisted, :attributes, :placed, :here)
end
You can use this repo provided in the tutorial you're following as a reference.
An additional reference on strong parameters.
Hope it helps!

How to force rank songs by vote?

So, I have an app that allows users to up vote/like songs (using this gem). However, I'd like the songs with higher votes to be ranked up the list. As currently, they only appear in the order in which they were uploaded. How do I accomplish this?
songs#index.html.erb
<div id="layout-1">
<div class="left-side">
<h3>Songs</h3>
<ol>
<% #songs.each do |song| %>
<li><%= link_to song.title, song %><br></li>
<%=link_to '&#9650'.html_safe, vote_for_song_path(song), :remote => true, :method => :put %>
<%#=link_to '&#9660'.html_safe, vote_against_song_path(song), :remote => true, :method => :put %> |
Submitted <%= time_ago_in_words(song.created_at) + " ago" %>
<span class="comments"> | <%= pluralize(song.comments.size, 'comment') %></span> | <span class="votes"><%= pluralize(song.votes.count, 'like') %></span><br />
<%#= 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>
<div class="right-side">
<%= image_tag('delorean.jpg')%>
</div></div>
<br />
songs_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)
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
# GET /Songs
# GET /Songs.json
def index
#songs = Song.all
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, :bio, :track, :user_id)
end
end
Your Song model should have a plusminus field or somesuch (looking at the gem briefly, that looks like plusminus, which is the sum of up plus down votes), which counts the number of thumbs-ups a given song has received. Then, simply query with a sort on that field:
def vote_for
#song = Song.find(params[:id])
current_user.vote_for(#song)
#song.plusminus = #song.voted_for
#song.save
respond_to do |format|
format.js { render 'update_votes' }
end
end
def index
#songs = Song.order("plusminus")
end

find_or_create_by_name not working when trying to associate tasks with lists on todolist app

Rails newbie working on associating tasks with lists and running into trouble when I try and interact with forms after I start the rails server.
Here's the error I'm getting. Any ideas?
Thanks!
NoMethodError in TasksController#create
undefined method `find_or_create_by_name' for #<Class:0x00000102a8bad0>
Rails.root: /Users/user/rails_projects/todolist
Application Trace | Framework Trace | Full Trace
app/models/task.rb:15:in `list_name='
app/controllers/tasks_controller.rb:43:in `new'
app/controllers/tasks_controller.rb:43:in `create'
Request
Parameters:
{"utf8"=>"✓",
"authenticity_token"=>"B7g7u+v5USPRhefdFPt84xGkKjB1nVwy62IJj6SHJpc=",
"task"=>{"description"=>"Milk",
"list_name"=>"Shopping"},
"commit"=>"Create Task"}
ListsController:
class ListsController < ApplicationController
# GET /lists
# GET /lists.json
def index
#lists = List.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #lists }
end
end
# GET /lists/1
# GET /lists/1.json
def show
#list = List.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #list }
end
end
# GET /lists/new
# GET /lists/new.json
def new
#list = List.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #list }
end
end
# GET /lists/1/edit
def edit
#list = List.find(params[:id])
end
# POST /lists
# POST /lists.json
def create
#list = List.new(params[:list])
respond_to do |format|
if #list.save
format.html { redirect_to #list, notice: 'List was successfully created.' }
format.json { render json: #list, status: :created, location: #list }
else
format.html { render action: "new" }
format.json { render json: #list.errors, status: :unprocessable_entity }
end
end
end
# PUT /lists/1
# PUT /lists/1.json
def update
#list = List.find(params[:id])
respond_to do |format|
if #list.update_attributes(params[:list])
format.html { redirect_to #list, notice: 'List was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #list.errors, status: :unprocessable_entity }
end
end
end
# DELETE /lists/1
# DELETE /lists/1.json
def destroy
#list = List.find(params[:id])
#list.destroy
respond_to do |format|
format.html { redirect_to lists_url }
format.json { head :no_content }
end
end
end
TasksController:
class TasksController < ApplicationController
# GET /tasks
# GET /tasks.json
def index
#tasks = Task.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #tasks }
end
end
# GET /tasks/1
# GET /tasks/1.json
def show
#task = Task.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #task }
end
end
# GET /tasks/new
# GET /tasks/new.json
def new
#task = Task.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #task }
end
end
# GET /tasks/1/edit
def edit
#task = Task.find(params[:id])
end
# POST /tasks
# POST /tasks.json
def create
#task = Task.new(params[:task])
respond_to do |format|
if #task.save
format.html { redirect_to #task, notice: 'Task was successfully created.' }
format.json { render json: #task, status: :created, location: #task }
else
format.html { render action: "new" }
format.json { render json: #task.errors, status: :unprocessable_entity }
end
end
end
# PUT /tasks/1
# PUT /tasks/1.json
def update
#task = Task.find(params[:id])
respond_to do |format|
if #task.update_attributes(params[:task])
format.html { redirect_to #task, notice: 'Task was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #task.errors, status: :unprocessable_entity }
end
end
end
# DELETE /tasks/1
# DELETE /tasks/1.json
def destroy
#task = Task.find(params[:id])
#task.destroy
respond_to do |format|
format.html { redirect_to tasks_url }
format.json { head :no_content }
end
end
end
Task model:
class Task < ActiveRecord::Base
attr_accessible :description, :list_name
belongs_to :list, :foreign_key => "list_id"
def name
#list = List.find(params[:id])
end
def list_name
list.name if self.list
end
def list_name=(str)
self.list = List.find_or_create_by_name(str)
end
end
List model:
class List < ActiveRecord::Base
attr_accessible :title
has_many :tasks
def name
#list = List.find(params[:id])
end
end
Partial for Tasks:
<%= form_for(#task) do |f| %>
<% if #task.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#task.errors.count, "error") %> prohibited this task from being saved:</h2>
<ul>
<% #task.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :description %><br />
<%= f.text_area :description %>
</div>
<div class="field">
<%= f.label :list_name %><br />
<%= f.text_field :list_name %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Partial for Lists:
<%= form_for(#list) do |f| %>
<% if #list.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#list.errors.count, "error") %> prohibited this list from being saved:</h2>
<ul>
<% #list.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="actions">
<%= f.submit %>
</div>
<% end %>
The dynamic finders find_or_create_by_*... have been deprecated in Rails 4, as can be read about here.
However find_or_create_by is still supported.
In other words, instead of
find_or_create_by_name( 'Alice' ) # DEPRECATED
do
find_or_create_by( name: 'Alice' ) # OK
Rails' dynamic finders (find_by_... and find_or_create_by_...) are generated using the attributes of a model. You were using find_or_create_by_name when name wasn't an attribute on the List model.
Changing that to find_or_create_by_title(...) fixes the problem.

Resources