Re: [Rails] new action doesn't render from other model's index page

28 views
Skip to first unread message

Walter Lee Davis

unread,
Dec 1, 2019, 11:58:10 AM12/1/19
to rubyonra...@googlegroups.com


> On Dec 1, 2019, at 8:08 AM, fugee ohu <fuge...@gmail.com> wrote:
>
> 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

>
> <div class="field">
> <%= f.select :item_type_id, nested_set_options(ItemType.all, @item_type) {|i| "#{'-' * i.level} #{i.name}" }, {:include_blank => "Select"}%>
> </div>
>
> <div class="actions">
> <%= f.submit "New item" %>
> </div>
>
> <% end %>
>
> new.html.erb:
>
> <%= render form %>
>
>
> --
> You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to rubyonrails-ta...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/rubyonrails-talk/53e9cef1-537b-4b77-8693-91b0e343f565%40googlegroups.com.

fugee ohu

unread,
Dec 1, 2019, 12:17:28 PM12/1/19
to Ruby on Rails: Talk
Thanks but since when do we post to the new action?

Walter Lee Davis

unread,
Dec 1, 2019, 12:49:53 PM12/1/19
to rubyonra...@googlegroups.com
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

> On Dec 1, 2019, at 12:17 PM, fugee ohu <fuge...@gmail.com> wrote:
>
> Thanks but since when do we post to the new action?
>
> --
> You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to rubyonrails-ta...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/rubyonrails-talk/fd3f5207-840b-4fec-ba29-100fdf882447%40googlegroups.com.

Walter Lee Davis

unread,
Dec 1, 2019, 12:58:33 PM12/1/19
to rubyonra...@googlegroups.com
Sorry, typo here:

> On Dec 1, 2019, at 12:49 PM, Walter Lee Davis <wa...@wdstudio.com> wrote:
>
> @item = Item.new(item_type = params[:item_type])

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

I meant hash syntax, not assignment.

Walter

fugee ohu

unread,
Dec 1, 2019, 2:06:14 PM12/1/19
to Ruby on Rails: Talk
> To unsubscribe from this group and stop receiving emails from it, send an email to rubyonra...@googlegroups.com.


The form has to be different depending on the item type

fugee ohu

unread,
Dec 1, 2019, 3:16:11 PM12/1/19
to Ruby on Rails: Talk


On Sunday, December 1, 2019 at 12:49:53 PM UTC-5, Walter Lee Davis wrote:
> To unsubscribe from this group and stop receiving emails from it, send an email to rubyonra...@googlegroups.com.

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

fugee ohu

unread,
Dec 1, 2019, 3:17:26 PM12/1/19
to Ruby on Rails: Talk


On Sunday, December 1, 2019 at 12:49:53 PM UTC-5, Walter Lee Davis wrote:
> To unsubscribe from this group and stop receiving emails from it, send an email to rubyonra...@googlegroups.com.

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

Walter Lee Davis

unread,
Dec 1, 2019, 7:12:18 PM12/1/19
to rubyonra...@googlegroups.com
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
> To unsubscribe from this group and stop receiving emails from it, send an email to rubyonrails-ta...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/rubyonrails-talk/1a0cfa0a-8962-4aa6-ab89-b26a680dacb0%40googlegroups.com.

fugee ohu

unread,
Dec 1, 2019, 9:52:11 PM12/1/19
to Ruby on Rails: Talk
> To view this discussion on the web visit https://groups.google.com/d/msgid/rubyonrails-talk/1a0cfa0a-8962-4aa6-ab89-b26a680dacb0%40googlegroups.com.

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

fugee ohu

unread,
Dec 1, 2019, 9:54:54 PM12/1/19
to Ruby on Rails: Talk
> To view this discussion on the web visit https://groups.google.com/d/msgid/rubyonrails-talk/1a0cfa0a-8962-4aa6-ab89-b26a680dacb0%40googlegroups.com.

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

fugee ohu

unread,
Dec 1, 2019, 10:17:46 PM12/1/19
to Ruby on Rails: Talk
> To view this discussion on the web visit https://groups.google.com/d/msgid/rubyonrails-talk/1a0cfa0a-8962-4aa6-ab89-b26a680dacb0%40googlegroups.com.


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 

fugee ohu

unread,
Dec 1, 2019, 10:42:37 PM12/1/19
to Ruby on Rails: Talk
> To view this discussion on the web visit https://groups.google.com/d/msgid/rubyonrails-talk/1a0cfa0a-8962-4aa6-ab89-b26a680dacb0%40googlegroups.com.


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)

Ariel Juodziukynas

unread,
Dec 1, 2019, 10:47:06 PM12/1/19
to rubyonra...@googlegroups.com
Form_with does an ajax request by default, use form_for or add local: true as an option or respond with a js view.

To unsubscribe from this group and stop receiving emails from it, send an email to rubyonrails-ta...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/rubyonrails-talk/f853922b-b6a3-4b25-a909-bd319967c91f%40googlegroups.com.

Walter Lee Davis

unread,
Dec 1, 2019, 11:04:01 PM12/1/19
to rubyonra...@googlegroups.com


> On Dec 1, 2019, at 10:17 PM, fugee ohu <fuge...@gmail.com> wrote:
>
> 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
>
>

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

fugee ohu

unread,
Dec 1, 2019, 11:55:04 PM12/1/19
to Ruby on Rails: Talk

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

fugee ohu

unread,
Dec 1, 2019, 11:56:51 PM12/1/19
to Ruby on Rails: Talk
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

Ariel Juodziukynas

unread,
Dec 2, 2019, 12:07:49 AM12/2/19
to rubyonra...@googlegroups.com
I don't think it's a secret, I guess it's right there in the form_with documentation

--
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rubyonrails-ta...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/rubyonrails-talk/e922a2fb-4118-41c4-b719-4f98bda7d1e7%40googlegroups.com.
Reply all
Reply to author
Forward
0 new messages