Ruby param is missing or the value is empty: group - ruby-on-rails

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.

Related

Why is my form not saving? form_for question

I have this form. I am new to rails and I am trying to write a simple ecommerce site. This is the only part not working. (It worked 2 days ago I sear)
<%= form_tag line_items_path do%>
<%binding.pry%>
<%= hidden_field_tag :lite_item, :order_id, #order.id%>
<%= hidden_field_tag :line_item, :menu_item_id, #menu_item.id%>
<%= number_field_tag :line_item, :quantity, 1 %>
<%= submit_tag "Add to Cart"%>
<% end %>
It gives params that look like:
#<ActionController::Parameters {"authenticity_token"=>"VECKnS5SBot1rCyekepPXZa7TyTYkfFi0KdNRTB617ZnelmQo8Lkz_cJmQ8nAmCHUdDlPu1mpkhrPvMKysfjew", "order_id"=>"1", "menu_item_id"=>"1", "quantity"=>"1", "commit"=>"Add to Cart", "controller"=>"line_items", "action"=>"create"} permitted: false>
The controller for the view looks like this:
class MenusController < ApplicationController
def index
#menu_items = MenuItem.all
end
def show
#menu_item = MenuItem.find(params[:id])
#line_items = current_order.line_items.build
end
end
The form is really going through the line_items controller
def create
binding.pry
#line_item = LineItem.create(line_item_params)
if #line_item.save
#order.line_item_id = #line_item.id
#order.save
redirect_to cart_path(#current_cart), notice: "Item added to cart."
else
redirect_to menu_path(#menu_item), alert: "Item did not add to cart."
end
end
With strong params like this
def line_item_params
params.require(:line_item).permit(:menu_item_id, :quantity, :order_id)
end
It should use the line_items_path POST>
If anything else is needed just ask. Thanks in advance.
There are a lot of problems here.
The signature is hidden_field_tag(name, value = nil, options = {}). So the parameters you would actually be creating with that form is:
{
"lite_item" => "order_id", # check your spelling...
"line_item" => "quantity"
}
Oops. And that not even going to happen as <%= number_field_tag :line_item, :quantity, 1 %> will raise since you're passing an integer where the method expects a hash.
If you really have to create the inputs manually you would want:
<%= hidden_field_tag "line_item[order_id]", #order.id %>
But since you actually have a model there is no reason why you should be using form_tag instead of form_for(#line_item) or form_with(model: #line_item).
<%= form_for(#line_item) do |form| %>
<%= form.hidden_field :order_id %>
<%= form.hidden_field :menu_item_id %>
<%= form.number_field :quantity %>
<%= form.submit_tag "Add to Cart"%>
<% end %>
The controller should also use the correct pluralization for the instance variable:
def show
#menu_item = MenuItem.find(params[:id])
#line_item = current_order.line_items.build
end
Your create method is also pretty questionable. All you should need is:
def create
# use .new not .create
#line_item = LineItem.new(line_item_params)
if #line_item.save
redirect_to cart_path(#current_cart), notice: "Item added to cart."
else
redirect_to menu_path(#menu_item), alert: "Item did not add to cart."
end
end
I have no idea why you think you need to update #order here. Your controller should just really be adding a row to what is essentially a join table.

error "Couldn't find User without an ID" when trying to create a tweet

I'm trying to make a twitter clone where a tweet displays the username of the user next to it. however getting the above error message and highlighting the first line of my create method. any ideas on how to solve.
I've done the association already.
thanks
class TweetsController < ApplicationController
def index
#tweets = Tweet.all.order("created_at DESC")
#tweet = Tweet.new
end
def show
#tweet = Tweet.find(params[:id])
end
def new
# #tweet = Tweet.new
end
def create
#user = User.find(params[:id])
#tweet = Tweet.new(tweet_params)
#tweet.user = #user
if #tweet.save
redirect_to tweets_path
end
end
private
def tweet_params
params.require(:tweet).permit(:content, :user_id)
end
end
tweets
<%= simple_form_for #tweet, id: "form-submit" do |f| %>
<%= f.input :content %>
<%= f.button :submit, class: "btn btn-danger" %>
<% end %>
<% #tweets.each do |tweet| %>
<ul>
<li>
<%= tweet.content %>
<%= tweet.user.username %>
</li>
</ul>
<% end %>
Your form doesn't have id field, so params[:id] is nil.
params hash does not contain id, because of that you are getting this error.
Just modify your create action as
def create
#user = current_user
#tweet = Tweet.new(tweet_params)
#tweet.user = current_user
if #tweet.save
redirect_to tweets_path
end
end
Or
instead of above you can also pass an user_id from the form.
<%= simple_form_for #tweet, id: "form-submit" do |f| %>
<%= f.input :content %>
<%= f.hidden_field :user_id, value: current_user.try(:id) %>
<%= f.button :submit, class: "btn btn-danger" %>
<% end %>
then modify create action as
def create
#tweet = Tweet.new(tweet_params)
if #tweet.save
redirect_to tweets_path
end
end
NOTE: Assuming that you are using devise gem for authentication
You are defining tweet.users after using tweet_params, since for tweet_params the user is not defined, that's why you are getting this error.
By answer accepted here, most appropriate change could be:
def new
#tweet = current_user.tweets.new
end
def create
#tweet = Tweet.new(tweet_params)
if #tweet.save
redirect_to tweets_path
end
end
nothing else was needed to be done.

Rails strong params not passing to object, can't create comment due to missing valid attributes

I'm trying to create a comment on a video show page. When I submit the form, rails gives me a flash notice: "User must exist, Video must exist". Not sure why my strong params aren't going through to the create method.
comments_controller.rb
def create
#user = current_user
#video = Video.find(params[:video_id])
#comment = Comment.new(comment_params)
#post = #video.post
if #comment.save
flash[:notice] = "Comment successfully created"
redirect_to post_video_path(#post, #video)
else
#errors = #comment.errors.full_messages.join(', ')
flash[:notice] = #errors
render :'videos/show'
end
private
def comment_params
params.require(:comment).permit(
:body,
:user,
:video
)
end
models/comment.rb
class Comment < ActiveRecord::Base
belongs_to :user
belongs_to :video
validates :body, presence: true
end
models/video.rb
class Video < ActiveRecord::Base
belongs_to :user
belongs_to :post
has_many :comments
end
views/videos/show.html.erb
<%= #video.title %>
<%= content_tag(:iframe, nil, src: "//www.youtube.com/embed/#{#video.embed_id}") %>
<%= link_to "Delete Video", post_video_path(#post, #video), method: :delete %>
<%= link_to('Back', user_post_path(#user, #post)) %>
<h3>Comments</h3>
<%= form_for [#video, #comment] do |f| %>
<%= f.label(:body, "Comment") %>
<%= f.text_area(:body) %>
<%= f.submit("Submit Comment") %>
<% end %>
<% unless #comments.nil? %>
<% #comments.each do |comment| %>
<%= comment.body %>
<%= comment.user %>
<% end %>
<% end %>
I tried adding this to the create method...
#comment.user = current_user
#comment.video = #video
That allowed the comment to save but instead of displaying the comment.body, it displayed the comment object. It still doesn't explain why the strong params aren't being passed.
This is probably a nested params issue and how you have the strong params defined. Check this answer for more information.
If you need to see what is in the params, insert a pry statement into the controller and inspect it there.
Good luck!
There are multiple things you should look at. I have made multiple changes to your code. Go through them.
In your videos/show.html.erb
<%= form_for Comment.new do |f| %>
<%= f.label(:body, "Comment") %>
<%= f.text_area(:body) %>
<%= f.hidden_field :video_id, :value => #video.id %>
<%= f.submit("Submit Comment") %>
<% end %>
Send video_id using hidden_field. Do not send current user id for security reasons. If you take current user id from form end user can easily edit your form in html and pass someone else's user id and this will be one of the easiest and major vulnerability.
In comments_controller.rb
def create
#comment = Comment.new(comment_params)
#comment.user = current_user # we are making sure that current_user is set to comment.
if #comment.save
flash[:notice] = "Comment successfully created"
redirect_to post_video_path(#comment.video.post, #comment.video)
else
#errors = #comment.errors.full_messages.join(', ')
flash[:notice] = #errors
render :'videos/show'
end
end
private
def comment_params
params.require(:comment).permit(:body, :user, :video_id)
# We are permitting video_id instead of video
end
I got this to work but I'm not sure if this addresses the security concerns that #Dinesh raised.
comments_controller.rb
def create
#user = current_user
#video = Video.find(params[:video_id])
#comment = Comment.new(comment_params)
#comment.user = #user
#comment.video = #video
#post = #video.post
if current_user == #video.user || current_user.admin
if #comment.save
flash[:notice] = "Comment successfully created"
redirect_to post_video_path(#post, #video)
else
#errors = #comment.errors.full_messages.join(", ")
flash[:notice] = #errors
render :"videos/show"
end
else
flash[:notice] = "Only OP or admin may comment"
render :"videos/show"
end
end
and
private
def comment_params
params.require(:comment).permit(
:body,
)
end

First argument in form cannot contain nil or be empty rails 4 Associated models

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.

Redirect to show in another controller (Rails)

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

Resources