I have the below form written for a movie review. Review is associated with movies. I am not able to display error message for this form. I have written similar code to display error message for validation on movies and that works well.
Code for the 'add new review' form -
<%= form_for([#movie, #movie.reviews.build]) do |f| %>
<% if #reviews.errors.any? %>
<div id="error_explanation">
<h3>
<%= pluralize(#reviews.errors.count, "error") %> prohibited
this review from being saved:
</h3>
<ul>
<% #reviews.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<p>
<%= f.label :reviewer %><br>
<%= f.text_field :reviewer %>
</p>
<p>
<%= f.label :comment %><br>
<%= f.text_area :comment %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
Models -
MOVIE -
class Movies < ActiveRecord::Base
has_many :reviews, dependent: :destroy
validates_associated :reviews
validates :title, presence: true
validates :rating, presence: true, numericality: { greater_than: 0, less_than_or_equal_to: 10 }
end
REVIEW -
class Review < ActiveRecord::Base
belongs_to :movies
validates :comment, presence: true
end
Adding code for reviews_controller.erb
class ReviewsController < ApplicationController
def create
#movie = Movies.find(params[:movie_id])
#review = #movie.reviews.create(review_params)
redirect_to movies_path(#movie)
end
def destroy
#movie = Movies.find(params[:movie_id])
#review = #movie.reviews.find(params[:id])
#review.destroy
redirect_to movies_path(#movie)
end
private
def review_params
params.require(:review).permit(:reviewer, :comment)
end
end
Here is my code for movies_controller.erb
class MoviesController < ApplicationController
def new
#movie = Movies.new
end
def index
#movies = Movies.all
end
def show
#movie = Movies.find(params[:id])
end
def edit
#movie = Movies.find(params[:id])
end
def create
#movie = Movies.new(movie_params)
if #movie.save
redirect_to #movie
else
render 'new'
end
end
def update
#movie = Movies.find(params[:id])
if #movie.update(movie_params)
redirect_to #movie
else
render 'edit'
end
end
def destroy
#movie = Movies.find(params[:id])
#movie.destroy
redirect_to movies_path
end
private
def movie_params
params.require(:movie).permit(:title,:year,:rating,:description)
end
end
Please help me identify what is going wrong and how to be able to get the validation message working.
Thanks in advance.
You are trying to display error of #review with <% if #reviews.errors.any? %>
But You do not have #reviews in <%= form_for([#movie, #movie.reviews.build) do |f| %>
Better solution, through controller assigning #review = Review.new. In this case it should show you errors, if comment field is empty.
def new
#review = Review.new
end
def create
#movie = Movie.find(params[:movie_id])
#review = #movie.reviews.build(review_params)
if #review.save
else
render 'new'
end
end
In Form
<%= form_for ([#movie, #review) do |f| %>
Related
Full source code is here https://github.com/tenzan/postfile
Creating a post working fine.
I have a parent element "Conversation" and its child/nested element "Post".
When I click on "Create Post" with nothing entered, it should throw an error "Body can't be blank".
Instead, it giving another error:
conversation.rb:
class Conversation < ApplicationRecord
belongs_to :contact
has_many :posts
end
post.rb:
class Post < ApplicationRecord
belongs_to :conversation
belongs_to :author, polymorphic: true
has_rich_text :body
validates :body, presence: :true
end
posts_controller.rb:
class PostsController < ApplicationController
before_action :authenticate_user!
before_action :set_conversation
def create
#post = #conversation.posts.new(post_params)
#post.author = current_user
respond_to do |format|
if #post.save
format.html { redirect_to #conversation }
end
end
end
private
def set_conversation
#conversation = Conversation.find(params[:conversation_id])
end
def post_params
params.require(:post).permit(:body)
end
end
I show all posts within from conversation's show.html.erb:
<p id="notice"><%= notice %></p>
<p>
<strong>Subject:</strong>
<%= #conversation.subject %>
</p>
<p>
<strong>Contact:</strong>
<%= link_to #conversation.contact.name, #conversation.contact %>
</p>
<%= link_to 'Edit', edit_conversation_path(#conversation) %> |
<%= link_to 'Back', conversations_path %>
<div id="posts">
<%= render #posts %>
</div>
<%= render partial: "posts/form", locals: { conversation: #conversation, post: Post.new } %>
Posts's partial _form.html.erb:
<%= form_with model: [conversation, post], id: "form" do |form| %>
<div>
<% form.object.errors.full_messages.each do |message| %>
<div><%= message %></div>
<% end %>
</div>
<br>
<%= form.rich_text_area :body %>
<%= form.submit %>
<% end %>
Full source code is here https://github.com/tenzan/postfile
Thanks in advance.
You have this block in your posts_controller, which is where your error is arising:
respond_to do |format|
if #post.save
format.html { redirect_to #conversation }
end
end
Inside a respond_to block, you should have blocks identified by the format type, but you've added an if statement at that top level of the block where Rails is expecting a format.xxx. Move the if outside your respond_to block and you should be fine:
if #post.save
respond_to do |format|
format.html { redirect_to #conversation }
end
else
DO SOMETHING WITH THE ERROR
end
(Also NB that you should handle the error if the post doesn't save, even if it's just to say "Sorry, please try again".)
I am trying to build a nested form and having issues when using the edit page of the resource. I can get the new action to work fine, but I am finding if I try to update the resource to include new sub-resource it doesn't save the subresources.
I am running rails 5.2 and have cocoon gem installed for the nested forms.
An order has many cards
Order Model:
class Order < ApplicationRecord
has_many :cards, dependent: :destroy
accepts_nested_attributes_for :cards, allow_destroy: true
end
Card Model:
class Card < ApplicationRecord
belongs_to :order
end
Orders Controller:
class OrdersController < ApplicationController
def index
#orders = Order.all
end
def new
#order = Order.new
#order.cards.build
end
def create
#order = Order.new(order_params)
if #order.save
redirect_to order_path(#order)
else
render 'new'
end
end
def show
#order = Order.find(params[:id])
end
def edit
#order = Order.find(params[:id])
#order.cards.build
end
def update
#order = Order.find(params[:id])
if #order.update_attributes(order_params)
redirect_to order_path(#order)
else
render 'edit'
end
end
def destroy
#order = Order.find(params[:id])
#order.destroy
redirect_to orders_path
end
private
def order_params
params.require(:order).permit(:title, :price, cards_attributes: [:id, :title, :price, :_destroy])
end
end
Orders Edit View:
<%= form_for #order do |f| %>
<%= f.fields_for :cards do |card| %>
<%= render 'card_fields', f: card %>
<% end %>
<%= link_to_add_association f, :cards, class: "add-cards" do %>
<span>Add Card</span>
<% end %>
<%= f.submit "Update" %>
<% end %>
Orders form partial View:
<div class="nested-fields">
<%= f.label :title, 'Card Description', class: "g-mb-10" %>
<%= f.text_field :title, class: "form-control form-control-md g-brd-gray-light-v7 g-brd-lightblue-v3--focus g-rounded-4 g-px-20 g-py-12" %>
<%= link_to_remove_association f, class: "remove-quals u-link-v5 d-flex align-items-center g-color-lightblue-v3 g-ml-30" do %>
<span class="g-ml-15">Remove Card</span>
<% end %>
</div>
Now if I add #order.cards.build to the edit action it works, but if no new card is added it still creates an empty record. Also if I change
accepts_nested_attributes_for :cards, allow_destroy: true
to
accepts_nested_attributes_for :cards, allow_destroy: true, reject_if: proc { |attributes| attributes['price'].blank? }
This is works as long as none of the other items are being updated at the same time.
Ideally, When someone goes to edit order a new card shouldn't be visible till someone clicks add card.
Any help would be greatful.
Thanks
found my problem.
Edit view (add div with id of cards)
<%= form_for #order do |f| %>
<div id="cards">
<%= f.fields_for :cards do |card| %>
<%= render 'card_fields', f: card %>
<% end %>
<%= link_to_add_association f, :cards, class: "add-cards" do %>
<span>Add Card</span>
<% end %>
</div>
<%= f.submit "Update" %>
<% end %>
and in my controller removed the #order.cards.build from the edit action.
Reason for the div, is the JS was inserting the fields for outside the actual form.
I have two models, Hotel and Room. I want to create a form that will allow me to add a new hotel and rooms, which indicates the name of the hotel and the quantity of rooms.
I know I should use "nested form", but it is hard for me to implement it properly.
Here is my code:
HotelsController
class HotelsController < ApplicationController
def index
#hotels = Hotel.all
end
def new
#hotel = Hotel.new
end
def create
#hotel = Hotel.new(hotel_params)
if #hotel.save
redirect_to #hotel
else
render 'new'
end
end
def show
#hotel = Hotel.find(params[:id])
end
def destroy
#hotel = Hotel.find(params[:id])
#hotel.destroy
redirect_to hotels_url, notice: 'Hotel was successfully destroyed.'
end
private
def hotel_params
params.require(:hotel).permit(:name, :rooms_count)
end
end
Hotel model
class Hotel < ApplicationRecord
has_many :rooms, dependent: :destroy
accepts_nested_attributes_for :rooms
end
Room model
class Room < ApplicationRecord
belongs_to :hotel, optional: true # avoiding rails 5.2 belongs_to error
end
form
<%= form_with scope: :hotel, url: hotels_path, local: true do |form| %>
<p>
<%= form.label :name %><br>
<%= form.text_field :name %>
</p>
<p>
<%= form.label :rooms_count %><br>
<%= form.number_field :rooms_count %>
</p>
<p>
<% form.fields_for :rooms do |f|%>
<p>
**THE CODE**
</p>
<% end %>
</p>
<p>
<%= form.submit %>
</p>
<% end %>
You forgot the "ERB echo sign" (=) on the fields_for helper.
Correct form:
<%= form.fields_for :rooms do |f|%>
I have found a solution to my question.
def create
#hotel = Hotel.new(hotel_params)
#hotel.rooms_count.times do
#hotel.rooms.build
end
if #hotel.save
redirect_to #hotel
else
render 'new'
end
end
It implement a #hotel.rooms.build as many times as #hotel.rooms_count number entered in Rooms Count field in form.
I am working on a website, where a user can have multiple projects and multpile users can contribute to a single project.
I have a project model
class Project < ActiveRecord::Base
#associations
has_and_belongs_to_many :users
end
and a users model
class User < ActiveRecord::Base
#associations
has_and_belongs_to_many :projects
end
and I have created a joins table by the name - :projects_users
everything works fine when I run the code on rails console.
but when I try to do the save thing in the controller, the data is not being saved in the joins table.
Code for the controller
please help
class ProjectsController < ApplicationController
def new
#project = Project.new
end
def create
#user = User.find(session[:user_id])
#project = Project.new(project_params)
if #project.save
#project.users << #user
redirect_to #project
else
flash[:error] = "Project has not been created due to some error"
render 'new'
end
end
private
def project_params
params.require(:project).permit(:name,:description)
end
end
Try using nestes_attributes_for
class Answer < ActiveRecord::Base
belongs_to :question
end
class Question < ActiveRecord::Base
has_many :answers
accepts_nested_attributes_for :answers, allow_destroy: true
end
Controlller
def new
#question = Question.new
#question.answers.build
end
def create
#question = Question.new(question_params)
respond_to do |format|
if #question.save
format.html { redirect_to #question, notice: 'question was successfully created.' }
format.json { render action: 'show', status: :created, location: #question }
else
format.html { render action: 'new' }
format.json { render json: #question.errors, status: :unprocessable_entity }
end
end
end
def question_params
params.require(:question).permit(:name, :description, answers_attributes:[:content, :id, :question_id])
end
You form should look like this
<%= form_for(#question) do |f| %>
<% if #question.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#question.errors.count, "error") %> prohibited this question from being saved:</h2>
<ul>
<% #question.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %><br>
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :description %><br>
<%= f.text_field :description %>
</div>
<%= f.fields_for :answer do |builder| %>
<%= builder.label :content %>
<%= builder.text_area :content %>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
just changed
#project.users << #user
to
#user.projects << #project
and it started working.Dont know the reason yet but its working
im doing an authorisation application where:
-have admin role, who can manage everything.
-have guest role, who can create posts and edit the posts which he has created.
im facing problem with the guest role. I have done associations where:
-posts belongs_to user(In post model am having user_id attribute also in migration i have referenced posts to users)
-user has_many posts.
when im tryin to create a new post, the user_id is nil. i dunno how to set user_id attribute in Post object.
class ProductsController < ApplicationController
before_filter :self_load, :only=>[:show,:edit,:update,:destroy]
before_filter :authenticate_user, :only=>[:edit,:update,:destroy]
def index
#products=Product.find(:all)
end
def new
#product=Product.new(:user_id=>current_user.id)
end
def create
#product=Product.new(params[:product])
if #product.save
redirect_to root_url, :notice=>'New Product has been added'
else
render :action=>'new'
end
end
def show
end
def edit
end
def update
if #product.update_attributes(params[:product])
redirect_to root_url, :notice=>'Product has been updated.'
else
render :action => 'edit'
end
end
def destroy
#product.destroy
redirect_to root_url
end
def self_load
#product = Product.find(params[:id])
end
def authenticate_user
if current_user
else
redirect_to root_url, :notice=>'You are not authorised to access'
end
end
end
view:
Add Product
<%= form_for(#product) do |f| %>
<% if #product.errors.any? %>
<ul>
<% #product.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
<% end %>
<table>
<tr><td><%= f.label 'Title:' %></td>
<td><%= f.text_field :title %></td>
<tr><td><%= f.label 'Description:' %></td>
<td><%= f.text_area :description,:rows=>10 %></td></tr>
<tr><td><%= f.label 'Price:' %></td>
<td><%= f.text_field :price %></td></tr>
<tr><td><%= f.submit 'Save' %></td></tr>
</table>
<% end %>
<%= link_to 'Back', root_url %>
Model
class Product < ActiveRecord::Base
belongs_to :user
attr_accessible :title, :description, :price, :user_id
validates_presence_of :title, :description, :price
validates_uniqueness_of :title
validates_length_of :title, :in=>4..10
validates_length_of :description, :minimum=>10
validates_numericality_of :price
end
Plz help me with this.... if u need any further info u can ask...
if only signed in user can create products, try this
class ProductsController < ApplicationController
def create
#product = current_user.products.build params[:product]
if #product.save
# Stuff is product save succesfully
else
# Stuff is product does not saved
end
end
end