1

This is a follow-up question on Rails 4: new instance is created and saved to database but not displayed in view.

In our Rails 4 app, there are four models:

class User < ActiveRecord::Base
  has_many :administrations, dependent: :destroy
  has_many :calendars, through: :administrations
end

class Administration < ActiveRecord::Base
  belongs_to :user
  belongs_to :calendar
end

class Calendar < ActiveRecord::Base
  has_many :administrations, dependent: :destroy
  has_many :users, through: :administrations
end

class Post < ActiveRecord::Base
    belongs_to :calendar
end

Here are the corresponding migrations:

class CreateUsers < ActiveRecord::Migration
  def change
    create_table :users do |t|
      t.string :first_name
      t.string :last_name
      t.string :email
      t.integer :total_calendar_count
      t.integer :owned_calendar_count

      t.timestamps null: false
    end
  end
end

class CreateAdministrations < ActiveRecord::Migration
  def change
    create_table :administrations do |t|
      t.references :user, index: true, foreign_key: true
      t.references :calendar, index: true, foreign_key: true
      t.string :role

      t.timestamps null: false
    end
  end
end

class CreateCalendars < ActiveRecord::Migration
  def change
    create_table :calendars do |t|
      t.string :name

      t.timestamps null: false
    end
  end
end

class CreatePosts < ActiveRecord::Migration
  def change
    create_table :posts do |t|
        t.references :calendar, index: true, foreign_key: true
        t.date :date
        t.time :time
        t.string :focus
        t.string :format
        t.string :blog_title
        t.text :long_copy
        t.text :short_copy
        t.string :link
        t.string :hashtag
        t.string :media
        t.float :promotion
        t.string :target
        t.integer :approval
        t.text :comment

      t.timestamps null: false
    end
  end
end

We have the following form to create posts:

<h2>Create a new post</h2>

<%= form_for(@post) do |f| %>

  <%= render 'shared/error_messages', object: f.object %>

    <tr>
        <%= f.hidden_field :calendar_id, value: @calendar.id %>
        <td class="field"><%= f.date_field :date, placeholder: "When do you want to publish this post?" %></td>
        <td class="field"><%= f.time_field :time, placeholder: "What time do you want to publish this post?" %></td>
        <td class="field"><%= f.text_field :focus, placeholder: "What is this post about?" %></td>
        <td class="field"><%= f.text_field :format, placeholder: "What type of post is this?" %></td>
        <td class="field"><%= f.text_field :blog_title, placeholder: "If this post is about a blog post, what is the title of the blog post?" %></td>
        <td class="field"><%= f.text_area :long_copy, placeholder: "What is the copy of the post?" %></td>
        <td class="field"><%= f.text_area :short_copy, placeholder: "What is the short copy of the post (to be used on Twitter for instance)?" %></td>
        <td class="field"><%= f.url_field :link, placeholder: "Which link to you want to embed in this post?" %></td>
        <td class="field"><%= f.text_field :hashtag, placeholder: "Which hashtag(s) do you want to you in this post?" %></td>
        <td class="field"><%= f.text_field :media, placeholder: "Which media file (image, video) do you want to include in this post?" %></td>
        <td class="field"><%= f.number_field :promotion, placeholder: "What advertising budget should be allocated to this post?" %></td>
        <td class="field"><%= f.text_field :target, placeholder: "Who do you want to target with this post?" %></td>
        <td class="field"><%= f.select(:approval, %w['Approved' 'Needs edits' 'To be deleted'], {prompt: 'How does this post look?'}) %></td>
        <td class="field"><%= f.text_area :comment, placeholder: "Any comment?" %></td>

        <td><%= f.submit "Create", class: "btn btn-primary" %></td>

    </tr>

<% end %>

This form is embedded into the Calendars#Show view, so that as soon as a post is created, it should appear in the corresponding calendar.

Here is our PostsController:

class PostsController < ApplicationController

  def create
    @post = Post.create(post_params)
    if @post.save
      redirect_to root_url
    else
      render root_url
    end
  end

end

Currently, whenever we submit the form, nothing happens:

  • All the values stay put in the form
  • The page is not reloaded (so, no error message appears)
  • No new @post is added to the database

EDIT: here are the server logs:

