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.
Related
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 #)
When I want to go to "localhost:3000/blog" the web page gives this error...
Showing C:/Sites/ifurniture/app/views/refinery/blog/posts/index.html.erb where line #3 raised:
undefined method `to_sym' for {:title=>"Body", :slug=>"body"}:Hash
Rails.root: C:/Sites/ifurniture
this is the blog controller..
module Refinery
module Blog
class PostsController < BlogController
before_filter :find_all_blog_posts, :except => [:archive]
before_filter :find_blog_post, :only => [:show, :comment, :update_nav]
before_filter :find_tags
respond_to :html, :js, :rss
def index
if request.format.rss?
#posts = if params["max_results"].present?
# limit rss feed for services (like feedburner) who have max size
Post.recent(params["max_results"])
else
Post.newest_first.live.includes(:comments, :categories)
end
end
respond_with (#posts) do |format|
format.html
format.rss { render :layout => false }
end
end
def show
#comment = Comment.new
#canonical = refinery.url_for(:locale => Refinery::I18n.current_frontend_locale) if canonical?
#post.increment!(:access_count, 1)
respond_with (#post) do |format|
format.html { present(#post) }
format.js { render :partial => 'post', :layout => false }
end
end
def comment
#comment = #post.comments.create(comment_params)
if #comment.valid?
if Comment::Moderation.enabled? or #comment.ham?
begin
CommentMailer.notification(#comment, request).deliver_now
rescue
logger.warn "There was an error delivering a blog comment notification.\n#{$!}\n"
end
end
if Comment::Moderation.enabled?
flash[:notice] = t('thank_you_moderated', :scope => 'refinery.blog.posts.comments')
redirect_to refinery.blog_post_url(params[:id])
else
flash[:notice] = t('thank_you', :scope => 'refinery.blog.posts.comments')
redirect_to refinery.blog_post_url(params[:id],
:anchor => "comment-#{#comment.to_param}")
end
else
render :show
end
end
def archive
if params[:month].present?
date = "#{params[:month]}/#{params[:year]}"
archive_date = Time.parse(date)
#date_title = ::I18n.l(archive_date, :format => '%B %Y')
#posts = Post.live.by_month(archive_date).page(params[:page])
else
date = "01/#{params[:year]}"
archive_date = Time.parse(date)
#date_title = ::I18n.l(archive_date, :format => '%Y')
#posts = Post.live.by_year(archive_date).page(params[:page])
end
respond_with (#posts)
end
def tagged
#tag = ActsAsTaggableOn::Tag.find(params[:tag_id])
#tag_name = #tag.name
#posts = Post.live.tagged_with(#tag_name).page(params[:page])
end
private
def comment_params
params.require(:comment).permit(:name, :email, :message)
end
protected
def canonical?
Refinery::I18n.default_frontend_locale != Refinery::I18n.current_frontend_locale
end
end
end
end
the post controller...
module Refinery
module Blog
class PostsController < BlogController
before_filter :find_all_blog_posts, :except => [:archive]
before_filter :find_blog_post, :only => [:show, :comment, :update_nav]
before_filter :find_tags
respond_to :html, :js, :rss
def index
if request.format.rss?
#posts = if params["max_results"].present?
# limit rss feed for services (like feedburner) who have max size
Post.recent(params["max_results"])
else
Post.newest_first.live.includes(:comments, :categories)
end
end
respond_with (#posts) do |format|
format.html
format.rss { render :layout => false }
end
end
def show
#comment = Comment.new
#canonical = refinery.url_for(:locale => Refinery::I18n.current_frontend_locale) if canonical?
#post.increment!(:access_count, 1)
respond_with (#post) do |format|
format.html { present(#post) }
format.js { render :partial => 'post', :layout => false }
end
end
def comment
#comment = #post.comments.create(comment_params)
if #comment.valid?
if Comment::Moderation.enabled? or #comment.ham?
begin
CommentMailer.notification(#comment, request).deliver_now
rescue
logger.warn "There was an error delivering a blog comment notification.\n#{$!}\n"
end
end
if Comment::Moderation.enabled?
flash[:notice] = t('thank_you_moderated', :scope => 'refinery.blog.posts.comments')
redirect_to refinery.blog_post_url(params[:id])
else
flash[:notice] = t('thank_you', :scope => 'refinery.blog.posts.comments')
redirect_to refinery.blog_post_url(params[:id],
:anchor => "comment-#{#comment.to_param}")
end
else
render :show
end
end
def archive
if params[:month].present?
date = "#{params[:month]}/#{params[:year]}"
archive_date = Time.parse(date)
#date_title = ::I18n.l(archive_date, :format => '%B %Y')
#posts = Post.live.by_month(archive_date).page(params[:page])
else
date = "01/#{params[:year]}"
archive_date = Time.parse(date)
#date_title = ::I18n.l(archive_date, :format => '%Y')
#posts = Post.live.by_year(archive_date).page(params[:page])
end
respond_with (#posts)
end
def tagged
#tag = ActsAsTaggableOn::Tag.find(params[:tag_id])
#tag_name = #tag.name
#posts = Post.live.tagged_with(#tag_name).page(params[:page])
end
private
def comment_params
params.require(:comment).permit(:name, :email, :message)
end
protected
def canonical?
Refinery::I18n.default_frontend_locale != Refinery::I18n.current_frontend_locale
end
end
end
end
and this is the index.html.erb of Blog.
<section class="container">
<% content_for :body do %>
<%= raw #page.content_for(Refinery::Pages.default_parts.first.to_sym) if Refinery::Pages.default_parts.any? %>
<% if #posts.any? %>
<section id="blog_posts" class="news">
<%= render :partial => "/refinery/blog/shared/post", :collection => #posts %>
<%= will_paginate #posts %>
</section>
<% else %>
<p><%= t('.no_blog_articles_yet') %></p>
<% end %>
<% end %>
<% content_for :side_body_prepend do -%>
<%= raw #page.content_for(Refinery::Pages.default_parts.second.to_sym) %>
<% end if Refinery::Pages.default_parts.many? -%>
<%= render "/refinery/content_page" %>
<% content_for :stylesheets, stylesheet_link_tag('refinery/blog/frontend') %>
</section>
I'll be watching for your help, thanks.
You can use to_sym method on hash or string so in your code you can do something like this:
index.html
instead this:
<%= raw #page.content_for(Refinery::Pages.default_parts.first.to_sym) if Refinery::Pages.default_parts.any? %>
put this:
<%= raw #page.content_for(Refinery::Pages.default_parts.first[:title].to_sym) if Refinery::Pages.default_parts.any? %>
instead [:title]you can also use [:slug]
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>
<% #idea.each do |#idea| %>
<div id="basic_details" class="idea-show-columns">
<%= render :partial => '/ideas/idea_basic_show', :locals => {:idea => #idea} %>
<%= render :partial => 'ideas/comments' %>
<%= render :partial => 'ideas/mockups' %>
</div>
<div id="copy_details" class="idea-show-columns">
<%= render :partial => 'ideas/ copy_show', :locals => {:idea => #idea} %>
</div>
<% end %>
When I take the # off it says "Parameter 'idea' is not used", I cannot find the proper syntax for this.
IdeasController
class IdeasController < ApplicationController
def index
respond_to do |format|
if request.xhr?
#ideas = Idea.select("sku, id").order(:sku)
else
if params[:search]
#ideas = Idea.where("sku like '%#{params[:search]}%' or working_name like '%#
{params[:search]}%' or product_name like '%#{params[:search]}%'").paginate(:page =>
params[:page]).reload
else
#ideas = Idea.paginate(:page => params[:page]).reload
end
end
format.html
format.json {render json: #ideas.where("sku like ?", "%#{params[:q]}%") }
end
end
def show
#idea = Idea.find_by_permalink(params[:id])
end
def new
#idea = Idea.new
end
def create
#idea = Idea.new(new_idea_params)
if #idea.save
flash[:notice] = 'Idea created!'
redirect_to ideas_url
else
render :new
end
end
def edit
#idea = Idea.find_by_permalink(params[:id])
end
def update
#idea = Idea.find_by_permalink(params[:id])
if request.xhr?
if params[:comment]
#idea.comments.create(:title => params[:comment][:title], :comment => params[:comment][:comment], :user_id => current_user.id)
end
if #idea.update_attributes(update_status_params)
#success = true
else
#success = false
end
else
if #idea.update_attributes(edit_idea_params)
flash[:notice] = 'Idea updated!'
redirect_to idea_url(params[:id])
else
render :edit
end
end
end
def destroy
Idea.find_by_permalink(params[:id]).destroy
flash[:success] = "Idea destroyed."
redirect_to ideas_url
end
def generate_mockups
idea = Idea.find_by_permalink(params[:id])
begin
idea.generate_mockups
rescue Exception => e
flash[:error] = "There was an error generating the mockups for #{idea.working_name}! # {e.message}"
end
flash[:notice] = "Successfully generated mockups for #{idea.working_name}"
redirect_to idea_url(params[:id])
end
def signoff
if current_user.has_overlord_access?
if params[:idea_id]
idea = Idea.find(params[:idea_id])
idea.overlord_id = current_user.id
idea.status = 'Ready To Publish'
idea.save
flash[:notice] = "#{current_user.full_name} just signed off on #{idea.sku}"
redirect_to :action => :signoff
end
#ideas = Idea.awaiting_overlord_signoff.reload
#idea = #ideas.first.reload
else
flash[:notice] = 'Sorry, you must have overlord access to sign off on ideas.'
redirect_to ideas_path
end
end
private
def new_idea_params
params.require(:idea).permit(:sku, :working_name, :working_description, :priority)
end
def update_status_params
params.require(:idea).permit(:art_status, :copy_status)
end
def edit_idea_params
(params[:idea][:color_ids] ||= []) unless !current_user.has_artist_access?
(params[:idea][:imprintable_ids] ||= []) unless !current_user.has_copywriter_access?
(params[:idea][:stores_ids] ||= []) unless !current_user.has_copywriter_access?
(params[:idea][:taxonomies_ids] ||= []) unless !current_user.has_copywriter_access?
params.require(:idea).permit(:sku, :working_name, :working_description, :priority,
:product_name, :product_line_tokens,
:description, :meta_description, :meta_keywords, :artist_id,
:copywriter_id, :overlord_id,
{:store_ids => []}, {:taxonomy_ids => []}, :base_price,
:shipping_category, :default_artwork_id,
:tax_category, {:imprintable_ids => []}, :marketplace,
:product_type,
:base, :colors_offered, :special_instructions, :copy_status,
:art_status, {:color_ids => []},
:artworks_attributes => [:height, :width, :from_top,
:from_center, :idea_id, :dimensions, :file, :_destroy, :id])
end
def update_status_params
params.require(:idea).permit(:copy_status, :art_status)
end
end
I am getting the error
undefined method `each' for nil:NilClass
It should :
<% unless #ideas.nil? %>
<% #ideas.each do |idea| %>
<div id="basic_details" class="idea-show-columns">
<%= render :partial => '/ideas/idea_basic_show', :locals => {:idea => idea} %>
<%= render :partial => 'ideas/comments' %>
<%= render :partial => 'ideas/mockups' %>
</div>
<div id="copy_details" class="idea-show-columns">
<%= render :partial => 'ideas/ copy_show', :locals => {:idea => idea} %>
</div>
<% end %>
<% end %>
Few things:
if you need to use #ideas in show view you need to load them using before_filter
dont do this dea.where("sku like '%#{params[:search]}%' because this is not secure. Do something like where("code = ?", params[:code])
I have an app that allows users to enter a project into a database.
They get the option to either enter new data via a textbox for some field, or can select data via a drop down menu, that has been entered before for that field.
If the user fills out the form, then clicks submit, but there is a problem, like they have missed out one of the fields, the page flags up an error saying which fields are missing, which is fine.
However, if the user had entered new data in the text boxes, that gets deleted, and the first option in the drop down is selected instead.
Here is my project controller:
class ProjectsController < ApplicationController
before_filter :authenticate_user!
#:except => [:show, :index]
def index
#projects = Project.all
respond_to do |format|
format.html # index.html.erb
format.json { render :json => #projects }
end
end
# GET /projects/1
# GET /projects/1.json
def show
#project = Project.find(params[:id])
#project_project_id = params[:id]
respond_to do |format|
format.html # show.html.erb
format.json { render json: #project }
end
end
# GET /projects/new
# GET /projects/new.json
def new
#project = Project.new
#technol = Technol.new(params[:tech])
#all_technols = Technol.all
tech_ids = params[:technols][:id].reject(&:blank?) unless params[:technols].nil?
#project_technol = #project.projecttechnols.build
respond_to do |format|
format.html # new.html.erb
format.json { render json: #project }
end
end
# GET /projects/1/edit
def edit
#project = Project.find(params[:id])
#project_technol = #project.projecttechnols.build
puts #project.inspect
puts #project.technols.inspect
end
# POST /projects
# POST /projects.json
def create
#project = Project.new(params[:project])
#project.client = params[:new_client] unless params[:new_client].blank?
#project.role = params[:new_role] unless params[:new_role].blank?
#project.industry = params[:new_industry] unless params[:new_industry].blank?
#project.business_div = params[:new_business_div] unless params[:new_business_div].blank?
if !params[:technols].nil?
params[:technols][:id].each do |tech|
if !tech.empty?
#project_technol = #project.projecttechnols.build(:technol_id => tech)
end
end
end
respond_to do |format|
if #project.save
format.html { redirect_to #project, notice: 'Project was successfully created.' }
format.json { render json: #project, status: :created, location: #project }
else
format.html { render action: "new" }
format.json { render json: #project.errors, status: :unprocessable_entity }
end
end
end
# PUT /projects/1
# PUT /projects/1.json
# PUT /projects/1
# PUT /projects/1.json
def update
#project = Project.find(params[:id])
puts #project.inspect
puts #project.technols.inspect
#project.client = params[:new_client] unless params[:new_client].blank?
#project.role = params[:new_role] unless params[:new_role].blank?
#project.industry = params[:new_industry] unless params[:new_industry].blank?
#project.business_div = params[:new_business_div] unless params[:new_business_div].blank?
respond_to do |format|
if #project.update_attributes(params[:project])
format.html { redirect_to #project, notice: 'Project was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #project.errors, status: :unprocessable_entity }
end
end
end
# DELETE /projects/1
# DELETE /projects/1.json
def destroy
#project = Project.find(params[:id])
#project.destroy
respond_to do |format|
format.html { redirect_to projects_url }
format.json { head :no_content }
end
end
private
helper_method :sort_column, :sort_direction
def sort_column
Project.column_names.include?(params[:sort]) ? params[:sort] : "project_name"
end
def sort_direction
%w[asc desc].include?(params[:direction]) ? params[:direction] : "asc"
end
def per_page
params[:per_page] ||= 1
end
def page
params[:page] ||= 1
end
end
Here is some of my new project view
<%= stylesheet_link_tag "new" %>
<h1>Create New Project</h1>
<HTML>
<%= stylesheet_link_tag "form" %>
<%= form_for(#project) do |f| %>
<% if #project.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#project.errors.count, "error") %> prohibited this project from being saved:</h2>
<ul>
<% #project.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<CENTER>
<div id = "project_name">
<div class="project_name">
Project Name:
<%= f.text_field :project_name,:maxlength => 30 %>
</div>
</div>
<div id ="smallbox">
<div id = "status">
<div class="status">
<%= f.label :status %> :
<%#= f.select :status, [['Active'],['Completed']], {:include_blank => true} %>
<%= f.select :status, [['Active'],['Completed']] %>
</div></div>
<div class="client" STYLE="text-align: left;">
<%= label_tag :new_client, "Client" %><br/>
<%= text_field_tag :new_client, nil, :maxlength => 30 %>
Or
<%= f.select( :client, Project.all.map {|p| [p.client]}.uniq, :prompt => "Select previous..") %>
</div>
<div class="business_div" STYLE="text-align: left;">
<%= label_tag :new_business_div, "Business Division" %><br/>
<%= text_field_tag :new_business_div, nil, :maxlength => 30 %>
Or
<%= f.select( :business_div, Project.all.map {|p| [p.business_div]}.uniq, :prompt => "Select previous") %>
</div>
<div class="start_date" STYLE="text-align: left;">
<b>Start Date:</b>
<%= f.text_field :start_date, :class => 'datepicker', :style => 'width: 80px;' %>
</div>
</P>
<div class="create_button">
<div class="actions">
<%= f.submit "Save New Project", :class => "button", :confirm => "Are you sure you want to save the new project?" %>
</div>
</div>
</div> <%#= small div %>
<% end %>
<div class="back_button2">
<%= button_to "Back", projects_path , :class => "button", :method => "get" %>
</div>
Here is my project model
class Project < ActiveRecord::Base
attr_accessible :fullname, :edited_first_name, :edited_last_name, :first_name, :last_name, :business_div, :client, :customer_benefits, :edited_date, :end_date, :entry_date, :financials, :industry, :keywords, :lessons_learned, :project_name, :role, :start_date, :status, :summary, :technol_ids, :tech , :technols
validates_presence_of :business_div, :client, :customer_benefits, :end_date, :financials, :industry, :lessons_learned, :project_name, :role, :start_date, :status, :summary #, :keywords
validates_format_of :industry, :with => /\A[^\d]+\Z/, :message => "field should only have letters"
validates_format_of :business_div, :with => /\A[^\d]+\Z/, :message => "field should only have letters"
validates_format_of :client, :with => /\A[^\d]+\Z/, :message => "field should only have letters"
validates_format_of :exception_pm, :with => /\A[^\d]+\Z/, :message => "field should only have letters"
validates_format_of :project_owner, :with => /\A[^\d]+\Z/, :message => "field should only have letters"
validates_format_of :role, :with => /\A[^\d]+\Z/, :message => "field should only have letters"
has_many :projecttechnols
has_many :technols, :through => :projecttechnols
def set_fullname(a, b)
fullname = [a, b].join(' ')
end
accepts_nested_attributes_for(:technols)
end
If I need to include anything else please let me know. I have been stuck with this problem for some time now. Thank you in advance.
As railsdog suggests, use the data passed to Projects#create. Your form submits data and that data is held in a variable called params as key/value pairs. That variable should still be accessible from whichever view Projects#create renders.
What you need to do is to set some default content on your form elements. Here's an example for the text_field called "project_name"
<div class="project_name">
Project Name:
<%= f.text_field :project_name, params[:project_name],:maxlength => 30 %>
</div>
You should be able to do the same or something similar with any other fields.