Rails 4: new instance is created and saved to database but not displayed in view

帅比萌擦擦* 提交于 2019-12-11 19:38:30

问题


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>
        <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 appears in the corresponding calendar.

EDIT 2: And here is ou PostsController:

class PostsController < ApplicationController

  def create
    @post = Post.create!
    if @post.save
      redirect_to root_url
    else
      render root_url
    end
  end

end

Currently, whenever we submit the form, a post is actually created (we checked through the console).

EDIT: Actually, the new @post is created and saved to the database but all values are set to nil. It seems we also have a problem with the saving of data from the form and into the database.

However, it does not appear in the corresponding calendar.

We believe this is due to the fact that, when a post is created, the calendar_id of the active calendar (the one in which the form is embedded in) is not added to the new post instance.

However, we don't know how to implement it:

  • Should we create an active_calendar method and then use it to automatically assign the active_calendar id of the active calendar to the newly created @post?
  • Should we simply declare the active calendar id as a variable, either in the post controller or the post model, so that we can add it when a new @post is created?
  • Should we include the active calendar id in the newly created @post through a hidden field in the form?

We kind of hit a wall here and are not sure of what we are doing wrong.

Any idea of how to fix this?

UPDATE: as suggested by @Fire-Dragon-DoL in the comments of his answer, we are going to use a hidden field.

Would the following code work?

<td type="hidden" value="#{@calendar.id}"><% f.number_field :calendar_id %></td>

回答1:


I'm not sure how or where is stored your "active calendar" information, you definitely need it. Make it a field for User, it's a good option.

Then I would create an application controller method like

def active_calendar
  # Assuming you have a method to return current logged in user
  current_user.try(:active_calendar)
end

Then when creating post you can easily perform the following

attrs = post_params.merge(calendar: active_calendar)
@post = Post.new(attrs)
# Or whatever logic you want
@post.save

Use the hidden field only if user is allowed to specify different calendars than the active one, otherwise it might just be a security hole

Notice that the code I wrote is also nil-proof




回答2:


You may want to nest your routes, for example:

resources :calendars do
    resources :posts
end

Now change your form to also include the calendar you want to be associated with the post like:

form_for([@calendar, @post])...

Then in your posts controller create path you can find your calendar and construct your post with something like:

def create
  my_calendar = Calendar.find(params[:calendar_id])
  post = my_calendar.posts.create(post_params)
  redirect_to root_path 
end

private

def post_params
  params.require(:post).permit(:date, :time, :focus, :format, :blog_title, :long_copy, :short_copy, :link, :hashtag, :media, :promotion, :target, :approval, :comment)
end


来源:https://stackoverflow.com/questions/31257024/rails-4-new-instance-is-created-and-saved-to-database-but-not-displayed-in-view

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!