Started GET "/calendars/1" for ::1 at 2015-07-07 22:21:07 -0700
Processing by CalendarsController#show as HTML
  Parameters: {"id"=>"1"}
  Calendar Load (0.1ms)  SELECT  "calendars".* FROM "calendars" WHERE "calendars"."id" = ? LIMIT 1  [["id", 1]]
  Post Exists (0.1ms)  SELECT  1 AS one FROM "posts" WHERE "posts"."calendar_id" = ? LIMIT 1  [["calendar_id", 1]]
  Post Load (0.1ms)  SELECT "posts".* FROM "posts" WHERE "posts"."calendar_id" = ?  [["calendar_id", 1]]
  Rendered posts/_post.html.erb (0.7ms)
  Rendered shared/_error_messages.html.erb (0.0ms)
  Rendered shared/_post_form.html.erb (5.1ms)
  Rendered calendars/show.html.erb within layouts/application (13.7ms)
  Rendered layouts/_shim.html.erb (0.1ms)
  User Load (0.1ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1  [["id", 1]]
  Rendered layouts/_header.html.erb (0.9ms)
  Rendered layouts/_footer.html.erb (0.4ms)
Completed 200 OK in 145ms (Views: 144.0ms | ActiveRecord: 0.4ms)

EDIT 2: here are the new server logs, after implementing what @miler350 recommended in his answer:

Started POST "/posts" for ::1 at 2015-07-08 09:09:58 -0700
Processing by PostsController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"+LS+B2/KiUq09cypZSQnzwj5xHbNnkYR6EC5hfjNCwc3/NfFkbWi3FJe0Zw3Mumsdnubnip5piQHXZ00eV1W2A==", "post"=>{"calendar_id"=>"", "date"=>"2015-08-20", "time"=>"12:04", "focus"=>"Test", "format"=>"Test", "blog_title"=>"Test", "long_copy"=>"Test", "short_copy"=>"Test", "link"=>"http://www.google.com", "hashtag"=>"Test", "media"=>"Test", "promotion"=>"50", "target"=>"Test", "approval"=>"'Approved'", "comment"=>"Test"}, "commit"=>"Create"}
Unpermitted parameter: calendar_id
   (0.1ms)  begin transaction
  SQL (0.7ms)  INSERT INTO "posts" ("date", "time", "focus", "format", "blog_title", "long_copy", "short_copy", "link", "hashtag", "media", "promotion", "target", "approval", "comment", "created_at", "updated_at") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)  [["date", "2015-08-20"], ["time", "2000-01-01 12:04:00.000000"], ["focus", "Test"], ["format", "Test"], ["blog_title", "Test"], ["long_copy", "Test"], ["short_copy", "Test"], ["link", "http://www.google.com"], ["hashtag", "Test"], ["media", "Test"], ["promotion", 50.0], ["target", "Test"], ["approval", 0], ["comment", "Test"], ["created_at", "2015-07-08 16:09:58.605712"], ["updated_at", "2015-07-08 16:09:58.605712"]]
   (0.6ms)  commit transaction
   (0.0ms)  begin transaction
   (0.0ms)  commit transaction
Redirected to http://localhost:3000/
Completed 302 Found in 9ms (ActiveRecord: 1.5ms)


