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.
Related
I'm new to Rails and am trying to create an application that takes a user request. However this is what is happening when I am trying to create a new request.
Request Controller:
class RequestsController < ApplicationController
before_action :set_request, only: [:show, :edit, :update, :destroy]
# GET /requests
# GET /requests.json
def index
#requests = Request.all
end
# GET /requests/1
# GET /requests/1.json
def show
end
# GET /requests/new
def new
#request = Request.new
end
# GET /requests/1/edit
def edit
end
# POST /requests
# POST /requests.json
def create
#request = Request.new(request_params)
respond_to do |format|
if #request.save # <-------------- The problem is here
format.html { redirect_to #request, notice: 'Request was successfully created.' }
format.json { render :show, status: :created, location: #request }
else
format.html { render :new }
format.json { render json: #request.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /requests/1
# PATCH/PUT /requests/1.json
def update
respond_to do |format|
if #request.update(request_params)
format.html { redirect_to #request, notice: 'Request was successfully updated.' }
format.json { render :show, status: :ok, location: #request }
else
format.html { render :edit }
format.json { render json: #request.errors, status: :unprocessable_entity }
end
end
end
# DELETE /requests/1
# DELETE /requests/1.json
def destroy
#request.destroy
respond_to do |format|
format.html { redirect_to requests_url, notice: 'Request was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_request
#request = Request.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def request_params
params.require(:request).permit(:user_id, :description, :created)
end
end
The error says there is no "Create" method in the requests controller, however the method that is saying this is the create method. I think that a problem is that my view isn't passing the description as a parameter and I'm not sure how to do that/why it's not already.
_form.html.erb (Rendered by edit.html.erb):
%= form_for(#request) do |f| %>
<% if #request.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#request.errors.count, "error") %> prohibited this request from being saved:</h2>
<ul>
<% #request.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<center>
<div class="field">
<%= f.label 'Describe your favor' %><br>
<%= f.text_area :description %>
</div>
<div class="actions">
<%= f.submit %>
</div>
</center>
<% end %>
If someone could show me how to pass the description object as a parameter to my create method and get the method to not crash.
Here is the error log:
NoMethodError (undefined method `Request' for #<Request:0x007f9fbd8992e8>):
app/controllers/requests_controller.rb:32:in `block in create'
app/controllers/requests_controller.rb:31:in `create'
Rendered /usr/local/rvm/gems/ruby-2.2.2/gems/actionpack-4.2.5/lib/action_dispatch/middleware/templates/rescues/_source.erb (6.9ms)
Rendered /usr/local/rvm/gems/ruby-2.2.2/gems/actionpack-4.2.5/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb (2.8ms)
Rendered /usr/local/rvm/gems/ruby-2.2.2/gems/actionpack-4.2.5/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb (0.9ms)
Rendered /usr/local/rvm/gems/ruby-2.2.2/gems/actionpack-4.2.5/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb within rescues/layout (29.4ms)
Using Request (or Response) as the name of a model is not a very good idea since you will end up shadowing the request object. Which is a core part of Rails controllers.
It will also make it very confusing to reason about your code since it will collide with a core concept in MVC and web development in general.
Use a thesaurus and find another name for your model.
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.
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| %>
I'm pretty new to Ruby on Rails and I've been trying to develop a simple blog. However when I try to save the new Post, the page reloads a new page and no data is saved. The data however is present in the URI.
Here's my controller:
class PostsController < ApplicationController
before_action :set_post, only: [:show, :edit, :update, :destroy]
# GET /posts
# GET /posts.json
def index
#posts = Post.all
end
# GET /posts/1
# GET /posts/1.json
def show
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: 'Post was successfully created.' }
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: 'Post was successfully updated.' }
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: 'Post was successfully destroyed.' }
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, :category, :body)
end
end
I modified the form produced by scaffolding:
<form role="form">
<%= form_for(#post) do |f| %>
<% if #post.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#post.errors.count, "error") %> prohibited this post from being saved:</h2>
<ul>
<% #post.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="form-group">
<%= f.label :title %><br>
<%= f.text_field :title, class: "form-control" %>
</div>
<div class="form-group">
<%= f.label :category %><br>
<%= f.select(:category, options_for_select(["Programming", "Commentary", "Book Reviews"]), {}, { class: "form-control" })%>
</div>
<div class="form-group">
<%= f.label :body %><br>
<%= f.text_area :body, class: "form-control", rows: "50" %>
</div>
<div class="actions">
<%= f.submit(class: "btn btn-primary") %>
</div>
<% end %>
</form>
Here's my model:
class Post < ActiveRecord::Base
validates :title, presence: true
end
Here's the logs from the server:
Started GET "/posts/new? utf8=%E2%9C%93&authenticity_token=QfJgH82nuYVTEa1vovO4VlIjZmMeJvBLj6bkNKDrz08%3D&post%5Btitle% 5D=Hello&post%5Bcategory%5D=Programming&post%5Bbody%5D=Hello&commit=Create+Post" for 127.0.0.1 at 2014-08-11 11:38:46 -0400
Processing by PostsController#new as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"QfJgH82nuYVTEa1vovO4VlIjZmMeJvBLj6bkNKDrz08=", "post"=> {"title"=>"Hello", "category"=>"Programming", "body"=>"Hello"}, "commit"=>"Create Post"}
Rendered posts/_form.html.erb (2.3ms)
Rendered posts/new.html.erb within layouts/application (3.2ms)
Completed 200 OK in 21ms (Views: 19.1ms | ActiveRecord: 0.0ms)
Your problem is from your invalid HTML - you have an outer <form> tag, and then an inner <form> tag (generated by the Rails form_for). Your browser is following the directive of the outer form, which by default is just to submit to the same page via a GET request.
You want your browser to follow the inner form tag, which is telling the browser to submit a POST request to the create URL. So remove the outer form tag.
I'm starting to wonder if this is a bug with Rails 4, but I'm very new to rails and find myself smacking myself in the forehead eventually with most of the bugs I run in to. But I'm running into a wall on this one.
I have a Post. Posts have comments.
My Comment partial (/views/comments/_comment.html.erb)
<div class="comment-wrap">
<div class="row">
<div class="comment-meta">
<%= comment.commenter %>
<small><%= comment.created_at %></small>
<%= link_to 'Destroy', [comment.post, comment], method: :delete, confirm: 'Are you sure?', class: "tiny button radius right" %>
</div>
<div class="small-2 columns">
<img src="http://placehold.it/50" height="50" width="50" alt="Avatar Image"/>
</div>
<div class="small-10 columns">
<%= comment.body %>
</div>
</div>
</div>
Here is how I render that in .../views/posts/show.html.erb
<h4>Leave a comment</h4>
<%= render "comments/form" %>
<h4>Comments</h4>
<%= render #post.comments %>
Edit:Controller .../controllers/comments/comments_controller.rb
class CommentsController < ApplicationController
def create
#post = post.find(params[:post_id])
#comment = #post.comments.create(comment_params)
redirect_to post_path(#post)
end
def destroy
#post = post.find(params[:post_id])
#comment = #post.comments.find(params[:id])
#comment.destroy
redirect_to post_path(#post)
end
private
def comment_params
params.require(:comment).permit(:commenter, :body, :post_id)
end
end
Edit: Posts Controller
class postsController < ApplicationController
before_action :set_post, only: [:show, :edit, :update, :destroy]
# GET /posts
# GET /posts.json
def index
#posts = post.all
end
# GET /posts/1
# GET /posts/1.json
def show
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: 'post was successfully created.' }
format.json { render action: 'show', status: :created, location: #post }
else
format.html { render action: '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: 'post was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: '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 }
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(:name, :description, :date, :address)
end
end
This will list out the comments, but the first item is always an empty partial, with the placeholder avatar and a delete button. I've checked in rails console to see how many comments a particular post has, just to make sure there wasn't some empty record in the db, but that's not the case. Why am I getting this empty and additional partial that does not match up with a database record?
It is because #post.comments.build in comments/form.html.erb. build() will always create a new empty object, and that comes before render(). Try replacing it with Comment.new so the empty comment won't be associated with the post.
The issue is that the form is above the <%= render #post.comments %> so there is an empty comment when you reach the partial for all the comments, even if there's none in database, put the <%= render "comments/form" %> below to fix this.