I am trying to allow for voting on posts in a Ruby on Rails blog that I created. I don't really want to go the plugin or gem route because I think I am close. Here is the situation:
I am displaying all my posts in /posts/index.html.erb through the partial _post.html.erb. With each post I am rendering the following code for the vote button:
<% remote_form_for [#post, Vote.new] do |f| %>
<%= f.hidden_field :ip_address, :value => "#{request.remote_ip}" %>
<%= submit_tag 'Me Too', :class => 'voteup' %>
<% end %>
Which sends the request through the votes controller:
def create
#post = Post.find(params[:post_id])
#vote = #post.votes.create!(params[:vote])
respond_to do |format|
format.html { redirect_to #posts}
format.js
end
end
The error I am getting is Couldn't find Post without an ID which makes sense because I am not on the /posts/show.html.erb page.
Is there a way that I can pass the post_id to the votes_controller (and into the post_id column in the votes table) from the /posts/index.html.erb view?
Try adding this in the view, after the remote_form_for :
<%= f.hidden_field :post_id, :value => #post.id %>
You might also need to to this in the def create
#post = Post.find(params[:vote][:post_id]) #note the added [:vote]
If you look at the params after those changes, it should show:
{"vote"=>{"ip_address"=>"127.0.0.1", "post_id"=> >>actual-post-id-here<< },
"commit"=>"Vote Up ↑" ..........
Also, I recommend having a look at the excellent RailsCasts by Ryan Bates. Lots of great video tutorials there.
Related
I have a form for creating new comments. This code exists in a page that is under a different controller (let's say it's app/views/posts/show.html.erb).
<%= form_for Comment.new do |f| %>
<%= f.label :content %>
<%= f.text_field :content %><br/>
<%= f.submit %>
<% end %>
The form works if I have Comment.new like above, but I want to use an instance variable like form_for #comment, similar to the first code snippet in this link: https://api.rubyonrails.org/v5.2.3/classes/ActionView/Helpers/FormHelper.html
In order to do so, I thought I need to define a new function like this and assign an empty comment. I tried putting this code in both the posts_controller and comments_controller.
def new
#comment = Comment.new
end
But when I replace Comment.new with #comment, I get this error: ActionView::Template::Error (First argument in form cannot contain nil or be empty):
This leads me to believe that neither of the new methods are being called. What am I doing wrong here?
My routes.rb looks like this:
Rails.application.routes.draw do
root to: 'posts#show'
resources :messages
end
if you are using show page (app/views/posts/show.html.erb) to display form
add this line in the show action of posts controller
# posts_controller
def show
#comment = Comment.new
end
and if you also want to submit your form other than the comment's create action mention the url in form_for tag
<%= form_for #comment, url: posts_path do |f| %>
<%= f.label :content %>
<%= f.text_field :content %><br/>
<%= f.submit %>
<% end %>
I'm working on a dynamic form in a Rails app, and I need to insert a variable number of records into a model in a single form submission. I've done this using PHP -> MySQL/Postgres before, but I have no idea how to do it in Rails.
Ultimately, users should be able to create any number of records to be inserted, but in my example below, I'm limiting it to 2... let me see if I can do that, first...
Here's the form - the ids all get a unique suffix because they are being populated dynamically from localStorage objects on submission.
new.html.erb
<%= form_for #entry, html: {id: :new_entry_form} do |f| %>
<% for i in 0..1 %>
<%= f.text_field :name, :id => 'name_#{i}' %>
<%= f.text_field :day, :id => 'day_#{i}' %>
<% end %>
<% end %>
Here's the associated controller - I'm sure that this is missing something, but I don't know what.
def new
#entry = Entry.new
end
def create
#entry = Entry.create(entry_params)
redirect_to "http://localhost:3000/entries"
end
private
def entry_params
params.require(:entry).permit(:name, :day)
end
Any help would be much appreciated.
Follow this link it shows how to create multiple object in one form submit:
http://vicfriedman.github.io/blog/2015/07/18/create-multiple-objects-from-single-form-in-rails/
This isn't really a troubleshooting question but rather a request for an explanation. I'm having a hard time understanding the workings of the form_for method. Could someone explain to me what this method does in this situation. Here is my code for creating a form for the comments feature on a blog application. My code works, so i just want to understand WHY it works and How it works. Thanks!!
Here is my new comment form:
<%= form_for([#post, #post.comments.build]) do |c| %>
<p>
<%= c.label :content, class: "col-md control-label" %><br>
<%= c.text_area :content, rows: "10", class: "form-control" %>
</p>
<p>
<%= c.submit %>
</p>
<% end %>
And here is my code for the comments Controller:
class CommentsController < ApplicationController
def new
#post = Post.find(params[:post_id])
end
def create
#post = Post.find(params[:post_id])
#comment = #post.comments.create(comment_params)
#comment.user_id = current_user.id
#comment.save
#redirect_to post_path(#post)
redirect_to posts_path
end
private
def comment_params
params.require(:comment).permit(:content)
end
end
In particular, what does the "[#post, #post.comments.build]" parameter of form_for do?
First off, there's nothing you can do with form_for that you couldn't do with form_tag (and some extra typing).
What form_for allows you to do is easily create forms that fit with the rails conventions in terms of urls & parameter naming.
The first argument to form_for is the resource that is being edited or created. At it's simplest this might be just #post. The array form is for namespaces or nested resources.
Your example of [#post, #post.comments.build] means that this is a form for a new comment (the last element of the array is an unsaved instance of Comment) that is nested under that specific post. This will result in the form doing a POST request to /posts/1234/comments (assuming the post has an id of 1234). The corresponding nested route needs to exist for this to work.
The second thing form_for does for you is allow you to write c.text_area :content and have that automatically use the correct parameter name (comment[content]) and have the value prefilled with the current value of the comment's content attribute.
The form_for will do a post to a specific resource and help to draw the inputs.
Example 1
form_for(#post) will do a post to myapp/posts/create and draw the posts fields
Example 2
form_for([#post, #post.comments.build]) will do a post to myapp/posts/:post_id/comments/create and draw the comments fields
here [#post, #post.comments.build] means this form is for a new comment, and form will do a POST request to /posts/post_id/comments (post_id is a #post.id)
I have list dropdown list in my activeadmin that populates the recipe and menu. I'm trying to override the create method but it is not working
<%= semantic_form_for [:admin, #menu_recipe] do |f| %>
<p>
<%= f.collection_select :recipe_id,
Recipe.all,:id,:name,:prompt => true%>
</p>
<p>
<%= f.collection_select :menu_id,
Menu.all,:id,:name,:prompt => true%>
</p>
<%= f.buttons :commit %>
<%end%>
Whenever I try to catch the and create or group it, it returns with a Couldn't find Recipe without an ID error
my active admin controller which i override is
ActiveAdmin.register MenuRecipe do
menu :parent => "Manage Package"
form :partial => "menu_recipe"
controller do
def new
new! do |format|
#menu_recipe = MenuRecipe.new
end
end
def create
create! do |format|
recipe = Recipe.find(params[:recipe_id])
menu = Menu.find(params[:menu_id])
#menu_recipe = #menu.add_recipe(menu.id)
if #menu_recipe.save
redirect_to {admin_menu_recipe_url}
end
end
end
end
end
im i doing it right? if anything is needed please just ask thanks in advance
My guess is it's how you are getting the recipe_id. I would maybe debug the params and see what the actual values are.
You may need to do something like this:
params[:menu_recipe][recipe_id]
I decided to start a little project in rails 3 and I am a little bit stuck on a form... Where can I specified the f.submit action should go to a special controller / action ?
The code in the form is:
<%= form_for #user, :url => { :action => "login" } do |f| %>
<div class="field">
<%= f.text_field :email %><br />
<%= f.text_field :password %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
User is defined as #user = User.new in "index" method of "home_controller".
but I have the error:
No route matches {:controller=>"home", :action=>"login"}
as soon as I run http://0.0.0.0:3000
I am very sorry for this newbee question but I cannot find the routing details (I worked a little bit with rails a couple of years ago but...)
Thanks,
Luc
You don't need to specify any action for f.sumbit.
First of all, you need to make sure you put
resources :users
(for example)
in your routes.rb
then if you want to create a user
put
def new
#user = User.new
end
in your users_controller so you have a page to create new user
or you can put #user=User.new anywhere you like, remember to set
the route correctly
then
def create
#user = User.new(params[:id])
if #user.save
sign_in #user
redirect_to #user
else
render 'new'
end
end
is the part that does real work after you hit on submit
the actual part that connect your form with everything else is this line
<% form_for #user do |f| %>
you can change user to other object, and you can also edit form using update action in a controller.
Hope you got the idea
Whenever you use REST objects, the mere:
form_for #article
is enough for the form to find the proper path.
Otherwise, you can use helpers this way:
form_tag(:controller => "people", :action => "search", :method => "get", :class => "nifty_form")
More info here: http://edgeguides.rubyonrails.org/form_helpers.html