Keep getting ActionController::UnknownFormat for nested resource view - ruby-on-rails

Every time I go to this link /books/2/chapter I get this error:
ChaptersController#index is missing a template for this request format and variant. request.formats: ["text/html"] request.variant: []
Please show me where I am going wrong and any other improvements I can make to my code.
These are my controllers
class ChaptersController < ApplicationController
def show
#chapter =Chapter.find(params[:id])
#sections = Section.all
end
def index
#chapters = Chapter.all
#book = Book.find(params[:book_id])
end
def new
#chapter = Chapter.new
#book = Book.find(params[:book_id])
end
def edit
#chapter = Chapter.find(params[:id])
end
def create
#chapter = Chapter.new(chapter_params)
#book = Book.find(params[:book_id])
if #chapter.save
redirect_to #chapter
else
render 'new'
end
end
def update
#chapter = Chapter.find(params[:id])
if #chapter.update(chapter_params)
redirect_to #chapter
else
render 'edit'
end
end
def destroy
#chapter = Chapter.find(params[:id])
#chapter.destroy
redirect_to chapters_path
end
private
def chapter_params
params.require(:chapter).permit(:title,:text)
end
end
and
class BooksController < ApplicationController
def show
#book = Book.find(params[:id])
#chapters = Chapter.all
end
def index
#books = Book.all
end
def new
#book = Book.new
end
def edit
#book = Book.find(params[:id])
end
def create
#book = Book.new(book_params)
if #book.save
redirect_to #book
else
render 'new'
end
end
def update
#book = Book.find(params[:id])
if #book.update(book_params)
redirect_to #book
else
render 'edit'
end
end
def destroy
#book = Book.find(params[:id])
#book.destroy
redirect_to books_path
end
private
def book_params
params.require(:book).permit(:title,:text,:bookcover,:authorpic,:author)
end
end
These are my models
class Chapter < ApplicationRecord
has_many :sections, dependent: :destroy
belongs_to :book
validates :title, presence: true,
length:{minimum: 5}
end
and
class Book < ApplicationRecord
has_many :chapters, dependent: :destroy
has_attached_file :bookcover, styles: { medium: "300x300>", thumb: "100x100>" }
has_attached_file :authorpic, styles: { medium: "300x300>", thumb: "100x100>" }
validates_attachment_content_type :bookcover, :content_type => ["image/jpg", "image/jpeg", "image/png", "image/gif"]
validates_attachment_content_type :authorpic, :content_type => ["image/jpg", "image/jpeg", "image/png", "image/gif"]
validates :title, presence: true,
length:{minimum: 5}
end
These are my routes
Rails.application.routes.draw do
devise_for :users
root to: 'pages#home'
get 'about', to: 'pages#about'
resources :contacts, only: :create
get 'contact-us', to: 'contacts#new', as: 'new_contact'
get 'bookclub', to: 'pages#bookclub'
get 'podcast', to: 'pages#podcast'
resources :essays do
resources :comments
end
resources :podcasts do
resources :podcomments
end
resources :books do
resources :chapters do
resources :sections do
resources :bookcomments
end
end
end
end
This is my chapters/_index.html.erb file
<div class="mdl-grid">
<div class="mdl-cell mdl-cell--4-col"><h3>Chapters</h3>
</div>
</div>
<%= link_to 'New chapter', new_book_chapter_path(#book) %>
<% #chapters.each do |chapter| %>
<ul class="demo-list-item mdl-list">
<li class="mdl-list__item">
<span class="mdl-list__item-primary-content">
<%=link_to chapter.title, book_chapter_path(#book, chapter)%>
</span>
</li>
</ul>
<%= link_to 'Edit', edit_book_chapter_path(#book, chapter) %>
<%= link_to 'Destroy', book_chapter_path(#book, chapter),
method: :delete,
data: { confirm: 'Are you sure?' } %>
<%end%>
This is my books/show.html.erb file
<div class="mdl-grid">
<div class="mdl-cell mdl-cell--4-col"><h3><%= #book.title %></h3>
</div>
<%= render 'chapters/index', chapters: #chapters %>
<p>
<%= link_to 'Edit', edit_book_path(#book) %> |
<%= link_to 'Back', books_path %>
</p>

Why chapters/_index and not chapters/index? This must be the error.
I think you have some errors in your controllers.
def index
# Do you really want all chapters? (from all books)
# #chapters = Chapter.all
#book = Book.find(params[:book_id])
# I think you want only this book's chapters
#chapters = #book.chapters
end
def show
#chapter =Chapter.find(params[:id])
# The same thing. You want only sections from this chapter
# #sections = Section.all
#sections = #chapter.sections
end
EDIT
I see you are using chapters/_index as a partial from book/show. But you are also using the same in ChaptersController#index. Although not very nice you could do this:
chapters/index.html.erb
<%= render partial: 'chapters/_index', locals: { book: #book, chapters: #chapters } %>
in chapters/_index, replace #chapters by chapters (without #) and #book by book (without #)

Related

Rails4 -undefined method `name' for nil:NilClass 4

I am getting an error message that says undefined method 'name' in my show.html.erb page. Where it says #book.category.name it keeps saying undefined method name.
show.html.erb
<h1><%= #book.title %></h1>
<h3><%= #book.author %></h3>
<h4>Category: <%= #book.category.name %></h4>
<p><%= #book.description %></p>
<%= link_to "Back", root_path %>
<% if user_signed_in? %>
<% if #book.user_id == current_user.id %>
<%= link_to "edit", edit_book_path(#book) %>
<%= link_to "Delete", book_path(#book), method: :delete, data: {confirm: "Are you sure you want to delete book?"} %>
<% end %>
<% end %>
Books_Controller.rb
class BooksController < ApplicationController
before_action :find_book, only: [:show, :edit, :destroy, :update]
def index
if params[:category].blank?
#books = Book.all.order("created_at DESC")
else
#category_id = Category.find_by(name: params[:category]).id
#books = Book.where(:category_id => #category_id).order("created_at DESC")
end
end
def show
end
def new
#book = current_user.books.build
#categories = Category.all.map{ |c| [c.name, c.id]}
end
def create
#book = current_user.books.build(book_params)
#book.category_id = params[:category_id]
if #book.save
redirect_to root_path
else
render 'new'
end
end
def edit
#categories = Category.all.map{ |c| [c.name, c.id]}
end
def update
#book.category_id = params[:category_id]
if #book.update(book_params)
redirect_to book_path(#book)
else
render ' new'
end
end
def destroy
#book.destroy
redirect_to root_path
end
private
def book_params
params.require(:book).permit(:title, :description, :author, :category_id, :book_img)
end
def find_book
#book = Book.find(params[:id])
end
end
Book.rb
class Book < ActiveRecord::Base
belongs_to :user
belongs_to :category
has_attached_file :book_img, :styles => { :book_index => "250x350>", :book_show => "325x475>" }, :default_url => "/images/:style/missing.png"
validates_attachment_content_type :book_img, :content_type => /\Aimage\/.*\Z/
end
Category.rb
class Category < ActiveRecord::Base
has_many :books
end
Just make sure that specific book has category or just cover it into if statement like below:
<% if #book.category %>
<h4>Category: <%= #book.category.name %></h4>
<% end %>
In case you have to leave category empty is use #try:
<h4>Category: <%= #book.category.try(:name) %></h4>
You need to make sure that the instance #book has a category object.
<h4>Category: <%= #book.category ? #book.category.name : "This book has no category" %></h4>

Ruby on Rails: :topic_id=>nil, I'm lost

So I am working on an assignment at the moment, where I am trying to display favorited posts. I currently have the favorited post displayed, but when I click it, it doesn't doesn't redirect me to anywhere.
Here is the code I currently have:
User#show where I am currently trying to display the favorited posts:
<div class="row">
<div class="col-md-8">
<div class="media">
<br />
<% avatar_url = #user.avatar_url(128) %>
<% if avatar_url %>
<div class="media-left">
<%= image_tag avatar_url, class: 'media-object' %>
</div>
<% end %>
<div class="media-body">
<h2 class="media-heading"><%= #user.name %></h2>
<small>
<%= pluralize(#user.posts.count, 'post') %>,
<%= pluralize(#user.comments.count, 'comment') %>
</small>
</div>
</div>
</div>
</div>
<h2>Posts</h2>
<%= posts_exists? %>
<%= render #user.posts %>
<h2>Comments</h2>
<%= comments_exists? %>
<%= render #user.comments %>
<h2>Favorites</h2>
<% #posts.each do |post| %>
<%= render partial: 'votes/voter', locals: { post: post } %>
<%= link_to post.title, topic_post_path(#topic, post) %>
<%= image_tag current_user.avatar_url(48), class: "gravatar" %>
<%= post.comments.count %> Comments
<% end %>
The error is occuring on the following line:
<%= link_to post.title, topic_post_path(#topic, post) %>
Here is the output from the error:
ActionView::Template::Error (No route matches {:action=>"show", :controller=>"posts", :id=>"54", :topic_id=>nil} missing required keys: [:topic_id]):
29: <h2>Favorites</h2>
30: <% #posts.each do |post| %>
31: <%= render partial: 'votes/voter', locals: { post: post } %>
32: <%= link_to post.title, topic_post_path(#topic, post) %>
33: <%= image_tag current_user.avatar_url(48), class: "gravatar" %>
34: <%= post.comments.count %> Comments
35: <% end %>
app/views/users/show.html.erb:32:in `block in _app_views_users_show_html_erb__1919900632491741904_70127642538380'
app/views/users/show.html.erb:30:in `_app_views_users_show_html_erb__1919900632491741904_70127642538380'
Obviously Topid.id is nil, but I can't figure out why. I'm going to provide you with everything I think you could need? I know this is probably a simple nooby issue, but I've been stuck on it for nearly an entire day already.
Here is my User#Controller:
class UsersController < ApplicationController
def new
#user = User.new
end
def create
#user = User.new
#user.name = params[:user][:name]
#user.email = params[:user][:email]
#user.password = params[:user][:password]
#user.password_confirmation = params[:user][:password_confirmation]
if #user.save
flash[:notice] = "Welcome to Bloccit #{#user.name}!"
create_session(#user)
redirect_to root_path
else
flash[:error] = "There was an error creating your account. Please try again."
render :new
end
end
def show
#user = User.find(params[:id])
#posts = #user.posts.visible_to(current_user)
#posts = Post.joins(:favorites).where('favorites.user_id = ?', #user.id)
#favorites = current_user.favorites
end
end
Here is my Post#Controller:
class PostsController < ApplicationController
before_action :require_sign_in, except: :show
before_action :authorize_user, except: [:show, :new, :create]
def show
#post = Post.find(params[:id])
end
def new
#topic = Topic.find(params[:topic_id])
#post = Post.new
end
def create
#topic = Topic.find(params[:topic_id])
#post = #topic.posts.build(post_params)
#post.user = current_user
if #post.save
#post.labels = Label.update_labels(params[:post][:labels])
flash[:notice] = "Post was saved."
redirect_to [#topic, #post]
else
flash[:error] = "There was an error saving the post. Please try again."
render :new
end
end
def edit
#post = Post.find(params[:id])
end
def update
#post = Post.find(params[:id])
#post.assign_attributes(post_params)
if #post.save
#post.labels = Label.update_labels(params[:post][:labels])
flash[:notice] = "Post was updated."
redirect_to [#post.topic, #post]
else
flash[:error] = "There was an error saving the post. Please try again."
render :edit
end
end
def destroy
#post = Post.find(params[:id])
if #post.destroy
flash[:notice] = "\"#{#post.title}\" was deleted successfully."
redirect_to #post.topic
else
flash[:error] = "There was an error deleting the post."
render :show
end
end
private
def post_params
params.require(:post).permit(:title, :body)
end
def authorize_user
post = Post.find(params[:id])
unless current_user == post.user || current_user.admin?
flash[:error] = "You must be an admin to do that."
redirect_to [post.topic, post]
end
end
end
Here is my Topics#Controller:
class TopicsController < ApplicationController
before_action :require_sign_in, except: [:index, :show]
before_action :authorize_user, except: [:index, :show]
def index
#topics = Topic.all
end
def show
#topic = Topic.find(params[:id])
end
def new
#topic = Topic.new
end
def create
#topic = Topic.new(topic_params)
if #topic.save
#topic.labels = Label.update_labels(params[:topic][:labels])
redirect_to #topic, notice: "Topic was saved successfully."
else
flash[:error] = "Error creating topic. Please try again."
render :new
end
end
def edit
#topic = Topic.find(params[:id])
end
def update
#topic = Topic.find(params[:id])
#topic.assign_attributes(topic_params)
if #topic.save
#topic.labels = Label.update_labels(params[:topic][:labels])
flash[:notice] = "Topic was updated."
redirect_to #topic
else
flash[:error] = "Error saving topic. Please try again."
render :edit
end
end
def destroy
#topic = Topic.find(params[:id])
if #topic.destroy
flash[:notice] = "\"#{#topic.name}\" was deleted successfully."
redirect_to action: :index
else
flash[:error] = "There was an error deleting the topic."
render :show
end
end
private
def topic_params
params.require(:topic).permit(:name, :description, :public)
end
def authorize_user
unless current_user.admin?
flash[:error] = "You must be an admin to do that."
redirect_to topics_path
end
end
end
Here is my User Model:
class User < ActiveRecord::Base
has_many :posts, dependent: :destroy
has_many :comments, dependent: :destroy
has_many :votes, dependent: :destroy
has_many :favorites, dependent: :destroy
before_save { self.email = email.downcase }
before_save { self.role ||= :member }
EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
validates :name, length: { minimum: 1, maximum: 100 }, presence: true
validates :password, presence: true, length: { minimum: 6 }, if: "password_digest.nil?"
validates :password, length: { minimum: 6 }, allow_blank: true
validates :email,
presence: true,
uniqueness: { case_sensitive: false },
length: { minimum: 3, maximum: 100 },
format: { with: EMAIL_REGEX }
has_secure_password
enum role: [:member, :admin]
def favorite_for(post)
favorites.where(post_id: post.id).first
end
def avatar_url(size)
gravatar_id = Digest::MD5::hexdigest(self.email).downcase
"http://gravatar.com/avatar/#{gravatar_id}.png?s=#{size}"
end
end
Here is my Topic Model:
class Topic < ActiveRecord::Base
has_many :posts, dependent: :destroy
has_many :labelings, as: :labelable
has_many :labels, through: :labelings
end
Here is my Post Model:
class Post < ActiveRecord::Base
belongs_to :topic
belongs_to :user
has_many :comments, dependent: :destroy
has_many :votes, dependent: :destroy
has_many :labelings, as: :labelable
has_many :labels, through: :labelings
has_many :favorites, dependent: :destroy
default_scope { order('rank DESC') }
scope :visible_to, -> (user) { user ? all : joins(:topic).where('topics.public' => true) }
validates :title, length: { minimum: 5 }, presence: true
validates :body, length: { minimum: 20 }, presence: true
validates :topic, presence: true
validates :user, presence: true
def up_votes
votes.where(value: 1).count
end
def down_votes
votes.where(value: -1).count
end
def points
votes.sum(:value)
end
def update_rank
age_in_days = (created_at - Time.new(1970,1,1)) / 1.day.seconds
new_rank = points + age_in_days
update_attribute(:rank, new_rank)
end
end
Any insight anyone could provide, I would be extremely grateful for. If you have the time to explain where I went wrong as well, that would be even more helpful.
User#show where I am currently trying to display the favorited posts
But you're not setting #topic in your User#show action. That's why it's nil.
def show
#user = User.find(params[:id])
#posts = #user.posts.visible_to(current_user)
#posts = Post.joins(:favorites).where('favorites.user_id = ?', #user.id)
#favorites = current_user.favorites
# your #topic object is not in here?
end
Since a post belongs_to a topic you could do something like this:
<%= link_to post.title, topic_post_path(post.topic, post) %>

Ruby on rails trouble with nested form

I have a clan.rb and clan_options.rb
clan.rb
class Clan < ActiveRecord::Base
has_one :options, :class_name => "ClanOptions", :foreign_key => "clan_id", dependent: :destroy
accepts_nested_attributes_for :options
end
clan_options.rb
class ClanOptions < ActiveRecord::Base
belongs_to :clan
end
To create an edit form for clan.rb and clan_options.rb I use the following in edit.html.erb:
<%= form_for #clan, :html => {:class => 'form-horizontal'} do |clan| %>
<fieldset>
<!-- Form stuff -->
<%= clan.fields_for :options do |o| %>
<!-- o.text_field -->
<% end %>
</fieldset>
<% end %>
I can update the fields of clan.rb but when I try to edit the value backgroundurl it won't save it. Backgroundurl is one of the clan_options.rb
clans_controller.rb
class ClansController < ApplicationController
before_filter :check_login, :only => [:new, :edit]
before_filter :check_bound, :only => [:new, :edit]
before_filter :check_clan, :only => :new
def update
#clan = Clan.find(params[:id])
if #clan.update_attributes(clan_update_params)
flash[:status] = TRUE
flash[:alert] = "Successfully updated your clan."
redirect_to clan_path(params[:id])
else
flash[:status] = FALSE
flash[:alert] = #clan.errors.full_messages
redirect_to edit_clan_path(#clan.id)
end
end
def edit
clan = Clan.where(id: params[:id])
if !clan.blank?
#clan = Clan.find(params[:id])
user = User.where(id: session[:user_id])
if !user.blank?
#De gebruiker is ingelogt en zit in de clan
#user = User.find(session[:user_id])
if #clan.id != #user.clan.id
flash[:status] = FALSE
flash[:alert] = 'That was not your clan, you may not edit theirs.'
redirect_to clans_path
elsif #user.clanmember.group.rank != 10
flash[:status] = FALSE
flash[:alert] = "You must be the leader to edit the clan."
redirect_to clan_path(#clan.id)
end
end
else
flash[:status] = FALSE
flash[:alert] = 'that clan doesn\'t exist or has been removed.'
redirect_to clans_path
end
end
def clan_params
params.require(:clan).permit(:name, :prefix, :description, :user_id)
end
def clan_update_params
params.require(:clan).permit(:name, :prefix, :description, :user_id, options: [:id, :clan_id, :backgroundurl])
end
end
I've fixed it by changing
def clan_update_params
params.require(:clan).permit(:name, :prefix, :description, :user_id, options: [:id, :clan_id, :backgroundurl])
end
to
def clan_update_params
params.require(:clan).permit(:name, :prefix, :description, :user_id, options_attributes: [:backgroundurl])
end

undefined method `vote_for_song_songs_path' [rails 4]

So, I'm having trouble getting the Thumbs Up gem workin'.
I've followed this tutorial but I seem to be getting the below errror:
Error msg:
NoMethodError in Songs#index
Showing /Users/apane/Downloads/leap_stage/leap_stage/app/views/songs/index.html.erb where line #10 raised:
undefined method `vote_for_song_songs_path' for #<#<Class:0x007fd0b60203d0>:0x007fd0b26ecdc0>
<li><%= link_to song.title, song %><br></li>
Submitted <%= time_ago_in_words(song.created_at) + " ago" %>
<span class="comments"> | <%= pluralize(song.comments.size, 'comment') %></span><br />
<%=link_to image_tag('thumbs_up', :border => 0), vote_for_song_songs_path(#song), :remote => true %>
<%=link_to image_tag('thumbs_down', :border => 0), vote_against_song_songs_path(#song), :remote => true %>
index.html.erb
<div id="layout1">
<h3>Songs</h3>
<ol>
<% #songs.each do |song| %>
<li><%= link_to song.title, song %><br></li>
Submitted <%= time_ago_in_words(song.created_at) + " ago" %>
<span class="comments"> | <%= pluralize(song.comments.size, 'comment') %></span><br />
<%=link_to image_tag('thumbs_up', :border => 0), vote_for_song_songs_path(#song), :remote => true %>
<%=link_to image_tag('thumbs_down', :border => 0), vote_against_song_songs_path(#song), :remote => true %>
<%#= 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>
<br />
</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 = Song.find(params[:id])
current_user.vote_for(#song)
respond_to do |format|
format.js
end
end
def vote_against_song
#song = Song.find(params[:id])
current_user.vote_against(#song)
respond_to do |format|
format.js
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
song.rb
class Song < ActiveRecord::Base
acts_as_voteable
belongs_to :user
has_many :comments, :dependent => :destroy
has_attached_file :track,
:url => "/assets/songs/:id/:style/:basename.:extension",
:path => ":rails_root/public/assets/songs/:id/:style/:basename.:extension"
validates_attachment :track, :presence => true
validates :title, length: { minimum: 10 }
validates :bio, length: { maximum: 300 }
end
user.rb
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
# :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :songs
has_many :comments
acts_as_voter
end
vote.rb
class Vote < ActiveRecord::Base
scope :for_voter, lambda { |*args| where(["voter_id = ? AND voter_type = ?", args.first.id, args.first.class.base_class.name]) }
scope :for_voteable, lambda { |*args| where(["voteable_id = ? AND voteable_type = ?", args.first.id, args.first.class.base_class.name]) }
scope :recent, lambda { |*args| where(["created_at > ?", (args.first || 2.weeks.ago)]) }
scope :descending, lambda { order("created_at DESC") }
belongs_to :voteable, :polymorphic => true
belongs_to :voter, :polymorphic => true
attr_accessible :vote, :voter, :voteable if ActiveRecord::VERSION::MAJOR < 4
# Comment out the line below to allow multiple votes per user.
validates_uniqueness_of :voteable_id, :scope => [:voteable_type, :voter_type, :voter_id]
end
routes.rb
Leap2::Application.routes.draw do
resources :comments
devise_for :users, controllers: {registrations: 'registrations'}
resources :songs
get '/contact', to: 'songs#contact'
get '/faq', to: 'songs#faq'
root to: 'songs#index'
end
Since you need an :id param, it should be get or put, and to avoid writing "song_songs" you can do
resources :songs do
member do
get :vote_for, :vote_against
end
end
That gets vote_for_song_path(#song) and vote_against_song_path(#song). Technically it would be more correct to have put :vote_for, since it's not an idempotent request, but then you'd need to remember to put method: :put at the end of your url.
Edit: to get the number of votes to show up, put an element in the page like
<span class="votes"><%= pluralize(song.votes.count, 'Vote') %></span>
right after the similar comments span. Also, since you have the vote_for_song_path called remotely, you'll want to update the page with js, which means you need to be able to find the spot on the page that has the number of votes for a song. Do do that, replace the <li> with
<%= content_tag_for :li, song do %>
[then put everything in your view that has to do with one song in the block]
<% end %>
That will generate html like <li id="song_21" class="song">..., which you can refer to in an update_votes.js.erb template,
$("#song_<%= #song.id %> .votes").html("<%= pluralize(song.votes.count, "Vote") %>")
That will send javascript to your view to update the proper element; you just have to instruct the controller to send it. I believe
format.js { render 'update_votes' }
in both the vote_for and vote_against actions will do it.

Albums in rails

I would like to create an image gallery in rails. I have produced a setup that allows you to create an album and upload photos to it. However, I am stumped on how I could allow the user to set one of the existing images as the album cover in the image's index view.
Anyone have some ideas? I found that if I used radio buttons, I couldn't figure hout how to determine which image was selected by ajax. I also don't know how I would force only one image being set as album cover.
Here is my setup:
Controller
class Admin::AlbumsController < ApplicationController
respond_to :html, :json
def index
#albums = Album.all
end
def new
#album = Album.new
end
def create
#album = Album.new(params[:album])
if #album.save
flash[:notice] = "Successfully created album!"
redirect_to [:admin, :albums]
else
render "new"
end
end
def edit
#album = Album.find(params[:id])
end
def show
#album = Album.find(params[:id])
end
def update
#album = Album.find(params[:id])
#album.update_attributes(params[:album])
if #album.update_attributes(params[:album])
respond_with #album
flash[:notice] = "Successfully updated Album"
else
render "edit"
end
end
def destroy
#album = Album.find(params[:id])
#album.destroy
#id = #album.id
FileUtils.remove_dir("#{Rails.root}/public/uploads/image/picture/#{#id}", :force => true)
respond_to do |format|
format.js { render :layout => false }
end
redirect_to admin_albums_path
end
def random_image
#image_files = %w( .jpg .gif .png )
#files ||= Dir.entries(
"#{RAILS_ROOT}/public/uploads").delete_if { |x|
!#image_files.index(x[-4,4])
}
file = #files[rand(#files.length)];
#files.delete file
return "/images/logos/#{file}"
end
def ajaxUpdate
#album = Album.find(params[:album_id])
#image = #album.images.find(params[:albumcover])
if #image.update_attributes(params[:image])
flash[:notice] = "Successfully updated Image"
else
render "edit"
end
end
end
class Admin::ImagesController < ApplicationController
respond_to :html, :json
#before_filter :split_hash, :only => [ :create, :update ]
def index
#album = Album.find(params[:album_id])
#images = #album.images.all
end
def new
#album = Album.find(params[:album_id])
#image = #album.images.new
end
def create
params[:image][:source].each do |image|
#album = Album.find(params[:album_id])
#params = {}
#params['source'] = image
#image = #album.images.create(#params)
end
if #image.save
if params[:image][:source].size > 1
flash[:notice] = "Successfully added images!"
else
flash[:notice] = "Successfully added image!"
end
redirect_to [:admin, #album, :images]
else
render "new"
flash[:notice] = "Did not successfully add image :("
end
end
def show
#album = Album.find(params[:album_id])
#image = #album.images.find(params[:id])
end
def edit
#album = Album.find(params[:album_id])
#image = #album.images.find(params[:id])
end
def update
#album = Album.find(params[:album_id])
#image = #album.images.find(params[:id])
if #image.update_attributes(params[:image])
redirect_to [:admin, #album, :images]
flash[:notice] = "Successfully updated Image"
else
render "edit"
end
end
def destroy
#album = Album.find(params[:album_id])
#image = #album.images.find(params[:id])
#image.destroy
#albumid = #album.id
#id = #image.id
FileUtils.remove_dir("#{Rails.root}/public/uploads/image/picture/#{#albumid}/#{#id}", :force => true)
redirect_to admin_album_images_path(#album)
end
def ajaxUpdate
#album = Album.find(params[:album_id])
#image = #album.images.find(params[:albumcover])
if #image.update_attributes(params[:image])
flash[:notice] = "Successfully updated Image"
else
render "edit"
end
end
# def split_hash
# #album = Album.find(params[:album_id])
# #image = #album.images
# array_of_pictures = params[:image][:picture]
# array_of_pictures.each do |pic|
# size = array_of_pictures.size.to_i
# size.times {#image.build(params[:image], :picture => pic)}
# #image.save
# end
# end
end
Models
class Album < ActiveRecord::Base
attr_accessible :title, :description, :album_id
has_many :images, :dependent => :destroy
validates :title, :description, :presence => true
end
class Image < ActiveRecord::Base
attr_accessible :title, :description, :source, :album_id, :albumcover, :image, :image_id
belongs_to :album
accepts_nested_attributes_for :album
mount_uploader :source, PictureUploader
end
View
<% content_for :head do %>
<%= stylesheet_link_tag 'admin/images' %>
<%= javascript_include_tag "admin.js" %>
<% end %>
<% content_for :menu do %>
<li class="menu_item"><%=link_to "New Album", :controller => "albums", :action => "new" %></li>
<li class="menu_item"><%= link_to "Add Images", {:controller => "images", :action => "new"}, :class => "highlight_menu"%> </li>
<% end %>
<%= link_to "< Back", admin_albums_path, :id => "return_link" %> </br>
<h1 class="section-title"> <strong style="font-weight: 600;"><%=best_in_place [:admin,#album], :title, :ok_button => :confirm %></strong></h1>
<h4 class="album-desc"><%= best_in_place [:admin,#album], :description, :type => :textarea, :ok_button => :confirm%></h4>
<%= form_tag admin_album_images_path(#album) do %>
<% if !#images.blank? %>
<% #images.each do |image| %>
<div class="item">
<div class="image-box">
<div class="source">
<%= image_tag image.source %>
</div>
</div>
<div class="info">
<div class="item-links">
<%= link_to "Edit", edit_admin_album_image_path(#album, image.id), :id => "edit"%>
<%= link_to "Delete",
admin_album_image_path(#album, image.id),
:class => "item-link delete-image",
:method => :delete,
:remote => true,
:confirm => "Are you sure?" %>
</div>
</div>
</div>
<% end %>
<% else %>
<p class="alert">No images in this album</p>
<% end %>
<% end %>
Answer!
*albums_controller*
def albumCoverSet
#album = Album.find(params[:album_id])
#image = #album.images.find(params[:albumcover])
if #image.update_attributes(params[:image])
flash[:notice] = "Successfully updated Image"
else
render "edit"
end
end
* album view *
<div class="image">
<%= image_tag album.images.find(album.albumcover_id).source, :class => "image" %>
</div>
model
class Album < ActiveRecord::Base
attr_accessible :title, :description, :album_id, :albumcover_id
has_many :images, :dependent => :destroy
has_one :albumcover, :class_name => "Image"
validates :title, :description, :presence => true
end
You can add a 'primary_image_id' to the Album in a migration.
has_one :primary_image, :class_name => 'Image'
In your form, you can show all album.images and select one. Radio buttons should work just fine.
Submitting the value of the param would set the primary_image_id.

Resources