I have a form that allows the user to Post in the a group Show method. Upon posting, I want to redirect to the same page showing the new post. I'm using the following, but I get the error below. I'm not sure why #group is nil, because I've defined it in the show of my group controller.
No route matches {:id=>nil} missing required keys: [:id]
for
redirect_to group_path(#group)
<%=form_for([#post]) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class = "field">
<%= f.label :event_name %>
<%= f.collection_select(:event_id, #events, :id, :title) %>
</div>
<div class = "field">
<%= f.text_area :comment, placeholder: "New Post..." %>
</div>
<%= f.hidden_field :user_id, value: current_user.id %>
<%=f.submit "Submit", class: "btn btn-large btn-primary" %>
<%end%>
class PostsController < ApplicationController
def create
if #post = Post.create(post_params)
flash[:success] = "Post Created!"
redirect_to group_path(#group)
else
redirect_to group_url
flash[:alert] = "Sorry - Post not created."
end
end
end
def show
#event = #group.events.build
#post = Post.new
#events = #group.events.includes(:posts)
#group = Group.find(params[:id])
end
In your create action you attempt to use the #group instance variable. You haven't defined it in the create action so you'll need to create it there if you want to use it. Since the call to create is in a separate request cycle the instance variables you defined in the show action are not available.
Update:
To get the group if you have an event_id and event belongs_to :group you would do:
event = Event.find(event_id)
#group = event.group
Set #group in create action. You have not assigned any value to #group there which is why you are getting error.
EDIT
As per your comment A Group has_many events so you can find the group as below:
#group = Event.find(params[:event_id]).group
Related
I'm developing an app with Ruby on Rails. Here is my controller action:
def new
#group = current_user.groups.build(group_params)
if #group.save
flash[:success] = "Group created!"
redirect_to root_url
else
#feed_items = []
render 'static_pages/home'
end
end
My form:
<%= form_for(#group) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="field">
<%= f.text_area :name, placeholder: "Group's name" %>
<%= f.text_area :hashtag, placeholder: "Category" %>
</div>
<%= f.submit "Create", class: "btn btn-primary" %>
<% end %>
When I try to use:
private
def group_params
params.require(:group).permit(:name, :hashtag)
end
I get the following exception:
param is missing or the value is empty: group
I've tried to change :group in require but nothing seems to be working. Any ideas?
param is missing or the value is empty: group
I am trying to display the form but the exception is shown before I
can hit the submit button
Well then you are calling group_params in the wrong method. You should call it in create method. Let me clear up your code which should resolve your problem.
def new
#group = current_user.groups.build
end
def create
#group = current_user.groups.build(group_params)
if #group.save
flash[:success] = "Group created!"
redirect_to root_url
else
#feed_items = []
render 'static_pages/home'
end
end
private
def group_params
params.require(:group).permit(:name, :hashtag)
end
Explanation to the error:
If you see the params hash while displaying the form you won't see any :group key. Since you are calling group_params in the new method, the require will raise an exception when the key is not present,so is the error.
I have a provider model which has many comments. I have a current setup working with the form being:
views/comments/_form.html.erb
<%= form_for([#provider, Comment.new] ) do |f| %>
<%= f.text_area :body, cols: 30, rows: 4, class: 'form-control' %>
<%= f.hidden_field :user_id, value: current_user.id, class: "form-control" %>
<div>
</br>
<%= f.submit :post, class: 'btn btn-primary btn-lg' %>
</div>
<% end %>
But I dont think its right from what iv seen around it should be
<%= form_for([#provider, #comment[) do |f| %>
but this method I get the following error
First argument in form cannot contain nil or be empty
I access my comments form from within my provider show.html.erb like this
<%= render 'comments/form', provider: #provider %>
My comments views are just _form.html.erb and _comments.html.erb which lists all the comments for a given provider.
My comments_controller.rb is as follows
class CommentsController < ApplicationController
before_action :set_provider
def new
#comment = Comment.new
end
def create
#provider = set_provider
#comment = #provider.comments.create!(comment_params)
redirect_to #provider
end
def destroy
#provider = set_provider
#comment = Comment.find(params[:id])
#comment.destroy
redirect_to #provider
end
private
def set_provider
#provider = Provider.find(params[:provider_id])
end
def comment_params
params.require(:comment).permit(:body, :user_id)
end
end
If anyone point me in the right direction that would be very much appreciated.
Found the issue.
Because I was showing the Comments in the show action of my provider model I needed this in the Provider
def show
#comment = Comment.new
#provider = find_provider
end
Works perfectly now.
I'm using rails 4.0.8. I added a comment section to a model called 'Things', but I keep getting the same error "param is missing or the value is empty: thing" when I press the submit comment button. It says the error is in the Things#Controller. What am I doing wrong?
UPDATE: I removed the url path from the form, but a new error returns "Couldn't find Thing without an ID". The error is in Comments#Controller.
VIEW FOR THING/SHOW
<div id= "thing">
<h1>
<%= #thing.name %>
</h1>
<br>
<div id= "commentsection">
Comments
<div id= "comments">
<br>
<% #thing.comments.each do |c| %>
<%= c.username %>
<br>
<%= c.text %>
<% end %>
<%= form_for #comment, :url => thing_path do |f| %>
<%= f.label :username %>
<%= f.text_field :username %>
<%= f.label :comment %>
<%= f.text_field :text %>
<%= f.submit "Enter", class: "btn btn-small btn-primary" %>
<% end %>
</div>
</div>
</div>
THINGS CONTROLLER
class ThingsController < ApplicationController
def show
#thing = Thing.find(params[:id])
#thing.comments.build
#comment = Comment.new
end
def index
end
def new
#thing = Thing.new
#things = Thing.all
end
def create
#thing = Thing.new(thing_params)
if #thing.save
redirect_to #thing
else
render 'new'
end
end
private
def thing_params
params.require(:thing).permit(:name, :avatar)
end
end
COMMENTS CONTROLLER (I put asterisks around the line where the error is)
class CommentsController < ApplicationController
def show
#comment = Comment.find(params[:id])
end
def new
#comment = Comment.new
#comments = Comment.all
end
def create
****#thing = Thing.find(params[:thing_id])****
#comment = #thing.comments.create(comment_params)
redirect_to thing_path(#thing)
end
end
private
def comment_params
params.require(:comment).permit(:user, :text, :upvotes, :downvotes, :thing_id)
end
end
ROUTES
Website::Application.routes.draw do
get "comments/new"
get "comments/show"
get "things/new"
root 'home_page#home'
get "all/things/new" => 'things#new'
get "all/allthings"
resources :things
resources :good_comments
get "things/show"
get "things/results"
end
You are posting the #comment form to post '/things' path.
<%= form_for #comment, :url => thing_path do |f| %>
It should just be <%= form_for #comment do %> (Rails is smart enough to plug in the comments_path) or if you feel like being more explicit (even though it's not necessary)
<%= form_for #comment, url: :comments_path do %>
Another note though, if you want that Comment to be tied to that specific Thing then in your models it should be
Class Thing
has_many :comments
end
Class Comment
belongs_to :thing
end
Then make sure in your database comment has a thing_id foreign_key field and then your form for comment should actually look like
<%= form_for #thing, #comment do %>
<% end %>
I am new to Rails and working on creating a generic "facebook" type of app as practice with users and posts associated with each user. However, I'm currently having an issue where I think the form that I am using to create the posts is also being rendered out as a blank post with no post ID where I display all of the posts in a section below. I think that this post is being shown even before it is being saved to the database.
Here is my code in my view:
<div class="newpostcontainer">
<div class="newposttext">
<%= form_for([#user, #user.posts.build]) do |f| %>
<%= f.text_area :post, size: "69x1" %>
</div>
<div class="newpostsubmitbutton">
<%= f.submit %>
</div>
<% end %>
</div>
<% #user.posts.reverse_each do |p| %>
<div class="postedcontainer">
<div class="minipostpic">
<%= image_tag #user.photo.url, width: 32, height: 32 %>
</div>
<div class="nameofposter"><%= #user.name %></div>
<div class="dateofpost"><%= p.created_at%></div>
<div class="postcontent"><%= p.id%></div> <br>
<div class="postcontent"><%= p.post%></div> <br>
<div class="likecommentdelete">
<%= link_to "Delete", [p.user, p], method: :delete %> | Like | Comment
</div>
</div>
<%end%>
</div>
Here is my controller:
def index
#user = User.find(params[:user_id])
#posts = #user.posts.all
end
def create
#user = User.find(params[:user_id])
#post = #user.posts.create!(post_params)
redirect_to user_path(#user)
end
def show
#user = User.find(params[:user_id])
#post = #user.posts.find(params[:id])
redirect_to user_path(#user)
end
def destroy
#user = User.find(params[:user_id])
#post = #user.posts.find(params[:id])
#post.destroy
if #post.destroy
redirect_to user_path(#user)
else
redirect_to users_path
end
end
private
def post_params
params.require(:post).permit!
end
end
And here is my model:
class Post < ActiveRecord::Base
belongs_to :user
has_many :comments
validates_presence_of :post
end
I'm pretty sure the issue has something to do with my form to create the new post because when I remove it or comment it out, the extra blank post with no post ID goes away.
Any thoughts or suggestions?
Thank you!!
I think you need to permit the field values to be posted:
i.e.,
params.require(:post).permit!
should be
params.require(:post).permit(:name, :post)
then only it will POST I think.
Hope it helps :)
This is because of rails 4 strong parameter feature. You need to whitelist your active models parameters. For more details refer to here.
In your case you need to do something like this:
params.require(:post).permit(:post)
where the ":post" inside require is your model and the other one is your permitted field that is your textarea.
Several issues -
Form
<%= form_for([#user, #user.posts.build]) do |f| %>
Why are you building an associative object? #user.posts.build will not persist your data, and will cause all sorts of non-conventional issues I would highly recommending building the posts associative object in your controller's new action before using in the view, so you can do this:
#app/controllers/users_controller.rb
def new
#user = current_user
#user.posts.build
end
<%= form_for #user do |f| %>
Association
You're trying to edit the post attribute with this statement:
<%= f.text_area :post, size: "69x1" %>
This won't work in any circumstance, as :post is an association, not an object. Rails only allows you to change / add attributes to specific objects, which means you'll be better doing something like this:
<%= f.fields_for :posts do |p| %>
<%= p.text_area :title %>
<%= p.text_area :body %>
<% end %>
Strong Params
You're currently permitting all your params? You'll be better doing this:
def post_params
params.require(:user).permit(posts_attributes: [:title, :body])
end
Use Posts Controller
A better way will be to just use the posts_controller, like this:
#app/controllers/posts_controller.rb
def new
#post = Post.new
end
def create
#post = Post.new(post_params)
#post.save
end
#app/views/posts/new.html.erb
<%= form_for #post do |f| %>
<%= f.text_field :title %>
<%= f.text_field :body %>
<% end %>
My app has a user model and a post model, where user has_many posts and posts belong_to users. Posts are displayed on a user's profile page. I'd like for any user to be able to post on his own, or any other user's profile page. However, the problem I'm having is that while I know who is posting (current_user), I don't know whose profile current_user is on. I need to know this in order to assign the new post to that user's posts. How do I extract user id information from the profile currently being viewed, so I know where to assign the new post?
My micropost controller looks like:
class MicropostsController < ApplicationController
before_filter :authenticate_user!
def create
#user_of_page = User.find_by_name(params[:id])
#micropost = #user_of_page.microposts.build(params[:micropost])
if #micropost.save
flash[:success] = "Micropost created!"
redirect_to :back
else
redirect_to about_path
end
end
def destroy
end
end
But I'm getting a NoMethodError: undefined method `microposts' for nil:NilClass. I assume this is because I'm making some mistake with the creation of the user_of_page variable, but I don't know what that is!
SOLUTION
Thanks Sam. I took your advice and ended up doing it like this:
I added a column to my Micropost table called belongs_to_id.
I then passed the id of the user whose profile is being shown from the user show view to the micropost controller using a hidden field in the micropost form, like so:
<%= form_for #micropost do |f| %>
<%= render 'shared/error_messages', :object => f.object %>
<div class="field">
<%= f.label :content, "Why that mood?" %>
<%= f.text_area :content %>
</div>
<div class="field">
<%= f.hidden_field :author, :value => current_user.name %>
<%= f.hidden_field :belongs_to_id, :value => #user.id %>
<%= f.hidden_field :agree, :value => "0" %>
<%= f.hidden_field :disagree, :value => "0" %>
<%= f.hidden_field :amused, :value => "0" %>
</div>
<div class="actions">
<%= f.submit "Submit" %>
</div>
<% end %>
I then used this id value to search for the user to assign the post to, in the micropost controller, like so:
class MicropostsController < ApplicationController
before_filter :authenticate_user!
def create
#user_of_page = User.find(params[:micropost][:belongs_to_id])
#micropost = #user_of_page.microposts.build(params[:micropost])
if #micropost.save
flash[:success] = "Micropost created!"
redirect_to :back
else
redirect_to about_path
end
end
def destroy
end
end
Magic! Thanks again, you helped me to see it in the right way.
I would do it like this:
class profiles_controller < AC
...
def show
#profile = User.find(params[:id]).profile || current_user.profile
#post = Post.new
end
..
end
/profiles/show.html.erb
...
Name: <%= #profile.full_name %>
...
<%= form_for #post do |f| %>
<%= hidden_field_tag #profile.user %>
...
<% end %>
class microposts_controller < AC
def create
profile_user = User.find(params[:user_id]) # Owner of the profile current_user is on
..
end
end
Not tested. Hope this helps.