Rails - submit and index on same page - ruby-on-rails

I would like to know if there is any way that I can use my index page as submit page too.
for example i want be able to submit post and list already exists posts on same page.

Yes, you can display a form with form_for helper in your index view.
Your index action in posts_controller.rb should look like this:
def index
#post = Post.new
#posts = Posts.all
end
Your view/posts/index.html.erb view should look like this:
<%= form_for(#post) do |f| %>
<%= f.label :title, "Post title" %>
<%= f.text_field :title%>
<%= f.label :content, "Content" %>
<%= f.text_field :content%>
<%= f.submit "Add"%>
<% end %>
<%= render #posts %>
Then you have to create a partial called _post.html.erb in the view/posts folder in order to display the html for every single post.
Note that you still need a create action in your posts_controller, something like:
def create
#post = Post.new(post_params)
redirect_to root_path
end
private
def post_params
params.require(:post).permit(:title, :content)
end
Let me know if it works :)

This is definitely wrong. Instead of routing all the POSTs and GETs to one method, you should read this:
Basically, you'll change your page to post data to a new method via ajax and replace the div element with a partial.

Related

Rails: How to check which form in a view was submitted

There are 2 forms on one page. I want an if else statement in the controller to use different params and variable values depending on which form was submitted. From doing a google search the best I came across was to have a value on the submit button.
<%= f.submit "Save" :value => "x" %>
If this is a plausible way I cant find how to make an if else statement for checking if the submit value is 'x'.
Something like
if submit.value == 'x'
do something
else
do something else
end
Really not sure. If there is another way of having an if else statement in the controller to catch witch form was submitted by using an id or name or whatever I'm happy to hear it.
The value of the submit button can be accessed with the help of params[:commit], so you can use it to check which form is submitted.
if params[:commit] == 'x'
do something
else
do something else
end
#Pavan has the direct answer, however if you're evaluating form submissions by their respective submit values, you've got a major issue with your pattern.
Form
Forms should be a way to pass values to your controller, which will then populate the model. You should not have to determine actions based on those values, unless you have different functionality...
#app/views/posts/index.html.erb
<% #posts.each do |post| %>
<%= form_for post do |f| %>
<%= f.text_field :name %>
<%= f.submit %>
<% end %>
<% end %>
The above will create multiple forms, all submitting to the posts#update method:
#app/controllers/posts_controller.rb
class PostsController < ApplicationController
def update
#post = Post.find params[:id]
#post.update post_params
end
private
def post_params
params.require(:post).permit(:x, :y, :z)
end
end
The values inside those forms don't matter, nor to which post object they were sent; they will all be evaluated in exactly the same way.
--
Actions
The other way around this is to make separate actions for the different forms:
#config/routes.rb
resources :posts do
patch :update_2, on: :member
end
#app/controllers/posts_controller.rb
class PostsController < ApplicationController
def update_2
#post = Post.find params[:id]
#post.param = "value"
#post.update post_params
end
end
#app/views/posts/show.html.erb
<%= form_for #post, url: posts_update_2_path(#post) do |f| %>
<%= f.submit %>
<% end %>
You could use something like
<%=f.submit "Basic update", name: "basic-update" %>
<%=f.submit "Security update", name: "security-update" %>
and then check in your controller:
if params.has_key? "security-update"
#do something
elsif params.has_key? "basic-update"
#do another thing
end

Creating a form in the partials of a rendered collection

