Embed a Rails form partial into another page - ruby-on-rails

I'm building a rails 4.2.0 app with a contact us page (this page does have a semi-empty controller). I'm trying to embed a form partial from another controller.
Here is the code (minus the text):
<% if user_signed_in? %>
<% render 'enquiries/form' %>
<% end %>
When I run this I get the error 'First argument in form cannot contain nil or be empty'.
My enquiries form looks like a basic rails form:
<%= form_for #enquiry do |f| %>
<% if #enquiry.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#enquiry.errors.count, "error") %> prohibited this enquiry from being saved:</h2>
<ul>
<% #enquiry.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :subject, "Subject:" %><br>
<%= f.text_field :subject %>
</div>
<div class="field">
<%= f.label :e_description, "Description:" %><br>
<%= f.text_area :e_description %>
</div>
<div class="actions">
<%= f.submit %>
</div>
What could be the possible reason for the error? Or is there a better way of embedding a view into another?
Update/Edit:
Here's the routes:
devise_for :users
resources :rooms do
resources :viewings
end
resources :rmcats
resources :extras
resources :extracats
resources :enquiries
root :to => redirect('/pages/home')
get 'pages/home'
get 'pages/contactus'
And the enquiry controller:
class EnquiriesController < ApplicationController
before_action :set_enquiry, only: [:show, :edit, :update, :destroy]
# GET /enquiries
def index
#enquiries = Enquiry.all
end
# GET /enquiries/1
def show
end
# GET /enquiries/new
def new
#enquiry = Enquiry.new
end
# GET /enquiries/1/edit
def edit
end
# POST /enquiries
def create
#enquiry = Enquiry.new(enquiry_params)
if #enquiry.save
redirect_to #enquiry, notice: 'Enquiry was successfully created.'
else
render :new
end
end
# PATCH/PUT /enquiries/1
def update
if #enquiry.update(enquiry_params)
redirect_to #enquiry, notice: 'Enquiry was successfully updated.'
else
render :edit
end
end
# DELETE /enquiries/1
def destroy
#enquiry.destroy
redirect_to enquiries_url, notice: 'Enquiry was successfully destroyed.'
end
private
# Use callbacks to share common setup or constraints between actions.
def set_enquiry
#enquiry = Enquiry.find(params[:id])
end
# Only allow a trusted parameter "white list" through.
def enquiry_params
params.require(:enquiry).permit(:subject, :e_description)
end
end
This is the pages controller:
class PagesController < ApplicationController
around_filter :resource_not_found
# def home
# end
private
# If resource not found redirect to root and flash error.
# => For pages this will rarely be needed as it should 404.
def resource_not_found
yield
rescue ActiveRecord::RecordNotFound
redirect_to root_url, :notice => "Page not found."
end
end
Edit:
Log:
Started GET "/pages/contactus" for ::1 at 2015-03-21 01:05:25 +0000
Processing by EnquiriesController#new as HTML
[1m[35mUser Load (0.0ms)[0m SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT 1 [["id", 1]]
Rendered enquiries/_form.html.erb (0.0ms)
Rendered pages/contactus.html.erb within layouts/application (0.0ms)
Completed 200 OK in 235ms (Views: 234.6ms | ActiveRecord: 0.0ms)

It is telling you that #enquiry is nil at the time it is trying to render the form. You need to call the new action to create the #enqiury for the form to represent.
You could change your route to:
get 'pages/contactus' => 'enquiries#new'
Then in your Enquiry controller:
def new
#enquiry = Enquiry.new
render 'pages/contactus'
end
EDIT:
Ok, so now we combine what Friends Systems put in his answer:
<% if user_signed_in? %>
<%= render 'enquiries/form' enquiry: #enquiry %>
<% end %>
And now change any instance of #enquiry in the form to enquiry
This is because you need to pass the variable to the partial.

the problem is, that your #enquiry variable is not defined in the context you are rendering the partial.
its not defined by the controller action that gets called, you should create a instance of Enquiry by calling
#enquiry = Enquiry.new
in your action.
In Addition
to use it somewhere else i would pass the #enquiry instance variable as a locale variable to the partial
<% render 'enquiries/form', :enquiry => #enquiry %>
your form method should then look like this:
<%= form_for enquiry do |f| %>
...
<% end %>
of course all the instances vars should be replaced then. just remove the '#'
EDIT:
According to your controller setup you posted above the best way would be to use something like
#enquiry ||= Enquiry.new
in your form partial to make shure a new instance is created if #enquiry is nil.

Related

Blog App not saving attributes to database upon form submission

I am following a guide to build a blog with rails, simple Post model with title and body.
I am using simple form and upon form submission to create a new post, the post saves created_at and updated_at values, but not the actual content submitted in the form.
I have attempted removing the code for simple form and using Rails native form_for. This DOES save all values to the database. I am new to simple form, not certain whether or not I am using it correctly.
Here is the console record:
Started POST "/posts" for ::1 at 2019-08-17 13:51:01 -0500
Processing by PostsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"qY8kYZxVIMBL8lzHYuQ4qOu6nXsTGLWCRhLPJ2eiAU8EyzR61fZppAFBYmgcm3rx02FYAHcCgFBVlUyDTLtDGA==", "post"=>{"title"=>"Simple Form Test", "body"=>"<p>Test Test Test</p>\r\n"}, "commit"=>"Create Post"}
(0.0ms) begin transaction
SQL (3.3ms) INSERT INTO "posts" ("created_at", "updated_at") VALUES (?, ?) [["created_at", "2019-08-17 18:51:01.325736"], ["updated_at", "2019- 08-17 18:51:01.325736"]]
(7.7ms) commit transaction
Redirected to http://localhost:3000/posts/3
Completed 302 Found in 28ms (ActiveRecord: 11.1ms)
Here is the form:
<%= simple_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 |msg| %>
<li>
<%= msg %>
</li>
<% end %>
</ul>
</div>
<% end %>
<div class="form-group">
<%= f.input :title, class: "form-control" %>
</div>
<div class="form-group">
<%= f.input :body, :as => :ckeditor, input_html: {:ckeditor => {:toolbar => 'FULL'}}, class: "form-control" %>
</div>
<div class="form-group">
<%= f.button :submit %>
</div>
<% end %>
Here is the controller:
class PostsController < ApplicationController
before_action :find_post, only: [:edit, :update, :show, :delete]
# Index action to render all posts
def index
#posts = Post.all
end
# New action for creating post
def new
#post = Post.new
end
# Create action saves the post into database
def create
#post = Post.new
if #post.save(post_params)
flash[:notice] = "Successfully created post!"
redirect_to post_path(#post)
else
flash[:alert] = "Error creating new post!"
render :new
end
end
# Edit action retrives the post and renders the edit page
def edit
end
# Update action updates the post with the new information
def update
if #post.update_attributes(post_params)
flash[:notice] = "Successfully updated post!"
redirect_to post_path(#post)
else
flash[:alert] = "Error updating post!"
render :edit
end
end
# The show action renders the individual post after retrieving the the id
def show
end
# The destroy action removes the post permanently from the database
def destroy
if #post.destroy
flash[:notice] = "Successfully deleted post!"
redirect_to posts_path
else
flash[:alert] = "Error updating post!"
end
end
private
def post_params
params.require(:post).permit(:title, :body)
end
def find_post
#post = Post.find(params[:id])
end
end
Hopin
g to be able to create posts with body and title, and learn more about simple form.
Thanks in advance!
You wrote #post = Post.new without pass your parameters to your object, so when you save you object you save an empty object.
It should be either :
#post = Post.new(post_params)
Or directly
#post = Post.create(post_params)

Rails routing : nested resources

I'm running into a problem when trying to create a new object using nested resources in Rails. My routing is set up as:
resources :coins do
resources :questions
end
When I attempt to create a new question, it does not save. I'm redirected to the 'questions' page and the form from the 'new' page including everything that was typed into it remains on the page (rather than the list of questions that are supposed to be there when it saves). My controller is as follows:
class QuestionsController < ApplicationController
before_action :find_question, only: [:show]
before_action :find_coin
before_action :authenticate_user!, except: [:index, :show]
def index
#questions = Question.where(coin_id: #coin.id).order("created_at DESC")
end
def show
end
def new
#coin
#question = current_user.questions.build
end
def create
#question = current_user.questions.build(question_params)
if #question.save
redirect_to coin_question(#question.coin_id, #question.id)
else
render 'new'
end
end
private
def find_question
#question = Question.find(params[:id])
end
def find_coin
#coin = Coin.find(params[:coin_id])
end
def question_params
params.require(:question).permit(:content, :ques_num, :coin_id)
end
end
My 'new' page then displays the following form:
<%= simple_form_for #question, url: coin_questions_path(#coin.id) do |f| %>
<%= f.input :ques_num %>
<%= f.input :content %>
<%= f.submit "Post", class: "btn btn-primary" %>
<% end %>
This is my first time using nested resources and its tripping me up a little bit. I really appreciate any assistance here.
Your create action is failing and so it's executing the else statement which is just rendering back your form with the data you entered. The easiest thing to do is to just check out the log file and see why the save it being blocked.
go to /log/development.log and if you're using a mac press Command and the down arrow which will bring you all the way to the bottom of the file.
Also you may want to check out your model validations. If you don't have flash setup or aren't outputting the errors to your view a validation may be causing the form not to save and you wouldn't see the errors.
you could add some error handling to your view like this
<%= form_with(model: question, local: true) do |form| %>
<% if question.errors.any? %>
<div id="error_explanation">
<h2 class="text-danger"><%= pluralize(question.errors.count, "error") %> prohibited this question from being saved:</h2>
<ul class="text-danger">
<% question.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
for your controller try
def create
#question = Question.new(question_params)
if #question.save
flash[:success] = "question created successfully!"
redirect_to question_url(#question.id)
else
render 'new'
end
end
I think there will be error to create question.
if #question.save
redirect_to coin_question(#question.coin_id, #question.id)
else
render 'new'
end
So if record have any error to save it will redirect to new form.
Just use following code to know what is the errors to creating question
def create
#question = current_user.questions.build(question_params)
if #question.save
flash[:notice] = 'Question created'
redirect_to coin_question(#question.coin_id, #question.id)
else
flash[:notice] = 'Some error here!'
render 'new'
end
end
You need to setup flash to show flash error.

How to manually save a reference object in Rails

Edit: Main problem was that when I added the reference fields, I did theater:reference and not theater:references so the field was not marked as a foreign key. Once I undid those migrations and redid them correctly, I was able to make this work.
In my showtimes controller, I am trying to automatically set the theater id to whatever theater owns the screen that the user inputed, but when I try to save it as an integer or a string, I get an error. Yet, when I try to save it as a theater object, I get "Unpermitted parameter: theater" from the console and a "Theater must exist" error from the rails application.
showtimes_controller:
class ShowtimesController < ApplicationController
before_action :set_theater, only: [:create, :edit]
before_action :set_showtime, only: [:show, :edit, :update, :destroy]
# GET /showtimes
# GET /showtimes.json
def index
#showtimes = Showtime.all
end
# GET /showtimes/1
# GET /showtimes/1.json
def show
end
# GET /showtimes/new
def new
#showtime = Showtime.new
end
# GET /showtimes/1/edit
def edit
end
# POST /showtimes
# POST /showtimes.json
def create
#showtime = Showtime.new(showtime_params)
respond_to do |format|
if #showtime.save
format.html { redirect_to #showtime, notice: 'Showtime was successfully created.' }
format.json { render :show, status: :created, location: #showtime }
else
format.html { render :new }
format.json { render json: #showtime.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /showtimes/1
# PATCH/PUT /showtimes/1.json
def update
respond_to do |format|
if #showtime.update(showtime_params)
format.html { redirect_to #showtime, notice: 'Showtime was successfully updated.' }
format.json { render :show, status: :ok, location: #showtime }
else
format.html { render :edit }
format.json { render json: #showtime.errors, status: :unprocessable_entity }
end
end
end
# DELETE /showtimes/1
# DELETE /showtimes/1.json
def destroy
#showtime.destroy
respond_to do |format|
format.html { redirect_to showtimes_url, notice: 'Showtime was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_showtime
#showtime = Showtime.find(params[:id])
end
def set_theater
screenInfo = Screen.where("id = ?", params[:showtime][:screen])
params['showtime']['theater'] = Theater.find(screenInfo[0]['theater_id'])
end
# Never trust parameters from the scary internet, only allow the white list through.
def showtime_params
params.require(:showtime).permit(:date, :time, :archived, :movie_id, :theater, :screen)
end
end
showtimes model:
class Showtime < ApplicationRecord
belongs_to :movie
belongs_to :theater
end
Showtimes _form
<%= form_for(showtime) do |f| %>
<% if showtime.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(showtime.errors.count, "error") %> prohibited this showtime from being saved:</h2>
<ul>
<% showtime.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :date %>
<%= f.date_select :date %>
</div>
<div class="field">
<%= f.label :time %>
<%= f.time_select :time %>
</div>
<div class="field">
<%= f.label :archived %>
<%= f.check_box :archived %>
</div>
<div class="field">
<%= f.label :movie_id %>
<%= f.text_field :movie_id %>
</div>
<div class="field">
<%= f.label :screen %>
<%= f.text_field :screen %>
</div>
<%= f.hidden_field :theater, :value => "" %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Error when trying to save as integer:
Theater(#70015922237640) expected, got Fixnum(#11723820)
Error when trying to save as string:
Theater(#70015868755420) expected, got String(#11739240)
Logs when trying to save as Theater object:
Started POST "/showtimes" for IP at 2016-11-08 20:22:37 +0000
Processing by ShowtimesController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"nENPV5d6YRXdcx3H+Xa9ZypGtyFlaTg+zyENGB10TmW9OyWxLR9Dsl7nDoG9irq+3qApiNA2/oEqL5RZ0SXorA==", "showtime"=>{"date(1i)"=>"2016", "date(2i)"=>"11", "date(3i)"=>"8", "time(1i)"=>"2016", "time(2i)"=>"11", "time(3i)"=>"8", "time(4i)"=>"20", "time(5i)"=>"22", "archived"=>"0", "movie_id"=>"2", "screen"=>"1", "theater"=>""}, "commit"=>"Create Showtime"}
[1m[36mScreen Load (0.3ms)[0m [1m[34mSELECT "screens".* FROM "screens" WHERE (id = '1')[0m
[1m[36mTheater Load (0.2ms)[0m [1m[34mSELECT "theaters".* FROM "theaters" WHERE "theaters"."id" = ? LIMIT ?[0m [["id", 1], ["LIMIT", 1]]
Unpermitted parameter: theater
[1m[35m (0.1ms)[0m [1m[36mbegin transaction[0m
[1m[36mMovie Load (0.2ms)[0m [1m[34mSELECT "movies".* FROM "movies" WHERE "movies"."id" = ? LIMIT ?[0m [["id", 2], ["LIMIT", 1]]
[1m[35m (0.2ms)[0m [1m[31mrollback transaction[0m
Rendering showtimes/new.html.erb within layouts/application
Rendered showtimes/_form.html.erb (13.6ms)
Rendered showtimes/new.html.erb within layouts/application (16.4ms)
Completed 200 OK in 323ms (Views: 86.5ms | ActiveRecord: 3.9ms)
How the hell do I save this parameter?
Have you tried assigning your object to an instance variable, and assigning it before saving?
On your before_action
def set_theater
#theather = ... # Code to find the theather
end
On your create action
def create
#showtime = Showtime.new(showtime_params)
#showtime.theather = #theather
... # Code to save and handle errors
end
You use theater instead of theater_id in several places in your code, and you'll need to change it in all the places, in order for this to work.
Firstly - you can't select a theater in our form... html doesn't recognise a type of theaterand will not pass one through - so your form needs to pass the theater_id instead (which will be an integer that it happily can deal with).
# eg here make sure it's a theater_id
<%= f.hidden_field :theater_id, :value => #theater.id %>
next - your require/permit is probably what's throwing some errors - you need that to be theater_id as well:
def showtime_params
params.require(:showtime).permit(:date, :time, :archived, :movie_id, :theater_id, :screen)
end
Now you need to fetch the theater out, using the screen-info param - but also keep in mind that this might come through as nil some times (so a guard-clause is always good):
def set_theater
if params[:showtime].present? && params[:showtime][:screen_id].present?
screen_info = Screen.find(params[:showtime][:screen_id])
#theater = Theater.find(screenInfo.theater_id)
end
end
Note: I have updated naming-schemes to be rail-standard and removed the thing where you try to set the theatre in params as below:
params['showtime']['theater'] = Theater.find(screenInfo[0]['theater_id'])
I don't know what you're actually trying to do with this line of code, but whatever it is, params doesn't work that way - consider that params is "the set of things that were passed through to us from the user, and are then thrown away" - we don't use it to store new values that we create ion the controller. That's what #variables are for
Can you explain more what you're trying to do and we'll figure out the right way to do it :)

Rails Error - params not passing user id from controller

I'm building an Events app and I'm trying to create a link from the Event show page to the event creator's profile but I'm getting the following error -
ActiveRecord::RecordNotFound in UsersController#show
Couldn't find User with 'id'=21
The error highlights this particular line of code in the Users Controller -
def show
#user = User.find(params[:id])
end
The development log produces this output -
Started GET "/users/21" for ::1 at 2016-04-15 12:37:08 +0100
Processing by UsersController#show as HTML
Parameters: {"id"=>"21"}
[1m[36mUser Load (0.1ms)[0m [1mSELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT 1[0m [["id", 8]]
[1m[35mUser Load (0.2ms)[0m SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 21]]
Completed 404 Not Found in 14ms (ActiveRecord: 0.9ms)
ActiveRecord::RecordNotFound (Couldn't find User with 'id'=21):
app/controllers/users_controller.rb:14:in `show'
The user id (in this instance 5) is not being passed.I've tried numerous arguments in the show.html.erb page but none will work. Changing the show argument in the users controller to #user = current_user only succeeds in bringing up the profile of the user viewing the event and not the profile of the event creator.
Here's my code -
Events Controller
class EventsController < ApplicationController
before_action :find_event, only: [:show, :edit, :update, :destroy,]
# the before_actions will take care of finding the correct event for us
# this ties in with the private method below
before_action :authenticate_user!, except: [:index, :show]
# this ensures only users who are signed in can alter an event
def index
if params[:category].blank?
#events = Event.all.order("created_at DESC")
else
#category_id = Category.find_by(name: params[:category]).id
#events = Event.where(category_id: #category_id).order("created_at DESC")
end
# The above code = If there's no category found then all the events are listed
# If there is then it will show the EVENTS under each category only
end
def show
end
def new
#event = current_user.events.build
# this now builds out from a user once devise gem is added
# after initially having an argument of Event.new
# this assigns events to users
end
# both update and create actions below use event_params as their argument with an if/else statement
def create
#event = current_user.events.build(event_params)
# as above this now assigns events to users
# rather than Event.new
if #event.save
redirect_to #event, notice: "Congratulations, you have successfully created a new event."
else
render 'new'
end
end
def edit
# edit form
# #edit = Edit.find(params[:id])
#event = current_user.events.find(params[:id])
end
def update
if #event.update(event_params)
redirect_to #event, notice: "Event was successfully updated!"
else
render 'edit'
end
end
def destroy
#event.destroy
redirect_to root_path
end
private
def event_params
params.require(:event).permit(:title, :location, :date, :time, :description, :number_of_spaces, :is_free, :price, :organised_by, :organiser_profile, :url, :image, :category_id)
# category_id added at the end to ensure this is assigned to each new event created
end
def find_event
#event = Event.find(params[:id])
end
end
Users Controller -
class UsersController < ApplicationController
before_action :authenticate_user!
def new
#user = User.new
end
def show
#user = User.find(params[:id])
end
def create
#user = User.new(user_params)
if #user.save
flash[:success] = "Welcome to Mama Knows Best"
session[:uid] = #user.id
redirect_to root_path
else
render 'new'
end
end
def edit
#user = current_user
end
def update
#user = current_user
if #user.update(user_params)
flash[:success] = "Profile successfully updated!"
redirect_to root_path
else
render 'edit'
end
end
private
def user_params
params.require(:user).permit(:name, :username, :biography, :email, :url)
end
end
Show page -
<%= image_tag #event.image.url %>
<h1><%= #event.title %></h1>
<p>Location </p>
<p><%= #event.location %></p>
<p>Date</p>
<p><%= #event.date.strftime('%A, %d %b %Y') %></p>
<p>Time</p>
<p><%= #event.time.strftime('%l:%M %p') %></p>
<!-- above expresses date and time as per UK expectations -->
<p>More details</p>
<p><%= #event.description %></p>
<p>Number of Spaces available</p>
<p><%= #event.number_of_spaces %></p>
<% if #event.is_free? %>
<p>This is a free event</p>
<% else %>
<p>Cost per person</p>
<p><%= #event.price %></p>
<% end %>
<p>Organiser</p>
<p><%= #event.organised_by %></p>
<p>Organiser Profile</p>
<button><%= link_to "Profile", user_path %></button>
<p>Link to Organiser site</p>
<button><%= link_to "Organiser site", #event.url %></button>
<p>Submitted by</p>
<p><%= #event.user.name %></p>
<% if user_signed_in? and current_user == #event.user %>
<%= link_to "Edit", edit_event_path %>
<%= link_to "Delete", event_path, method: :delete, data: { confirm: "Are you sure?"} %>
<%= link_to "Back", root_path %>
<% else %>
<%= link_to "Back", root_path %>
<%= link_to "Book the Event", new_event_booking_path(#event) %>
<% end %>
routes -
Rails.application.routes.draw do
devise_for :users, :controllers => { registrations: 'registrations' }
resources :users
resources :events do
resources :bookings
end
# get 'welcome/index'
authenticated :user do
root 'events#index', as: "authenticated_root"
end
root 'welcome#index'
# the above method comes from devise and allows for the site to have a home page
# for users not signed in and one for when they are signed in
end
I haven't added anything relating to the users profile on the form partial as I didn't believe it to be relevant. Any help would be much appreciated.
To reiterate your question, you want a link on the event page that goes to the event organiser's profile page?
<p>Organiser Profile</p>
<button><%= link_to "Profile", user_path(#event.user) %></button>
user_path is a path helper in Rails which resolves to RESTful route of /users/:id. This goes in UserController#show and expects params hash to contain :id.
For your case, you are missing the argument. You need to do:
<button><%= link_to "Profile", user_path(current_user) %></button>
It automatically picks up id and passes it to params hash as : {:id => 7}
Doc
You may also want fix other such helpers call:
event_path
edit_event_path with appropriate argument.
What are you using for user authentication, devise or similar gem? Did you build your own? If so do you have current_user defined in the sessions helper? The below code is how current_user could be defined (a la Hartl Rails tutorial). This will allow you to use current_user in views and controllers.
def current_user
if (user_id = session[:user_id])
#current_user ||= User.find_by(id: user_id)
elsif (user_id = cookies.signed[:user_id])
user = User.find_by(id: user_id)
if user && user.authenticated?(:remember, cookies[:remember_token])
log_in user
#current_user = user
end
end
end
I also noticed in your Users Controller under def create. I believe it should be session[:id] instead of session[:uid]. Please excuse me if this is not the case. Hope this helps.

My Ruby on Rails won't post new messages or edit messages

I'm creating a reddit clone where users can post messages and edit them after posting them. I have the views set up to access the posts and to even make a new post, but when I try to edit a post as an administrator or make a new post as a member, the app flashes an error, saying that the topic is blank.
I'm trying to add user avatars to each post, but I'd like to settle this bug before I move forward. I'm not sure what piece of code is responsible for this, but I've narrowed it down to a few culprits.
It could be the render line here:
<h1>Edit Post</h1>
<div class="row">
<div class="col-md-4">
<p>Guidelines for posts</p>
<ul>
<li>Make sure it rhymes.</li>
<li>Use complete sentences.</li>
<li>Post messages with more than 30 characters.</li>
</ul>
</div>
<div class="col-md-8">
<%= render partial: 'form', locals: { topic: #topic, post: #post } %>
</div>
</div>
Here another file that also has this render partial.
<h1>New Post</h1>
<div class="row">
<div class="col-md-4">
<p>Guidelines for posts</p>
<ul>
<li>Make sure it rhymes.</li>
<li>Use complete sentences.</li>
<li>Post messages with more than 30 characters.</li>
</ul>
</div>
<div class="col-md-8">
<%= render partial: 'form', locals: { topic: #topic, post: #post } %>
</div>
</div>
Lastly is render partial:
<%= form_for [topic, post] do |f| %> <!-- It's kind of like a module! -->
<% if post.errors.any? %>
<div class="alert alert-danger"
<h4>There are <%= pluralize(post.errors.count, "error") %>.</h4>
<ul>
<% post.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<%= form_group_tag(post.errors[:title]) do %>
<%= f.label :title %>
<%= f.text_field :title, class: 'form_control', placeholder: "Enter post title" %>
<% end %>
<%= form_group_tag(post.errors[:body]) do %>
<%= f.label :body %>
<%= f.text_area :body, rows: 8, class: 'form-control', placeholder: "Enter post body" %>
<% end %>
<div class="form-group">
<%= f.submit "Save", class: 'btn btn-success' %>
</div>
<% end %>
What do you think? I'm new to Ruby, and partials are cool, but it's still a new concept. And if this the source of the error, How can I fix it?
EDIT: It was noted that I could be my routes, so here is my routes file.
Rails.application.routes.draw do
devise_for :users
resources :users, only: [:update]
resources :topics do
resources :posts, except: [:index]
end
get 'about' => 'welcome#about'
root to: 'welcome#index'
end
Here's the post_controller also:
class PostsController < ApplicationController # using private methods to Refactor code!
def show
#topic = Topic.find(params[:topic_id])
#post = Post.find(params[:id])
end
def new
#topic = Topic.find(params[:topic_id])
#post = Post.new
authorize #post # from include Pundit in the application controller, authorize is an inherited method
end
def create
#topic = Topic.find(params[:topic_id])
#post = current_user.posts.build(post_params)
authorize #post
if #post.save
flash[:notice] = "Post was saved."
redirect_to [#topic, #post]
else
flash[:error] = "There was an error saving the post. Please try again."
render :new
end
end
def edit
#topic = Topic.find(params[:topic_id])
#post = Post.find(params[:id])
authorize #post
end
def update
#topic = Topic.find(params[:topic_id])
#post = Post.find(params[:id])
authorize #post
if #post.update_attributes(post_params)
flash[:notice] = "Post was updated."
redirect_to [#topic, #post]
else
flash[:error] = "There was an error saving the post. Please try again."
render :edit
end
end
private
def post_params
params.require(:post).permit(:title, :body)
end
end
EDIT:
It was noted that the topic_id could be seen as nil, so I looked at the activity log displayed on my terminal.
Started POST "/topics/1/posts" for 127.0.0.1 at 2014-12-12 14:14:46 +0300
Processing by PostsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"glyWpWi1oJpZFuP2g0FvYowq1NG8edZEYzzirnX9pRE=", "post"=>{"title"=>"Hello sdfsd", "body"=>"fdsfsfsd dfdfsdfsfs dsfsdfsfdsfs"}, "commit"=>"Save", "topic_id"=>"1"}
Topic Load (0.1ms) SELECT "topics".* FROM "topics" WHERE "topics"."id" = ? LIMIT 1 [["id", 1]]
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = 8 ORDER BY "users"."id" ASC LIMIT 1
(0.0ms) begin transaction
(0.0ms) rollback transaction
Rendered posts/_form.html.erb (1.4ms)
Rendered posts/new.html.erb within layouts/application (1.8ms)
Completed 200 OK in 73ms (Views: 69.5ms | ActiveRecord: 0.2ms)
Does this mean that the my app recognized the post's topic ID as 1?
Add #post.topic = #topic to your controller after #post is build (to create and update):
...
#post = current_user.posts.build(post_params)
#post.topic = #topic
...

Resources