1

I am working on a simple crowdsource platform in Rails 4.1. The application is based on the rails-devise-pundit starter app from RailsApp. After the initial bootstrap I have generated the following two scaffolds:

  • project
  • pledge

$ rails generate scaffold project title body:text user_id:integer:index

$ rails generate scaffold pledge amount:integer user_id:integer:index project_id:integer:index

I have the following associations:

app/models/user.rb

class User < ActiveRecord::Base
  has_many :projects
  has_many :pledges
end

app/models/project.rb

class Project < ActiveRecord::Base
  belongs_to :user
  has_many :pledges
end

app/models/pledge.rb

class Pledge < ActiveRecord::Base
  belongs_to :project
  belongs_to :user
end

And the following routes.

config/routes.rb

Rails.application.routes.draw do
  resources :users
  resources :projects do
    resources :pledges
  end
end

When I try to create a new pledge on a project I get the following error:

NoMethodError at /projects/1/pledges/new

undefined method `pledges_path' for #<#:0x007f994c0596b8> Started GET "/projects/1/pledges/new" for 127.0.0.1 at 2014-07-04 23:18:59 +0200 Processing by PledgesController#new as HTML
Parameters: {"project_id"=>"1"} User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 ORDER BY "users"."id" ASC LIMIT 1 Rendered pledges/_form.html.erb (8.6ms) Rendered pledges/new.html.erb within layouts/application (9.3ms) Completed 500 Internal Server Error in 28ms

NoMethodError - undefined method pledges_path' for #<#<Class:0x007f994c05a6d0>:0x007f994c0596b8>: actionpack (4.1.1) lib/action_dispatch/routing/polymorphic_routes.rb:142:in polymorphic_url' actionpack (4.1.1) lib/action_dispatch/routing/polymorphic_routes.rb:148:in polymorphic_path' actionview (4.1.1) lib/action_view/helpers/form_helper.rb:452:in apply_form_for_options!' actionview (4.1.1) lib/action_view/helpers/form_helper.rb:425:in form_for'
app/views/pledges/_form.html.erb:1:in
_app_views_pledges__form_html_erb___852280298890992063_70148190581820'

The _form.html.erb for the pledge-view is just the default generated from the scaffold.

app/view/pledges/_form.html.erb

<%= form_for(@pledge) do |f| %>
  <% if @pledge.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@pledge.errors.count, "error") %> prohibited this pledge from being saved:</h2>

      <ul>
      <% @pledge.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="form-group">
    <%= f.label :amount %><br>
    <%= f.number_field :amount, class: "form-control" %>
  </div>
  <div class="form-group">
    <%= f.label :user_id %><br>
    <%= f.number_field :user_id, class: "form-control" %>
  </div>
  <div class="form-group">
    <%= f.label :project_id %><br>
    <%= f.number_field :project_id, class: "form-control" %>
  </div>
  <div class="form-group">
    <%= f.submit class: "btn btn-primary" %>
  </div>
<% end %>

Can anyone tell me what I am doing wrong or help me on how I should approach the simple models with users, projects and pledges to create a simple crowdsourcing platform in rails?

When I created the nested resources in config/routes.rb I also changed all "pledge_path" to "project_pledge_path". Showing pledges under projects seems to work, but not creating a new one.

1
  • add your pledges controller, it sounds like you're not building the relationship in your pledges controller. Commented Jul 4, 2014 at 22:05

2 Answers 2

8

Method

James Mason is right - let me explain

When you pass objects into the form_for method, Rails will automatically build the form's action and other arguments from the object.

The problem you have is this process is rather "dumb", meaning it will try and build the path based on the objects it's been passed, nothing more. The problem here is if you're calling the form as part of a nested route structure, Rails won't know how to define the path element of your form correctly.

As pointed out, the way to fix this is to send an array to your form_for tag, like so:

<%= form_for [@parent, @nested] do |f| %>

Alternatively, you could also use a :symbol for the parent object:

<%= form_for [:parent, @nested] do |f| %>

--

This should fix your error for you

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for your detailed explanation, it made me understand how it works.
Thanks very much, had to use :parent instead of @parent to get my issue resolved.
1

Since your pledges are always under projects, you need to replicate that relationship when you create your form.

<%= form_for([@project, @pledge]) do |f| %>

or

<%= form_for([@pledge.project, @pledge]) do |f| %>

depending on how you're initializing your @pledge object.

4 Comments

Thanks you, I will work on it. I ran the rake routes and noticed that project_pledge_path takes two arguments: project_pledge GET /projects/:project_id/pledges/:id. Is this related? I'm a bit new with Rails, so sorry for my lack of knowledge.
Yep. Check out @Rich Peck's answer. He explains how it all ties together.
I figured out that when I create a new @pledge-object, it is not tied to a project. How do I tie it to the current project in the pledges-controller?
Just figured it out. I had to define the @project object in the pledges-controller for the new-method.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.