simple_form_for not showing fields - ruby-on-rails

I have a model (Project), in the 'new' action I have this code
<h1>Create new project</h1>
<% simple_form_for #project, :url => create_project_path do |project_form| %>
<%= project_form.error_messages %>
<ul>
<% project_form.input :name %>
<% project_form.input :subdomain %>
<% project_form.input :allow_email_report_client %>
<% project_form.input :allow_email_post_client %>
<% project_form.submit %>
</ul>
<% end%>
the controller code is simple
I have a load_and_authorize_resource (using CanCan) and the action code is this
def new
#project = Project.new
end
now, I do get a tag rendered but no fields inside this form
I have the exact same thing for Account model and there all of the fields are shown with no problem.
does anyone have an idea what is the problem?

Ah! You're missing the = signs in your fields:
<%= project_form.input :name %>
<%= project_form.input :subdomain %>
....
Without the =, the code within the <% %> will run, but there will be no output.
Also, good to know: in Rails 2.x you do not need the = for the form_for (Rails 3, however does need the =)

Make sure your new action looks like this:
def new
#project = Project.new
end

Related

Rails:ArgumentError in MethodTypes#edit

I tried to make an edit for ruby on rails, but it shows me the argument error about the edit. I am confused about this question.
Then, I have tried to put the different argument into index.html.erb However, it still does not work. For example m.id and m
This is index.html.erb
<% #methodtypes.each do|m| %>
<tr>
<td><%=m.name %></td>
<td><%=m.desp %></td>
</tr>
<%= link_to "Edit", edit_method_types_path(m.id) %>
<% end %>
<%= link_to "Create Method", new_method_types_path %>
This is my controller file:
class MethodTypesController < ApplicationController
def index
#methodtypes = MethodType.all
end
def show
#methodtype = MethodType.find_by_id(params[:id])
end
def create
#methodtype = MethodType.new(method_params)
#methodtype.save
if #methodtype.save
redirect_to method_types_path
else
render :new
end
end
def edit
#methodtype = MethodType.find_by_id(params[:id])
end
def new
#methodtype = MethodType.new
end
private
def method_params
params.require(:method_type).permit(:name, :desp)
end
This is my edit page which is edit.html.erb:
<%= form_for #methodtype do |f| %>
<div>
<%= f.label :name %>
<%= f.text_area :name %>
</div>
<div>
<%= f.label :desp %>
<%= f.text_field :desp %>
</div>
<%= f.submit %>
<% end %>
The result should show that I can edit my text. but, it shows the ArgumentError in MethodTypes#edit. Does someone can give me some suggestion, I do not know how to fix that.....
Wrong edit url path
It should be <%= link_to "Edit", edit_method_type_path(m.id) %> instead of <%= link_to "Edit", edit_method_types_path(m.id) %>
Also check your routes file It seems you are defining
resource: method_types
Change to
resources: method_types
<%= link_to "Edit", edit_method_types_path(m.id) %> should be <%= link_to "Edit", edit_method_type_path(m) %>, note that type is in singular.
Run rails routes -g method_type to confirm it.
Also, change the MethodType.find_by_id(params[:id]) to MethodType.find(params[:id]) in the controller.
Btw, you are calling save twice in your create method:
def create
#methodtype = MethodType.new(method_params)
#methodtype.save # delete this line
if #methodtype.save
redirect_to method_types_path
else
render :new
end
end

Render in a different order on the page breaks the routing

