I have a index page and wish to display a form from a different controller that I created on the index page. I have 3 folders in my view. In the folder called index, I have a html file called index and in the folder called job I have form.html and show.html.
so in my index.html I have
<h1>Complete Job Applications</h1>
<%= render 'job/form'%>
When I run the code I receive this error First argument in form cannot contain nil or be empty. I think I know why but am not too sure. Instead of displaying the form so the user can fill out all the needed text fields so it can be submitted it's submitting it right away (just a guess though). Does anyone have any ideas to how I can display a form from another controller on my index page
You will need to initialize the object that is passed to the form, for example, lets say your view looks like this:
# job/form
<%= form_for(some_model_instance, method: :get) do |form|
...
<% end %>
To render that form from another controller's action, make sure to initialize some_model_instance before rendering the partial, so:
# controller which has the index action
def index
#some_model_instance = SomeModel.where(id: 1).first
end
# index.html.erb
<h1>Complete Job Applications</h1>
<%= render partial: 'job/form', locals: { some_model_instance: #some_model_instance } %>
Related
My app is running Rails Rails 7.0.2.3
In my update controller action I have the line:
return render(:edit) unless #user_form.save
This renders the edit view on error .... but errors are not displayed.
In my edit view I am defining the form with:
form_for #user_form, url: user_path(#user_form), method: :patch do |f|
The form submits via turbo. I can see the error being added to #user_form.errors in the controller, but the instance of #user_form in the view is not changing on each form submission. If I output #user_form.inspect to the view - the id remains the same on each submission.
I have tried adding remote: false to the form_for call, but this does not seem to have an effect.
The only solution I have found is to add data: { turbo: false } to the form_for call.
Is there a better way of handling this?
you'll want to use a partial to show the errors.
you'll need to add an update.turbo_stream.erb file to this view's directory. In that file have something like:
<%= turbo_stream.update 'id_of_div_where_you_want_to_show_errors' do %>
<%= render partial: 'partial_that_displays_errors' %>
<% end %>
or your controllers update action you'll want to have something like
respond_to do |format|
format.turbo_stream { turbo_stream.update 'id_of_div_where_you_want_to_show_errors', render partial: 'partial_that_displays_errors' %>
end
Treat all this more like pseudocode and apply it to your own app, it's hard to say what's going on without seeing your code.
I'm learning RoR by building my first app (yay!). I gotta a question thought as rails guides do not cover this topic:
How to render unique results on #show to a user without storing any data in a model?
Steps I want to take:
Create a basic index view with a form_tag that will allow user to submit a link (string) and click submit button
Write Service Objects that will allow me to parse that link and create a response I want user to see
I want to write a #show method in a separate controller that will allow me to display all the data. (I also want to parse my params[:link] in that method using Service Objects.
I want to finally display this data in a table in #show view (probably I need to create a unique #show/[:id] for each user?
Here's what my app looks like at the moment (more or less):
Static Controller (just to render index.html.erb with a form)
class StaticController < ApplicationController
def index
end
end
Static Index view (yup, parsing imgur link here)
<h1>Hello Rails!</h1>
<%= form_tag("/images", method: "post") do %>
<p>
<%= label_tag(:imgur_link) %><br>
<%= text_field_tag(:imgur) %>
</p>
<p>
<%= submit_tag("Get my cards") %>
</p>
<% end %>
Images Controller (where all the magic SHOULD happen)
class ImagesController < ApplicationController
def show
#collection = params[:imgur_link]
#service1 = service1.new(*args).call
#service2 = service2.new(*args).call
...
end
end
Images Show view
Empty as I'm stuck with the Images controller at the moment.
Any help would be more than appreciated.
Thanks!
There is no reason you should put something into storage just in order to display it. If you get to a point when you have the results in your controller, you could just pass them to view in some #variable
As I see, you have set up the form for step 1. If you also have routes.rb call 'images#show' for POST /images, then you will have params[:imgur_link] available in your show action. This should do:
# config/routes.rb
YourApplication.routes.draw do
# ...
post '/images' => 'images#show'
end
Now you have to somehow process that link. Since I don't know what your results should be, I'm going to assume that you have two classes, Service1 and Service2, both of which accept an URL and return collection of results, and both collections hold the elements of the same class. Then you can leave only unique results for your show view, like this:
# app/controllers/images_controller.rb
class ImagesController < ApplicationController
def show
link = params[:imgur_link]
results1 = Service1.new(link).results
results2 = Service2.new(link).results
#results = (results1 + results2).uniq
end
end
Then you can do something with #results in your show view. E.g.
# app/views/images/show.html.erb
<% #results.each do |result| %>
<%= result.inspect %>
<% end %>
Ok, So i'm trying to place the form found in the "_form.html.erb" in the "index.html.erb" of my ruby project crashes with the error
"First argument in form cannot contain nil or be empty"
<%= form_for(#customer) do |f| %>
I know that changing the #customer to Customer.new could fix this but I would like to know why this isn't necessary in one file and it is in another
Why is this happening and how do I make a form that will update the sqlite db on the index page.
#customer is a variable that must be created somewhere in the corresponding controller action. If your #index controller action defines a variable by that name, then you'll be able to use it in the view template; otherwise you'll need to create it like this:
#customer = Customer.new # (or whatever the value is)
When Rails processes a request, it just executes a big (and complex) lump of code that's created from a bunch of different files. First it executes the appropriate controller action, then it executes any Ruby code found inside the corresponding view template. So any variable (or any method name) that is used in the view template, was first defined at some point before that: either in the controller action, or in one of Rails' countless built-in helper files.
When I am using form_for in a index or show page I like to do is set it to new
<%= form_for Customer.new, url: {controller: "customers", action: "create"} do |f| %>
...
<%= f.submit %>
<% end %>
that way there is a object to be created, I also I like to pass in the controller and the action.
the f.error_messages form builder helper has been depreciated in Rails 3.
How do I get the error messages for a form with the opening tag:
<%= form_for Model.new %>
(I'm using Model.new because I want to be able to load an undefined multiple number of these forms onto a single page)
You can't. Not with a form builder like this one.
Basically, error messages are stored inside the object you use to build a form. If you build a new one every time, you get a clean object without errors.
What you need to do is persist the object filled in by the user between requests. Typically this is done by creating a new object in controller:
#model = Model.new
The essence of this is, that new view uses #model to render a form. And the trick is to have a possibility to render the same view in other actions that also provide #model. That said, if you do something like this in create:
#model = Model.new(model_params)
if #model.save
# success
else
render :new
end
It can render new view, because it assigns #model too; in this case, it will contain errors with messages and other stuff. All this is inside #model.errors – which is always empty in new action.
It's not that different for multiple forms, bear in mind that you always submit only one. You may switch to rendering an array of forms, in that case you could have #models array:
#models = [form1, form2, form3]
In that case, if saving fails, assign that array again and either replace the form the user tried to fill in (if you can identify it), ot prepend/append that form with errors to that array.
#models[index_of_submitted_form] = form_from_user #replace
#models << form_from_user # append
#models.unshift form_from_user # prepend
In Rails 3, you can access errors using #model.errors
<%= form_for #model = Model.new do |f| %>
<% #model.errors.full_messages.each do |msg| %>
<p><%= msg %></p>
<% end %>
# ...
# ...
# ...
<% end %>
In my application.html.erb I have a header partial. which I rendered with the render tag
<%= render 'layouts/header' %>
So this header applies to all the controller and all the actions.
I have a dropdown partial which i want to show, in addition to the header partial, in all the controllers except one one controller. I want something like
<%= render 'layouts/dropdown' except_controller_anycontroller %>
When I put
render :partial => 'layouts/dropdown'
It just renders the dropdown partial and all other layouts are lost (like the footer,header,body). I want to add the extra dropdown partial only to certain actions and controllers.
How can I achieve that in Rails 3.2.13?
Replace your render with this:
<%= render 'layouts/dropdown' unless #disable_dropdown %>
Then you can simply set disable_dropdown to true in any controller you like:
def test_method
#disable_dropdown = true
end
call this method in your controller filter, in which you dont want to show this:
write this on top of your controller above your first method:
before_filter :test_method
it will automatically be called when your request comes to this controller.
Hope it will help. Thanks
I would suggest something like:
<%= render 'layouts/dropdown' unless params[:controller] == "controller_to_avoid" %>