I am rendering a collection of Posts:
In posts_controller.rb:
def show
#posts = Post.where("user_id = ?", id)
end
In show.html.erb:
<ol>
<%= render #posts %>
</ol>
In _post.html.erb:
<%= form_for [post, #comment] do |f| %>
<%= f.text_area :content %>
<%= f.submit "Post" %>
<% end %>
The form_for in _post.html.erb is so someone can add a comment to any of the rendered posts. Comments are also of class Post. This means in the posts_controller I need something like #comment = Post.new(post_params) for the form in the partial. If I were only rendering a single Post this wouldn't be a problem. However, I am rendering a collection of Posts, each of which needs a #comment instance variable passed to it. How do I create a #comment instance variable in the posts_controller for each post? And how do I pass these #comments to the partials? And what's the correct code in form_for in the partial?
You should explicitly build the comment for each post like below,
def show
#posts = Post.where("user_id = ?", id)
#posts.each{|post| post.comments.build}
end
and use the same in form,
<%= form_for [post, post.comments.last] do |f| %>
<%= f.text_area :content %>
<%= f.submit "Post" %>
<% end %>
This will build the comment for every post while rendering the page, which can be accessed by post.comments.last. Comment won't exist in database until the comment form associated with post is submitted.
Note: Need to modify post.comments.last if default scope is changed http://apidock.com/rails/ActiveRecord/Base/default_scope/class
You should specify that each post contains a/many comment and build those
class Post
attribute :comments, type:Comment, typecaster: Comment, default: []
end
Class Comment
end
Now in the form you can simply render using
<%=#post.comments%>
PS : Do not keep comment as a post type if you want to avoid rendering comments for comments and so on.(You can use the same type as well)

Rails: Why isn't the 'create' action saving the newly created Quiz instance?

My form gets passed a 'new' Quiz (not saved to the database). My form partial looks like this:
<%= form_for(#quiz) do |f| %>
<p>
<%= f.check_box(:answer1) %>
<%= f.check_box(:answer2) %>
<%= f.check_box(:answer3) %>
<%= f.check_box(:answer4) %>
<%= f.check_box(:answer5) %>
<%= f.check_box(:answer6) %>
<%= f.check_box(:answer7) %>
<%= f.check_box(:answer8) %>
</p>
<p>
<%= f.submit("Get my results!") %>
</p>
<% end %>
Here is my QuizzesController#create action:
def create
#results = Quiz.create(post_params) #from private method
if #results.save
redirect_to results_path
else
#error handle here
end
end
...which gets triggered when the user clicks 'get my results' on my quiz form. And the post_params method looks like this:
def post_params
params.require(:quiz).permit(:id, :user_id, :answer1, :answer2, :answer3, :answer4, :answer5, :answer6, :answer7, :answer8) #add other attributes here
end
My results/index.html.erb looks like this:
<div class="container">
<!-- Example row of columns -->
<div class="row">
<h1>Results</h1>
<p><%= #results.inspect %></p>
</div>
</div>
But that 'inspected' Quiz instance returns 'nil' for all the answers1, answers2 etc attributes. Any idea why that would be? Is there something I'm NOT doing to save the user's answers to the database?
The reason it shows nil is because you are not setting the variable.
After creating and saving, you redirect to results_path and the variable #results does not persist during a redirect. Without seeing the full code, I'll have to guess at your naming conventions but there are two ways to do this.
1) If you want to redirect to the index then in the code for your index action, you can set the variable:
#results = Quiz.last
This is easy to work with in development because you are the only user and this will always return the last quiz you created. Not so great in production.
2) The alternative is to redirect to the show action for that quiz.
def create
#results = Quiz.new(post_params)
if #results.save
redirect_to result_path(#results)
else
# error handle here
end
end
Again, I have had to guess that result_path is the correct path. Without seeing the full routes file, I cannot be sure but you can rename accordingly if necessary.

Getting started with Rails tutorial 5.7 - Data not showing in view

I am trying out ruby on rails, going through the "Getting started with Ruby" tutorial. I have gone through steps to and including 5.7 and by now I should be able to create a new post and view it, the post is created, but the title and text is not showing.
The controller: posts_controller.rb
class PostsController < ApplicationController
def new
end
def create
#post = Post.new(params[post_params])
#post.save
redirect_to #post
end
def show
#post = Post.find(params[:id])
end
private
def post_params
params.require(:post).permit(:title, :text)
end
end
The view to create the post
<h1>New Post</h1>
<%= form_for :post, url: posts_path do |f| %>
  <p>
    <%= f.label :title %><br>
    <%= f.text_field :title %>
  </p>
 
  <p>
    <%= f.label :text %><br>
    <%= f.text_area :text %>
  </p>
 
  <p>
    <%= f.submit %>
  </p>
<% end %>
The show view for showing the post.
<p>
<strong>Title:</strong>
<%= #post.title %>
</p>
<p>
<strong>Text:</strong>
<%= #post.text %>
</p>
My guess is that the issue is with the passing of data to the database, but i can't figure out whats wrong. Any idea?
In the new controller action, be sure to assign a new instance of Post to an instance variable:
# app/controllers/posts_controller.rb
def new
#post = Post.new
end
Then, pass the #post instance variable to the form_for helper in the view:
# app/views/posts/new.html.erb
<%= form_for #post do |f| %>
The form_for helper expects a resource to be passed to it; the form is automatically submitted to the correct route based on the type of resource passed. You're passing a new resource in this instance, so the form is routed to the resource's create action.
I figured out that this line was the issue
#post = Post.new(params[post_params])
It should be
#post = Post.new(post_params)
Thanks to everybody who answered!
you may want to change the title of this post to something like "data not showing in view". here is what i would make sure of: that you have in fact created items in your database, i assume you are using sqlite. you can do this in the rails console. or you can enter directly into the form or "The view to create the post" as you call it.
it seems to me that your show action in your controller and your view are correct -- at least, they should show your data.
even without the form working, your data should still show up -- if you input your data via rails console.

Rails: form_for active record object complaining about no index path

I have a survey model that has no index page. I only want an edit view for this model, but it seems like rails wont let me do that. It complains undefined method surveys_path when I try to use form_for(#survey). Is there anyway around doing this without creating an empty index route/view.
Here is my survey controller so far
class SurveysController < ApplicationController
def show
#survey = Survey.find(params[:id])
end
def edit
#survey = Survey.new
job = Job.find(params[:id])
#survey.job_id = job.id
authorized_user = job.user
unless !is_runner?(current_login) && current_login.id == authorized_user.id
redirect_to jobs_path
end
end
def update
#survey = Survey.new(params[:survey])
end
end
And here is the form partial being rendered in the edit.html.erb
<%= form_for(#survey) do |f| %>
<div class="field">
<%= f.label :speed %><br />
<%= f.text_field :speed %>
</div>
<div class="field">
<%= f.label :service %><br />
<%= f.text_field :service %>
</div>
<div class="field">
<%= f.label :suggestion %><br />
<%= f.text_area :suggestion %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
It shouldn't be asking about surveys_path just for defining a form, but there are some oddities in your controller code that could be causing you grief.
Your edit action should, in the surveys controller of a RESTful app, be using that params[:id] to find an existing survey, why is it finding a job? It should be doing the same as your show action.
Your survey object in the survey edit method is new and unsaved, therefore the form builder will generate a form pointing to a create action rather than an update action. Form builder will generate an edit form only for records that are persisted?
Have you defined the routes for this model? You should have something like the following in your routes file:
resources :surveys, :except => [:index] # will create all rest routes for survey model except for an index route.
You get this error if you mistakenly run your model/table as plural instead of singular. You probably ran something like this:
rails generate model surveys
Instead of this:
rails generate model survey
So, if you run:
rake routes
You'll probably see that all of your routes have an 's' ie. surveys_new.
So, rails is confused. You need to rename your table in a migration.
class ChangePluralNametoSingularforSurveys< ActiveRecord:Migration
def change
rename_table :surveys, :survey
end
end
Then you'll have to rename your files (surveys.rb, etc) manually.
For me, the issue was nested routes. If your object has a parent and its routes are nested, you'll need to do something like:
<%= form_for([#category, #survey]) do |f| %>
...
<% end %>

Resources