rails form trying to get the posts path - ruby-on-rails

I cant get the syntax of this correct I'm trying to include :url => posts_path in the form_for section
<% form_for :post do |f| %>
<p>
<%= f.label :text %><br>
<%= f.text_area :text %></p>
<p><%= f.submit %></p>
<% end %>

form_for expects an instance of a model, not a symbol:
<% form_for Post.new do |f| %>
...
<% end %>

There are a few ways to do this. Like #meager, you want to call Post.new. I usually do it in the controller, though.
posts_controller.rb
#post = Post.new
view
<% form_for #post do |f| %>
...
<% end %>
You can use a custom path if that's where you want to send the data. So if you have a special case, you can make a route for it
routes.rb
get '/special', to: 'posts#special'
then you can have a form that says...
<% form_tag special_path do |f| %>
...
<% end %>
and the params will pass as you'd think. Notice the form_tag instead of form_for though.

Related

rails partial form only build and available for post method, can't build for and use for put method (nested route)

i have partial form on my rails project.
this form is for nested route(post and comment), and this form only brings me to make new data.
the url to edit page works well, but when i get into that edit page, form tag was written like -> posts/1/comment (method: post), which makes me can not update data.
my expecting result is -> posts/1/comment/1 (method: put)
form for nested route->
<%= form_with model: [post, post.comments.build] do |f| %>
<div class="form-item-box">
<%= f.hidden_field :post_id %>
<%= f.label :content %>
<%= f.text_field :content %>
<% post.comments.build.errors.full_messages_for(:content).each do |error_message| %>
<div class="warning-box">
<%= error_message %>
</div>
<% end %>
<%= f.submit %>
</div>
<% end %>
edit page->
<%= render partial: "form", locals: { post: #post } %>
on controller (testing for update method works well, so i did not write it. only the problem is form tag build as post method all time.)
def edit
#post = Post.find(params[:post_id])
end
this edit form link is in post's show page, and i written #post in postcontroller
def show
#post = Post.find(params[:id])
end
routes
resources :posts do
resources :comments
end
how can i solve it?
partial form build as -> posts/1/comment (method: post)
my expecting result is -> posts/1/comment/1 (method: put)
i tried change variable for glocal variable, change form for not nested(it works but i thought using nested route is right for this situation)
I think your error is here:
<%= form_with model: [post, post.comments.build] do |f| %>
In post.comments.build you're always initiating a new comment, therefore creating a form to create a new comment (POST), that isn't going to update anything because it doesn't exist yet. Not 100% sure about the logic of your app, but if you want a form to edit each one of the post comments (PUT), you will need to do something like:
<% post.comments.each do |comment| %>
<%= form_with model: [post, comment] do |f| %>
<% #.....
worst case scenario, you could also set manually the attributes of your form, like:
<%= form_with(model: comment, url: edit_post_comment_path(post, comment), method: "put") %>
form for nested route ->
<%= form_with model: [post, comment] do |f| %>
<div class="form-item-box">
<%= f.hidden_field :post_id %>
<%= f.label :content %>
<%= f.text_field :content %>
<% comment.errors.full_messages_for(:content).each do |error_message| %>
<div class="warning-box">
<%= error_message %>
</div>
<% end %>
<%= f.submit %>
</div>
<% end %>
edit page ->
<%= render partial: "form", locals: { post: #post, comment: #comment } %>
comments_controller ->
def edit
#post = Post.find(params[:post_id])
#comment = Comment.find(params[:id])
end
posts_controller ->
def show
#post = Post.find(params[:id])
#comment = Comment.new(post: #post)
end
now works.

Pass new parent object id to link_to

I am trying to save parent as well as child object at the same time using accepts_nested_attributes_for
Code in controller's new method:
def new
#project = Project.new
#project.instances.build
end
and form looks like this:
<%= simple_form_for(#project) do |f| %>
<%= f.input :name %>
<%= link_to "Add New Instance", new_project_instance_path(#project), id: "new_link", remote: true %>
<% end %>
The route entry for this is:
resources :projects do
resources :instances
end
And the fields that need to be displayed instances/_form.html.erb:
<%= form.simple_fields_for :instances do |i| %>
<%= i.input :user_id %>
<%= i.input :password %>
<%= i.input :service_url %>
<% end %>
The issue here project_id being :nil, it is giving error:
No route matches {:action=>"new", :controller=>"instances", :project_id=>nil} missing required keys: [:project_id]
I need to somehow call <%= render 'cdd_instances/form', form: f %>, so that the fields get rendered below the Project details, how should I implement this?
I think your #project is null you have to pass like:
new_project_instance_path(project_id: (#project || ''))
In this case you are not able to pass non-persisted #project to create this link_to url.
I believe you are looking for something like: cocoon.
<%= simple_form_for #project do |f| %>
<%= f.input :name %>
<h3>Instances</h3>
<div id="instances">
<%= f.simple_fields_for :instances do |instance| %>
<%= render 'instance_fields', f: instance %>
<% end %>
<div class="links">
<%= link_to_add_association 'add instance', f, :instances %>
</div>
</div>
<%= f.submit %>
<% end %>
Cheers!

Ruby on Rails - No route matches [POST] "/setor/update"

i'm new to ruby on rails and I keep getting this error when trying to update an object.
here's my controller:
class SetorController < ApplicationController
def index
#setor = Setor.all
end
def new
end
def show
#setor = Setor.find(params[:id])
end
def create
#setor = Setor.new(setor_params)
#setor.save
redirect_to #setor
end
def edit
#setor = Setor.find(params[:id])
end
def update
#setor = Setor.find(params[:id])
if (#setor.update(setor_params))
redirect_to #post
else
render 'edit'
end
end
private def setor_params
params.require(:setor).permit(:nome, :sigla, :cnpj)
end
end
this is the index page - where I link to edit the object:
<%= #setor.each do |s| %>
<%= s.nome %> |
<%= s.sigla %> |
<%= s.cnpj %> |
<%= link_to "edit", edit_setor_path(s.id) %> <br>
<% end %>
and this is the update form:
<h1> Editar Setor </h1>
<%= form_for :setor, url: setor_path(:update) do |f| %>
<p>
<%= f.label :nome %>
<%= f.text_field :nome %> <br>
<%= f.label :sigla %>
<%= f.text_field :sigla %> <br>
<%= f.label :cnpj %>
<%= f.text_field :cnpj %> <br>
</p>
<%= f.submit %>
<% end %>
what am I missing?
Thanks!
First, make sure you have a route that matches edit_setor_path. You can do this by running rails routes in your terminal or by going to the url localhost:3000/rails/info/routes in your browser.
On your index page, you have the following:
<%= link_to "edit", edit_setor_path(s.id) %> <br>
You do not need to pass in the id of the s object. Rails will figure this out on its own. Instead, just pass in the object:
<%= link_to "edit", edit_setor_path(s) %> <br>
Change #setor in the index action of your SetorController to #setors and change #setor in your index.html.erb file to #setors.
Change the :sector in your edit.html.erb to #setor. You can also remove url: setor_path(:update) from the edit.html.erb form.
These changes follow Rails conventions. You should try to follow Rails conventions as much as possible, especially when just learning Rails.
Try to mention #setor object in the form code:
<%= form_for #setor do |f| %>
How about trying something like this:
Rename your controller to setors_controller.rb and change the class name to SetorsController -- this is to follow the typical Rails naming convention.
Then make sure you have a route:
# config/routes.rb
Rails.application.routes.draw do
resources :setors
end
Update your view's form_for tag to use the instance variable set up in the controller:
# app/views/setors/edit.html.erb
# NOTE: folder path above... "setor" is now "setors" to follow the Rails convention
<%= form_for #setor do |f| %>
<p>
<%= f.label :nome %>
<%= f.text_field :nome %> <br>
<%= f.label :sigla %>
<%= f.text_field :sigla %> <br>
<%= f.label :cnpj %>
<%= f.text_field :cnpj %> <br>
</p>
<%= f.submit %>
<% end %>

Rails Nested routes undefined method

I keep getting an
undefined method 'orders_path' for #<#<Class:0x007faefee50a88>:0x007faefee414e8>
when navigating to my new order path url /users/1/orders/new
Been stuck on this, not sure what the deal is.
Routes:
devise_for :users, :path => 'accounts'
resources :users, only: [:index, :show] do
resources :orders
end
root index:
<%= link_to "Create an Order", new_user_order_path(current_user.id) %>
form:
<%= form_for([#user, #order]) do |f| %>
<%= f.hidden_field :user_id %>
<div class="form-group">
<%= f.label :name %><br />
<%= f.text_field :name, autofocus: true, class: "form-control" %>
</div>
<% end %>
new:
<h1>New Order</h1>
<%= render 'form' %>
<%= link_to 'Back', user_orders_path(#user) %>
When you write this:
<%= form_for(#order) do |f| %>
Rails is looking for orders_path, but you don't really have such a route as you have defined your orders resource nested under the users resource. So, you have to pass both: #user and #order to the form like this:
<%= form_for([#user, #order]) do |f| %>
# your code goes here
<% end %>
If you write the form this way, then Rails will look for this path: user_orders_path which will match your defined route and will work and you won't get this error anymore:
undefined method 'orders_path' for #<#<Class:0x007faefee50a88>:0x007faefee414e8>
So, this will fix your current issue. But, there is another issue in your new.html.erb file where you currently have this:
<%= link_to 'Back', user_orders_path %>
You have to pass the #user as an argument to this method:
<%= link_to 'Back', user_orders_path(#user) %>
otherwise, it will fail again.
Hope this helps to solve your problems.
Since orders is nested on top of users, the form_for declaration will need to include both the user, and the order objects.
<%= form_for([#user, #order]) do |f| %>
Your new template will also need to have a reference to the given user.
<%= link_to 'Back', user_orders_path(#user) %>

Rendering partials failing in rails 4

Here's the partial view I'm trying to render if an user is logged in
<div class='row'>
Post a project
<% form_for #project do |f| %>
<%= f.text_field :title, class:'form-control' %>
<%= f.text_area :brief, class: 'form-control' %>
<%= f.submit "Post" %>
<% end %>
In the main view when I try calling the partial, there's no error, but the partial doesn't render
<div class='col-lg-6'>
<% if current_user %>
<% render 'projects/new_project' %>
<% end %>
</div>
This is my current_user method, defined in the application controller. I've also defined it as a helper method to use in a view template.
private
def current_user
#current_user ||= User.find(session[:user_id]) if session[:user_id]
end
helper_method :current_user
What am I doing wrong?
You want to render, you need to output the render's returned value using <%=...:
<%= render 'projects/new_project' %>
The expression(s) within the erb tags only get evaluated without the equals sign. In order to display the result of the expression, you need to include the equals sign; place your code within <%=...%>
Similarly, for you form_for call:
<%= form_for #project do |f| %>
...
<% end %>
You need to appreciate that <%= is an output tag
This means every time you want to output something in a non-native Ruby file (.erb etc), you'll have to use <%=
This is contrary to <% which does not output anything, but still performs the functions you specify
Partial
Also, you need to ensure your partial syntax is right:
#app/views/controller/you_view.html.erb
<%= render partial: "projects/new_project" %>
#app/views/projects/_new_project.html.erb
<%= form_for #project do |f| %>
<%= f.text_field :title, class:'form-control' %>
<%= f.text_area :brief, class: 'form-control' %>
<%= f.submit "Post" %>
<% end %>

Resources