I have Challenges containing Puns, and it is possible to vote on puns. On the Challenge Show page, all puns are rendered and show their votes count. This is currently on the view page:
<%= render #challenge.puns.reverse %>
<br>
<div id="form">
<%= render "puns/form" %>
</div>
I want the puns form to appear above the items (puns) already submitted. But if swap them around, like this:
<div id="form">
<%= render "puns/form" %>
</div>
<%= render #challenge.puns.reverse %>
I get a controller error and pun.id is not suddenly not available and the voting link breaks.
No route matches {:action=>"upvote", :challenge_id=>"9", :controller=>"puns", :id=>nil}, missing required keys: [:id]
Here is the puns/form part that is causing the issue
<% if signed_in? %>
<% if current_user.voted_for? pun %>
<%= pun.votes_for.size %>
<span class="pun_text"><%= link_to pun.pun_text, challenge_pun_path(#challenge, pun.id) %></span>
<% else %>
<%= link_to like_challenge_pun_path(#challenge, pun.id), method: :put do %>
<span class="heart_like">❤</span> <%= pun.votes_for.size %>
<% end %>
<span class="pun_text"><%= link_to pun.pun_text, challenge_pun_path(#challenge, pun.id) %></span>
<% end %>
<% end %>
It is the like_challenge_pun_path that throws an error but I cannot understand why. I am declaring #challenge again here, so it should be able to get the id.
Here is the form for the puns:
<%= form_for([#challenge, #challenge.puns.build]) do |f| %>
<span class=".emoji-picker-container">
<%= f.text_area :pun_text, placeholder: "Add pun", data: { emojiable: true } %>
</span>
<%= f.submit %>
<% end %>
Also, here is my routes setup
resources :challenges do
resources :puns do
member do
put "like", to: "puns#upvote"
put "dislike", to: "puns#downvote"
end
end
end
and the corresponding action to upvote
def upvote
#pun = #challenge.puns.find(params[:id])
#pun.upvote_by current_user
redirect_to #challenge
end
Can anyone help?
I think the code is for the puns collection.
I assume the issue is that in the form you have something like:
#challenge.puns.build
So in #challenge.puns collection appears not persisted record (without id), so path for this model cannot be generated.
As a quick solution I suggest:
<%= render #challenge.puns.reverse.select(&:persisted?) %>
UPDATE:
As I assumed you have
<%= form_for([#challenge, #challenge.puns.build]) do |f| %>
You can also try:
<%= form_for([#challenge, Pun.new]) do |f| %>
Or solve it in the controller. But need to see controller code for it.

Rails 5. How to submit from the form_tag to custom action?

I'm a real newbie at Ruby and Rails, and I've been looking for the solution for two days. I need to submit data from form_tag to action 'create' in my controller to add new entries to database, but looks like I'm doing something terribly wrong, because absolutely nothing happens, and it seems that form_tag doesn't even redirect to needed action.
Here's the page code:
<h1>Todos</h1>
<% #projects.each do |project| %>
<tr>
<h2><%= project.title %></h2>
<% project.todos.each do |todo| %>
<ul style="list-style-type:disc">
<li><%= todo.text %></li>
</ul>
<% end %>
</tr>
<% end %>
<%= form_tag({controller: "mega", action: "create"}, method: "get", remote: true) do %>
<h2>New todo</h2>
<p>
<%= text_field_tag 'text' %>
</p>
<p>
<%= select_tag 'title', options_from_collection_for_select(#projects, 'id', 'title') %>
</p>
<p>
<%= link_to 'CANCEL' %>
<%= link_to 'OK', "", :onclick => "$('#form_id').submit()" %>
</p>
<% end %>
And the controller:
class MegaController < ApplicationController
def index
#projects = Project.all
#todos = Todo.all
end
def update
end
def create
#newTodo = Todo.create(text: params[:text])
#newProject = Project.find_by(title: params[:title])
#newProject.todos << #todo
#newTodo.save
end
end
My routes file. I seriously don't know how it works:
Rails.application.routes.draw do
get 'mega/index'
root 'mega#index'
get 'mega/update'
post 'mega/create'
resources :todos
resources :projects
end
You create resources with a POST request. Never GET.
GET requests should be idempotent - they should not update or alter resources on the server. One very important reason is that they are stored in the browser's history, so pressing the back button will cause unintended consequences for the user.
In Rails flavor MVC instead of tacking the action name on the path of the route you use the HTTP verb to create routes to the correct action:
GET /things things#index
POST /things things#create
I'm not going to attempt to salvage your code (it's deeply flawed) and instead show you how you would solve this the rails way as it is much simpler:
<%= form_for(Todo.new) do |f| %>
<h2>New todo</h2>
<%= f.text_field :text %>
<%= f.collection_select(:project_id, #projects, :id, :title, prompt: true) %>
<%= f.submit %>
<% end %>
This would submit to todos#create - if you want to route it to an unconventional action you can use the url option:
<%= form_for(Todo.new, url: polymorphic_path(controller: 'foo', action: 'bar')) do |f| %>
It's best to learn the rules before you break them.

Create multiple records simultaneously on one form

After trying to accomplish the deceptively tricky task of building a form that enables the creation of multiple users at once, I wanted to pay it forward by sharing how I did it. Somewhat to my surprise, I was unable to find any SO answers that addressed this problem. Instead, the questions/answers kept addressing the scenario of creating a model as well as its associations on one form (using nested_attributes).
I must attribute the answer to a Ryan Bates' post from 2007 http://archive.railsforum.com/viewtopic.php?id=2696.
Your controller
def new
#owners = Array.new(3) { Owner.new } # set up any defaults here
end
def create
#owners = params[:owners].values.collect { |owner| Owner.new(owner) }
if #owners.all?(&:valid?)
#owners.each(&:save!)
redirect_to :action => 'index'
else
render :action => 'new'
end
end
Your View - new.erb.html
<% form_tag :action => 'create' do %>
<% #owners.each_with_index do |owner, index| %>
<% fields_for "owners[#{index}]", owner do |f| %>
First Name: <%= f.text_field :firstname %>
Last Name: <%= f.text_field :lastname %>
<% end %>
<% end %>
<%= submit_tag %>
<% end %>

Creating multiple objects in a form Rails

So I have an interesting problem I'm working on. I am trying to create multiple objects of the same model in one view. I would like to display all the possible objects in my view, check boxes to select which ones to create, then submit and create all the corresponding objects.
Now the objects to select are gotten using an API request and returned in JSON format. The JSON is then displayed on the view for the user to select, then an array containing all the selected objects is sent back to the controller for creation.
Here is the relevant code that I've tried so far.
objects_controller.rb
def new
#possible_objects = <api call to get objs>
#objects = []
end
def create
params[:objects].each do |obj|
# create and save obj
end
end
objects/new.html.erb
<% form_for #objects do |f| %>
<% #possible_objects.each do |api_obj| %>
<%= check_box_tag(api_obj["name"])%>
<%= api_obj["name"] %>
<% end %>
<%= f.submit %>
<% end %>
This is definitely not the right approach, as the form will not accept an empty array as a parameter. I'm not sure where else to go with this, any pointers in the right direction would be great. Thanks.
Thanks to MrYoshiji for pointing me in the right direction, this is what ended up working
objects_controller.rb
def
#possible_objects = <api call to get objs>
end
def create
params[:objects].each do |object|
new_obj = Object_Model.new( <params> )
new_obj.save
if !new_obj.save
redirect_to <path>, alert: new_obj.errors.full_messages and return
end
end
redirect_to <path>, notice: 'Successfully created.'
end
objects/new.html.erb
<%= form_tag objects_path(method: :post) do %>
<% #possible_objects.each do |api_obj| %>
<%= check_box_tag 'objects[]', api_obj %>
<%= possible_object["name"] %>
<% end %>
<%= submit_tag 'Create'%>
<% end %>
Can you try the following?
# view
<% form_tag my_objects_path(method: :post) do |f| %>
<% #possible_objects.each do |api_obj| %>
<%= check_box_tag 'objects[names][]', api_obj["name"] %>
<%= api_obj["name"] %>
<% end %>
<%= f.submit %>
<% end %>
# controller
def create
params[:objects][:names].each do |obj_name|
YourModelForObject.create(name: obj_name)
end
end
See this comment on the documentation of check_box_tag: http://apidock.com/rails/ActionView/Helpers/FormTagHelper/check_box_tag#64-Pass-id-collections-with-check-box-tags

Resources