ActiveRecord Rollback when trying to save to database - ruby-on-rails

I am building a fairly simple album review application. I am attempting to set up a simple_form for new reviews. The change will not stick. This is what appears in my terminal when I attempt to add a review:
Started POST "/albums/6/reviews" for ::1 at 2017-01-10 11:36:30 -0800
Processing by ReviewsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"Ld5yOdf4fbzQvyPdckfAtnjWqbDQQHkEZuszSrdlsjVfRYntGZymxwP80DI xe4O8Pe5X7cl7P2ioCR1bQ//waw==", "review"=>{"comment"=>"I like DSOTM"}, "commit"=>"Create Review", "album_id"=>"6"}
Album Load (0.4ms) SELECT "albums".* FROM "albums" WHERE "albums"."id" = ? LIMIT ? [["id", 6], ["LIMIT", 1]]
(0.2ms) begin transaction
(0.2ms) rollback transaction
Rendering reviews/new.html.erb within layouts/application
Rendered reviews/_form.html.erb (6.8ms)
Rendered reviews/new.html.erb within layouts/application (17.8ms)
Completed 200 OK in 251ms (Views: 222.5ms | ActiveRecord: 0.7ms)
Not sure what's going on. Any help would be appreciated. Here are my routes:
Rails.application.routes.draw do
devise_for :users
resources :albums do
resources :reviews
end
root 'albums#index'
end
Here is the review form I am attempting to build:
<%= simple_form_for([#album, #album.reviews.build]) do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<%= f.input :comment %>
</div>
<div class="form-actions">
<%= f.button :submit %>
</div>
<% end %>
Here is the reviews controller(have not finished this. Basically an edited scaffold):
class ReviewsController < ApplicationController
before_action :set_review, only: [:show, :edit, :update, :destroy]
before_action :set_album
def index
#reviews = Review.all
end
def show
end
def new
#review = Review.new
end
def edit
end
def create
#review = Review.new(review_params)
respond_to do |format|
if #review.save
format.html { redirect_to #review, notice: 'Review was successfully created.' }
format.json { render :show, status: :created, location: #review }
else
format.html { render :new }
format.json { render json: #review.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #review.update(review_params)
format.html { redirect_to #review, notice: 'Review was successfully updated.' }
format.json { render :show, status: :ok, location: #review }
else
format.html { render :edit }
format.json { render json: #review.errors, status: :unprocessable_entity }
end
end
end
def destroy
#review.destroy
respond_to do |format|
format.html { redirect_to reviews_url, notice: 'Review was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_review
#review = Review.find(params[:id])
end
def set_album
#album = Album.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def review_params
params.require(:review).permit(:comment)
end
end
Review model:
class Review < ApplicationRecord
belongs_to :user
belongs_to :album
end
Album model:
class Album < ApplicationRecord
has_many :reviews
belongs_to :user
end

A validation error is preventing the model from being persisted. You're not seeing that error because you create a new instance of it in this line:
simple_form_for [#album, #album.reviews.build]
You ought to build the review in advance in your controller, and replace that line with:
simple_form_for [#album, #review]
Then you should see the validation error. If this still isn't showing, or if one of your attributes gets erased, it might be because your parameters whitelist is excluding them. You can get more info by building and validating the object in the Rails Console, then checking the errors on the model instance.

Related

Please review the problems below: Rails created post

I dont't know why but when i'm trying to create post, i got this error.
I created a scaffold "post"
Then i wanted to get my posts in a different controller, in my Controller home.
I put "belongs_to :home" in my Post.rb
In this step, all is fine.
But when i'm trying to create post, i got this "Please review the problems below:"
Processing by PostsController#create as HTML Parameters: {"utf8"=>"✓", "authenticity_token"=>"0QgNSnhZWnsa+U9iYi1RB2Yk+qoW1be0Mj/o3579Es74oKBD452HQxZF144KBhR+in7UaSf9OLpzAyn8aJrB6A==", "post"=>{"title"=>"sfsf", "content"=>"sdfsfsfs", "author"=>"sdfsfsdf"}, "commit"=>"Create Post"} (0.4ms) BEGIN (0.3ms) ROLLBACK Rendering posts/new.html.erb within layouts/application Rendered posts/new.html.erb within layouts/application (14.6ms) User Load (0.7ms) SELECT users. FROM users WHERE users.id = 2 ORDER BY users.id ASC LIMIT 1 Rendered layouts/_header.html.erb (6.8ms) Rendered layouts/_footer.html.erb (0.9ms) Completed 200 OK in 1512ms (Views: 381.2ms | ActiveRecord: 1.4ms)*
post_controller.rb
class PostsController < ApplicationController
before_action :set_post, only: [:show, :edit, :update, :destroy]
# GET /posts
# GET /posts.json
def index
#posts = Post.all.order("created_at DESC")
end
# GET /posts/1
# GET /posts/1.json
def show
#posts
end
# GET /posts/new
def new
#post = Post.new
end
# GET /posts/1/edit
def edit
end
# POST /posts
# POST /posts.json
def create
#post = Post.new(post_params)
respond_to do |format|
if #post.save
format.html {redirect_to #post, notice: 'Article crée.'}
format.json {render :show, status: :created, location: #post}
else
format.html {render :new}
format.json {render json: #post.errors, status: :unprocessable_entity}
end
end
end
# PATCH/PUT /posts/1
# PATCH/PUT /posts/1.json
def update
respond_to do |format|
if #post.update(post_params)
format.html {redirect_to #post, notice: 'Article édité.'}
format.json {render :show, status: :ok, location: #post}
else
format.html {render :edit}
format.json {render json: #post.errors, status: :unprocessable_entity}
end
end
end
# DELETE /posts/1
# DELETE /posts/1.json
def destroy
#post.destroy
respond_to do |format|
format.html {redirect_to posts_url, notice: 'Article supprimé.'}
format.json {head :no_content}
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_post
#post = Post.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def post_params
params.require(:post).permit(:title, :content, :author)
end
end
post/new.html.erb
<div class="container left-box">
<h1 class="left-box-title">Ajouter un article</h1>
<%= simple_form_for #post, wrapper: :vertical_form do |f| %>
<%= f.error_notification %>
<%= f.input :title, label: 'Titre' %>
<p>Contenu</p>
<%= f.text_area :content, class: 'col-md-12 form-control content_post_create' %>
<%= f.input :author, label: 'Auteur' %>
<%= f.button :submit, class: "btn-primary", label: 'Mettre en ligne' %>
<%= f.button :button, "Recommencer", type: "reset", class: "btn-outline-secondary" %>
<% end %>
<%= link_to "Retour à l'accueil", posts_path %>
</div>
Your error comes from belongs_to :home in Post.rb:
The belongs_to association creates a one-to-one match with another
model. In database terms, this association says that this class
contains the foreign key. (source)
If you add the error full messages in your form like this:
<%= simple_form_for #post, wrapper: :vertical_form do |f| %>
<ul>
<% #post.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
...
<% end %>
you should see this error: Home must exist
To fix your issue you can remove the belongs_to association or, if Home is really a model, add the home_id to #post in your create action before saving.

Unpermitted parameter using fields_for Rails

I got such message in console when trying to use fields_for in Rails:
Parameters: .... "task"=>{"task_name"=>"111", "tag"=>{"tag_text"=>"222"}}, "commit"=>"Save"}
Unpermitted parameter: tag
My models with has_many and belongs_to:
class Task < ActiveRecord::Base
has_many :tags
accepts_nested_attributes_for :tags
end
class Tag < ActiveRecord::Base
belongs_to :task
end
Form helper for new/edit page:
<%= form_for(#task) do |f| %>
<%= f.text_field :task_name %>
<%= f.fields_for([#task, #task.tags.build]) do |t| %>
<%= t.text_field :tag_text %>
<% end %>
<%= f.submit 'Save' %>
<% end %>
My Task Controller (I used scaffold to generate it, and its mostly default)
class TasksController < ApplicationController
before_action :set_task, only: [:show, :edit, :update, :destroy]
def index
#tasks = Task.all
end
def show
end
def new
#task = Task.new
#task.tags.build
end
def edit
#task.tags.build
end
def create
#task = Task.new(task_params)
respond_to do |format|
if #task.save
format.html { redirect_to #task, notice: 'Task was successfully created.' }
format.json { render :edit, status: :created, location: #task }
else
format.html { render :new }
format.json { render json: #task.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #task.update(task_params)
format.html { redirect_to edit_task_path, notice: 'Task was successfully updated.' }
format.json { render :edit, status: :ok, location: #task }
else
format.html { render :edit }
format.json { render json: #task.errors, status: :unprocessable_entity }
end
end
end
def destroy
#task.destroy
respond_to do |format|
format.html { redirect_to tasks_url, notice: 'Task was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_task
#task = Task.find(params[:id])
end
def task_params
params.require(:task).permit(:task_name, :task_sum, :status_id, :user_id, :target_release_id, tag_attributes: [:tag_text, :task_id])
end
end
I think the problem is in the way you use fields_for. Try to make this way:
<%= f.fields_for :tags do |t| %>
That way the param tags_attributes will be send and every thing should be fine.
EDIT
Also, if you are using Rails 5, you need to set the belongs_to as optional so the accepts_nested_attributes_for can work properly. So:
class Tag < ActiveRecord::Base
belongs_to :task, optional: true
end
And the parameters sanitization in your tasks_controller.rb you do not need tag_id under tags_attributes:
def task_params:
params.require(:task).permit(:task_name, tags_attributes: [:tag_text])
end
EDIT
I think I found your problem. Try to put tags_attributes instead of tag_attributes in your task_paramsmethod.

Form With Nested Attributes Not Saving Rails 5

I have a Client and Office Address Model, I want to create the office address when the client is created, so to do this I have decided to go the nested attribute direction.
When I try to create the Client with the Office Address I get this in the server output, doesn't give me much to go on and not sure how to proceed.
Started POST "/clients" for 127.0.0.1 at 2016-10-26 21:57:06 -0600
Processing by ClientsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"oC4Bwgw8zQrQCGU6RVGXXVwgWGIbOGmyP9gmJYUbyKXVXzgdeRGrp/wMnsmbF6spSeNxTpcHLJx+ZceBKjHxvQ==", "client"=>{"account_id"=>"", "name"=>"Test Client", "client_type"=>"Corp", "client_ident"=>"1234567890", "office_address_attributes"=>{"client_id"=>"", "unit_number"=>"317", "street_number"=>"1717", "street_name"=>"60 st SE", "city"=>"Clagary", "prov_state"=>"Alberta", "postal_zip"=>"T2A7Y7", "country"=>"CA"}}, "commit"=>"Create Client"}
Account Load (0.1ms) SELECT "public"."accounts".* FROM "public"."accounts" WHERE "public"."accounts"."subdomain" = $1 LIMIT $2 [["subdomain", "shawnwilson"], ["LIMIT", 1]]
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2 [["id", 1], ["LIMIT", 1]]
(0.1ms) BEGIN
(0.1ms) ROLLBACK
Rendering clients/new.html.erb within layouts/application
Rendered clients/_form.html.erb (32.8ms)
Rendered clients/new.html.erb within layouts/application (34.4ms)
Rendered shared/_signed_in_nav.html.erb (0.7ms)
Completed 200 OK in 109ms (Views: 102.0ms | ActiveRecord: 1.2ms)
So when I create the client I want to associate the client to the account and I want to associate the OfficeAddress to the Client.
My Client Model
class Client < ApplicationRecord
belongs_to :account, required: true
has_one :office_address
validates :office_address, presence: true
accepts_nested_attributes_for :office_address
end
My Office Address Model
class OfficeAddress < ApplicationRecord
belongs_to :client, required: true
end
My Client Controller
class ClientsController < ApplicationController
before_action :set_client, only: [:show, :edit, :update, :destroy]
# GET /clients
# GET /clients.json
def index
#clients = Client.all
end
# GET /clients/1
# GET /clients/1.json
def show
end
# GET /clients/new
def new
#client = Client.new
#client.build_office_address
end
# GET /clients/1/edit
def edit
end
# POST /clients
# POST /clients.json
def create
#client = Client.new(client_params)
respond_to do |format|
if #client.save
format.html { redirect_to #client, notice: 'Client was successfully created.' }
format.json { render :show, status: :created, location: #client }
else
format.html { render :new }
format.json { render json: #client.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /clients/1
# PATCH/PUT /clients/1.json
def update
respond_to do |format|
if #client.update(client_params)
format.html { redirect_to #client, notice: 'Client was successfully updated.' }
format.json { render :show, status: :ok, location: #client }
else
format.html { render :edit }
format.json { render json: #client.errors, status: :unprocessable_entity }
end
end
end
# DELETE /clients/1
# DELETE /clients/1.json
def destroy
#client.destroy
respond_to do |format|
format.html { redirect_to clients_url, notice: 'Client was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_client
#client = Client.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def client_params
params.require(:client).permit(:account_id, :name, :client_type, :client_ident, office_address_attributes: [:unit_number, :street_number, :street_name, :city, :prov_state, :postal_zip, :country, :client_id])
end
end
My Form
<%= simple_form_for(#client) do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<%= f.input :account_id %>
<%= f.input :name %>
<%= f.input :client_type %>
<%= f.input :client_ident %>
</div>
<%= f.fields_for :office_address do |oa| %>
<%= oa.input :client_id %>
<%= oa.input :unit_number %>
<%= oa.input :street_number %>
<%= oa.input :street_name %>
<%= oa.input :city %>
<%= oa.input :prov_state %>
<%= oa.input :postal_zip %>
<%= oa.input :country %>
<% end %>
<div class="form-actions">
<%= f.button :submit %>
</div>
<% end %>
Any assistance here would be much appreciated!
EDIT # 1 - Adds Byebug Errors
(byebug) #client.errors
#<ActiveModel::Errors:0x007fb249813488 #base=#<Client id: nil, account_id: nil, name: "Test Client", client_type: "Corp", client_ident: "1234567890", created_at: nil, updated_at: nil>, #messages={}, #details={}>
(byebug)
If you don't want to turn off validation on related models ( which is not ideal in some cases ) then you should set inverse_of like so
has_one :office_address, inverse_of: :client
inverse_of is really worth knowing about, this blog explains it well:
https://www.viget.com/articles/exploring-the-inverse-of-option-on-rails-model-associations
Please change you association as per below:
class OfficeAddress < ApplicationRecord
belongs_to :client, optional: true
end
Rails 5 association belongs to filed validate your client id, so your entry is getting rollback.
I fixed this issue by adding update_attributes to the create method of the client controller. like so:
def create
#client = Client.new(client_params)
respond_to do |format|
if #client.save
### This is what I added ###
#client.update_attributes!(account_id: #current_account.id)
#client.office_address.update_attributes!(client_id: #client.id)
format.html { redirect_to #client, notice: 'Client was successfully created.' }
format.json { render :show, status: :created, location: #client }
else
puts #client.errors
format.html { render :new }
format.json { render json: #client.errors, status: :unprocessable_entity }
end
end
end
My not be the best solution, however it gets it working.

ruby on rails 4 simple_form simple_fields_for not rendering html code in nested model

I'm having some trouble getting a form to render correctly for a nested model. Basically, I have 2 models a Question model and an Answer model. The Question models has_many Answers and an Answer belongs_to a Question. So, as per the documentation here and here, I've set up my model, controller and form as follows:
Question Model:
class Question < ActiveRecord::Base
has_many :answers, :dependent => :destroy
accepts_nested_attributes_for :answers, :reject_if => lambda {|attrib| attrib[:content].blank? }, :allow_destroy => true
validate :validate_answers
def validate_answers
remaining_answers = answers.reject(&:marked_for_destruction?)
errors.add :answers, "At least 4 answers are required." if remaining_answers < 4
end
end
Answer Model:
class Answer < ActiveRecord::Base
belongs_to :question
end
questions_controller.rb
class QuestionsController < ApplicationController
before_action :set_question, only: [:show, :edit, :update, :destroy]
# GET /questions
# GET /questions.json
def index
#questions = Question.all
end
# GET /questions/1
# GET /questions/1.json
def show
end
# GET /questions/new
def new
#question = Question.new
4.times { #question.answers.build }
end
# GET /questions/1/edit
def edit
end
# POST /questions
# POST /questions.json
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 :show, status: :created, location: #question }
else
format.html { render :new }
format.json { render json: #question.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /questions/1
# PATCH/PUT /questions/1.json
def update
respond_to do |format|
if #question.update(question_params)
format.html { redirect_to #question, notice: 'Question was successfully updated.' }
format.json { render :show, status: :ok, location: #question }
else
format.html { render :edit }
format.json { render json: #question.errors, status: :unprocessable_entity }
end
end
end
# DELETE /questions/1
# DELETE /questions/1.json
def destroy
#question.destroy
respond_to do |format|
format.html { redirect_to questions_url, notice: 'Question was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_question
#question = Question.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def question_params
params.require(:question).permit()
end
end
and the app/views/questions/_form.html.erb:
<%= simple_form_for #question do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<p>
<%= f.label :question_stem, "Question" %>
<%= f.text_area :question_stem, :rows => 3 %>
</p>
<p>
<% f.simple_fields_for :answers do |builder| %>
<%= builder.label :answer_text, "Answer" %><br>
<%= builder.text_area :answer_text %>
<% end %>
</p>
</div>
<div class="form-actions">
<%= f.button :submit, "Create Question" %>
</div>
<% end %>
However, when I point my browswer to http://localhost:3000/questions/new
this is what I get:
Any idea what is going on? The rails console shows that the request was received and that the form was rendered:
Started GET "/questions/new" for 127.0.0.1 at 2015-08-27 01:03:57 -0500
Processing by QuestionsController#new as HTML
Rendered questions/_form.html.erb (4.9ms)
Rendered questions/new.html.erb within layouts/application (17.3ms)
Completed 200 OK in 221ms (Views: 179.1ms | ActiveRecord: 1.2ms)
I'm stumped as to why the fields for the answer model aren't being rendered. Any help is much appreciated!
The problem is because you are missing = here in this line <% f.simple_fields_for :answers do |builder| %>
It should be
<%= f.simple_fields_for :answers do |builder| %>

Can't Display a value from my rails model

I'm new to Ruby on Rails and I started with a scaffold and added another model manually. I can't seem to get the values from the model I manually generated to display in my index view.
My first model is for Golf Courses names, city, par, and hole_id. The second model is the amount of holes for each course. For some reason I can't get the hole amount to display Below is my code.
Models
class Course < ActiveRecord::Base
has_many :holes
end
class Hole < ActiveRecord::Base
belongs_to :course
end
Controller
class CoursesController < ApplicationController
before_action :set_course, only: [:show, :edit, :update, :destroy]
# GET /courses
# GET /courses.json
def index
#courses = Course.all
#holes = Hole.all
end
# GET /courses/1
# GET /courses/1.json
def show
end
# GET /courses/new
def new
#course = Course.new
end
# GET /courses/1/edit
def edit
end
# POST /courses
# POST /courses.json
def create
#course = Course.new(course_params)
respond_to do |format|
if #course.save
format.html { redirect_to #course, notice: 'Course was successfully created.' }
format.json { render :show, status: :created, location: #course }
else
format.html { render :new }
format.json { render json: #course.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /courses/1
# PATCH/PUT /courses/1.json
def update
respond_to do |format|
if #course.update(course_params)
format.html { redirect_to #course, notice: 'Course was successfully updated.' }
format.json { render :show, status: :ok, location: #course }
else
format.html { render :edit }
format.json { render json: #course.errors, status: :unprocessable_entity }
end
end
end
# DELETE /courses/1
# DELETE /courses/1.json
def destroy
#course.destroy
respond_to do |format|
format.html { redirect_to courses_url, notice: 'Course was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_course
#course = Course.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def course_params
params.require(:course).permit(:name, :city, :hole_id)
end
end
View
<p id="notice"><%= notice %></p>
<p>
<strong>Name:</strong>
<%= #course.name %>
</p>
<p>
<strong>City:</strong>
<%= #course.city %>
</p>
<p>
<strong>Hole:</strong>
<%= #course.holes %>
</p>
<%= link_to 'Edit', edit_course_path(#course) %> |
<%= link_to 'Back', courses_path %>
<%= #course.holes %> gives you an ActiveRecord_Associations_CollectionProxy
You need to ask for its size, length or its count to get the total amount of holes that belong to #course which means you have to say #course.holes.size, #course.holes.length or #course.holes.count. Check the documentation for the differences between these three.

Resources