Started GET "/" for ::1 at 2015-07-08 09:09:58 -0700
Processing by StaticPagesController#home as HTML
  User Load (0.1ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1  [["id", 1]]
  Rendered static_pages/home.html.erb within layouts/static_pages (1.8ms)
  Rendered layouts/_shim.html.erb (0.0ms)
  Rendered layouts/_static_header.html.erb (1.0ms)
  Rendered layouts/_footer.html.erb (0.3ms)
Completed 200 OK in 148ms (Views: 147.5ms | ActiveRecord: 0.1ms)


Started GET "/users/1" for ::1 at 2015-07-08 09:10:02 -0700
Processing by UsersController#show as HTML
  Parameters: {"id"=>"1"}
  User Load (0.1ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1  [["id", 1]]
  User Load (0.1ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1  [["id", 1]]
  Rendered shared/_error_messages.html.erb (0.7ms)
  Rendered shared/_calendar_form.html.erb (5.0ms)
  Administration Exists (0.5ms)  SELECT  1 AS one FROM "administrations" WHERE "administrations"."user_id" = ? LIMIT 1  [["user_id", 1]]
  Administration Load (0.5ms)  SELECT "administrations".* FROM "administrations" WHERE "administrations"."user_id" = ?  [["user_id", 1]]
  Calendar Load (0.1ms)  SELECT  "calendars".* FROM "calendars" WHERE "calendars"."id" = ? LIMIT 1  [["id", 1]]
  Calendar Load (0.1ms)  SELECT  "calendars".* FROM "calendars" WHERE "calendars"."id" = ? LIMIT 1  [["id", 2]]
  Calendar Load (0.1ms)  SELECT  "calendars".* FROM "calendars" WHERE "calendars"."id" = ? LIMIT 1  [["id", 3]]
  Calendar Load (0.1ms)  SELECT  "calendars".* FROM "calendars" WHERE "calendars"."id" = ? LIMIT 1  [["id", 4]]
  Calendar Load (0.1ms)  SELECT  "calendars".* FROM "calendars" WHERE "calendars"."id" = ? LIMIT 1  [["id", 5]]
  Rendered administrations/_administration.html.erb (4.1ms)
  Rendered users/show.html.erb within layouts/application (32.1ms)
  Rendered layouts/_shim.html.erb (0.3ms)
  Rendered layouts/_header.html.erb (0.9ms)
  Rendered layouts/_footer.html.erb (0.7ms)
Completed 200 OK in 150ms (Views: 135.3ms | ActiveRecord: 1.8ms)


Started GET "/calendars/1" for ::1 at 2015-07-08 09:10:04 -0700
Processing by CalendarsController#show as HTML
  Parameters: {"id"=>"1"}
  Calendar Load (0.1ms)  SELECT  "calendars".* FROM "calendars" WHERE "calendars"."id" = ? LIMIT 1  [["id", 1]]
  Post Exists (0.1ms)  SELECT  1 AS one FROM "posts" WHERE "posts"."calendar_id" = ? LIMIT 1  [["calendar_id", 1]]
  Post Load (0.1ms)  SELECT "posts".* FROM "posts" WHERE "posts"."calendar_id" = ?  [["calendar_id", 1]]
  Rendered posts/_post.html.erb (1.1ms)
  Rendered shared/_error_messages.html.erb (0.0ms)
  Rendered shared/_post_form.html.erb (5.3ms)
  Rendered calendars/show.html.erb within layouts/application (13.9ms)
  Rendered layouts/_shim.html.erb (0.1ms)
  User Load (0.1ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1  [["id", 1]]
  Rendered layouts/_header.html.erb (0.8ms)
  Rendered layouts/_footer.html.erb (0.3ms)
Completed 200 OK in 113ms (Views: 111.2ms | ActiveRecord: 0.4ms)

EDIT 3: here are the server logs when I add :calendar_id to the permitted post_params in the PostsControllers:

Started GET "/calendars/1" for ::1 at 2015-07-08 11:07:39 -0700
Processing by CalendarsController#show as HTML
  Parameters: {"id"=>"1"}
  Calendar Load (0.1ms)  SELECT  "calendars".* FROM "calendars" WHERE "calendars"."id" = ? LIMIT 1  [["id", 1]]
  Post Exists (0.2ms)  SELECT  1 AS one FROM "posts" WHERE "posts"."calendar_id" = ? LIMIT 1  [["calendar_id", 1]]
  Post Load (0.2ms)  SELECT "posts".* FROM "posts" WHERE "posts"."calendar_id" = ?  [["calendar_id", 1]]
  Rendered posts/_post.html.erb (0.7ms)
  Rendered shared/_error_messages.html.erb (0.0ms)
  Rendered shared/_post_form.html.erb (5.2ms)
  Rendered calendars/show.html.erb within layouts/application (17.9ms)
  Rendered layouts/_shim.html.erb (0.0ms)
  User Load (0.1ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1  [["id", 1]]
  Rendered layouts/_header.html.erb (0.8ms)
  Rendered layouts/_footer.html.erb (0.3ms)
Completed 200 OK in 160ms (Views: 147.4ms | ActiveRecord: 0.8ms)

Where could the problem be coming from: the models, the form, the controller, or somewhere else?

Community
  • 1
  • 1
Thibaud Clement
  • 6,607
  • 10
  • 50
  • 103

1 Answers1

1

You have to create your post params.

class PostsController < ApplicationController

  def create
    @post = Post.create(post_params)
    if @post.save
      redirect_to root_url
    else
      render root_url
    end
  end

  protected

  def post_params
    params.require(:post).permit(:date, :time, :focus....) #put all columns that you want to submit via form here. 
  end

end

What you are getting is most likely a validation error because you probably require at least one field to be submitted for your post. When rails doesn't receive this, you tell it to render not redirect so you may not notice the reload.

miler350
  • 1,411
  • 11
  • 15
  • Ok, great, I am going to do that. Is it ok if I use `private` instead of `protected`? – Thibaud Clement Jul 08 '15 at 14:59
  • Also, shouldn't we include somewhere in the `post_params` the `:calendar_id`? – Thibaud Clement Jul 08 '15 at 16:07
  • Yes to both. You can pass the `calendar_id` to the post_params via a hidden form. `<%= f.hidden_field :calendar_id, value: @calendar.id %>` – miler350 Jul 08 '15 at 17:17
  • Perfect, this is what I have done. However, the post is still not created. I have included the logs in the question (EDIT 2). – Thibaud Clement Jul 08 '15 at 17:23
  • The `Post` is not created or the post isn't associated with the calendar? Those logs look like you've created a freestanding post because calendar_id was unpermitted (?) – miler350 Jul 08 '15 at 17:55
  • Well, I would say that the post is not created, since it does not appear in the `rails console` when I run `Post.last`. Plus, I believe that we do associate the post with the calendar thanks to your `<%= f.hidden_field :calendar_id, value: @calendar.id %>` line of code, don't we? (Sorry if these are basic mistakes, I am pretty new to Ruby & Rails). – Thibaud Clement Jul 08 '15 at 18:05
  • I just added `:calendar_id` to the `post_params` in the `PostsController` and edited the question with the new server logs, if that may help. I must me missing something obvious, but I just don't know what. – Thibaud Clement Jul 08 '15 at 18:11