new action doesn't render from other model's index page

When I click submit nothing happens The console only shows the request

items/index.html.erb:

<%= form_with model: Item, url: new_item_path(@item), method: "get" do |f| %>

Your problem is right here. You are using a GET where you want a POST, and you are GETting the items/new path when you want to POST to the items path. Rails is particular about all of these points, because it is a (mostly standard) REST framework. When you change away from these conventions, you do so on your own. You can't expect Rails to know what you want this request to do, and you can't expect anyone who follows the usual patterns to be able to help you.

Walter

Thanks but since when do we post to the new action?

That's just it, you don't. You POST to the collection, which `create`s a new instance.

If you are expecting the GET with a querystring to create a new form with a picker selected, you should start by creating the form all in one piece, where you create a new form including a select (like the one you are trying to divide across two pages) in that same form. Make sure that submitting that form works, even though it doesn't do precisely what you're asking it to do in the divided form (yet).

Then figure out how to set that property (which the select chooses) on the `new` controller method.

There's a couple of different ways to do that. One would be to create a completely hand-made variable that you pass in the querystring of the form:

/items/new?item_type=Foo

and then "catch" that in the controller in the new method:

@item = Item.new(item_type = params[:item_type])

The other would be to go full-on REST, and create a new instance in the `index`, use that to build your form, and then you can use the regular strong_params accessor to get that same value (which will be "nested" inside a properly-named instance params hash) and assign it to the instance in the `new` method.

Now, what you should see at this point is that your all-in-one `new` form begins to behave "automatically". The instance that you build in the controller will be populated with the item_type property, and the picker will auto-select to the chosen value.

Once you see this working, you can change the select (picker) to a hidden field, and with no other changes, you will have your two-step form.

Walter

Sorry, typo here:

The form has to be different depending on the item type

Here’s my index definition

def index @item=Item.new if (params[:picture_id]) @items = Picture.find(params[:picture_id]).items.includes(:sales).where(:sales => { :item_id => nil }) @picture = Picture.find(params[:picture_id]) else @items = Item.includes(:sales).where(:sales => { :item_id => nil }).order(:item_type_id, :title) end end

What does that mean? How do I POST to a collection which creates a new instance

Look at a generic Rails controller, fresh out of `rails generate scaffold foo bar baz`. You will see that the `foos/new` form posts to the /foos path. That's what I mean by "posts to the collection". Once an instance has been persisted, you will see that the `foos/1/edit` form sends a POST disguised as a PATCH or PUT to the instance, at foos/1, and the `update` method is invoked by the controller. But when you are first creating a new instance, you are sending a POST to /foos (the collection of Foo instances).

Don't try to create a separate form for each kind of thing you want to create yet, just focus for now on making the two-step "wizard" work. Once you have that working, you can use the controller's `new` method (which will be getting a parameter passed to it to say what the item_type is) to decide which form to render. But until you have that part figured out, don't waste your energy on rendering a different form.

Walter

You’re telling me to forego the first step The form loads with a get request to the new action doesn’t it?

Who said anything about two step? Just trying to pass item_type to “get /items/new” using a select list

A generic scaffold posts to the create action PATCH and PUT according to you in this discussion POST to update Even still new is fetched by GET where new.html.erb renders _form.html.erb

Strangely the log shows it rendered the form but the page doesn’t change in the browser as if nothing happened when I clicked the submit button on the index page

Rendered items/_form.html.erb (34.5ms)

Form_with does an ajax request by default, use form_for or add local: true as an option or respond with a js view.

I'm not sure if you're confused about what I wrote, or just confused. Here are the actual actions that a generic Rails 6 scaffold generates and responds to. Read the comments before each method:

class FoosController < ApplicationController   before_action :set_foo, only: [:show, :edit, :update, :destroy]

  # GET /foos   # GET /foos.json   def index     @foos = Foo.all   end

  # GET /foos/1   # GET /foos/1.json   def show   end

  # GET /foos/new   def new     @foo = Foo.new   end

  # GET /foos/1/edit   def edit   end

  # POST /foos   # POST /foos.json   def create     @foo = Foo.new(foo_params)

    respond_to do |format|       if @foo.save         format.html { redirect_to @foo, notice: 'Foo was successfully created.' }         format.json { render :show, status: :created, location: @foo }       else         format.html { render :new }         format.json { render json: @foo.errors, status: :unprocessable_entity }       end     end   end

  # PATCH/PUT /foos/1   # PATCH/PUT /foos/1.json   def update     respond_to do |format|       if @foo.update(foo_params)         format.html { redirect_to @foo, notice: 'Foo was successfully updated.' }         format.json { render :show, status: :ok, location: @foo }       else         format.html { render :edit }         format.json { render json: @foo.errors, status: :unprocessable_entity }       end     end   end

  # DELETE /foos/1   # DELETE /foos/1.json   def destroy     @foo.destroy     respond_to do |format|       format.html { redirect_to foos_url, notice: 'Foo was successfully destroyed.' }       format.json { head :no_content }     end   end

  private     # Use callbacks to share common setup or constraints between actions.     def set_foo       @foo = Foo.find(params[:id])     end

    # Never trust parameters from the scary internet, only allow the white list through.     def foo_params       params.require(:foo).permit(:bar, :baz)     end end

Here's what I have gleaned from this exchange:

You want to start at the "index" view, and have a form on that page send a request to the "new" view, passing along a parameter that you will use to determine what `item_type` is to be created by the "create" method that the form on the "new" view will display.

On your Index page, here's what that form could look like:

<%= form_with url: 'foos/new', method: :get, local: true do |f| %> <%= f.collection_select :item_type, %w[one two], :to_s, :titleize %> <%= f.submit 'Choose', name: nil %> <%- end -%>

When that form is submitted, you will have access to either 'one' or 'two' in the params[:item_type] variable. You can do something interesting with that in the #new controller method. For a start, just to show that it worked, I changed the generic scaffold new.html.erb page to include this line:

<h1>New <%= params[:item_type].to_s.titleize %></h1>

When I test that, I see either "New One" or "New Two" when that page loads, depending on the choice I made on the index page.

Try some of these suggestions in a new, scaffolded controller in a different Rails app (or the same one, if you've been keeping up with your version control). Just try it as a test, and see what you can learn.

Walter

Oh Thanks Ariel I don’t know why they kept that a secret from me I needed to add ‘local: true’

Thanks Walter Like Ariel said, form_with does an ajax request by default unless you add ‘local: true’ I don’t know how they keep that a secret

I don’t think it’s a secret, I guess it’s right there in the form_with documentation