1

I have more curious questions for all you amazing people!

I am creating a forum and when you create a topic, you are also creating the first post at the same time.

I need to assign variables to certain fields.

Example: :user_id => current_user.id,

I don't have the param settings correct, so many of the fields are NULL when stored in the database.

Models

class Topic < ActiveRecord::Base
  belongs_to :forum
  has_many :posts, :dependent => :destroy  
  belongs_to :user
  accepts_nested_attributes_for :posts
end

class Post < ActiveRecord::Base  
  belongs_to :topic  
  belongs_to :user
end

Topics Controller

# GET /topics/new
def new
  @topic = Topic.new
  @topic.posts.build
end

def create  
  @topic = Topic.new(topic_params)

  if @topic.save 
    #@topic.responses = Post.new(params[:responses])
    flash[:success] = "Topic Posted"
    redirect_to "/forums/#{@topic.forum_id}" 
  else  
    render :new  
  end   
end

def topic_params
  # last_post_at = (:last_post_at => Time.now)
  params.require(:topic).permit(
    :name, 
    :description, 
    [:last_poster_id => current_user.id], 
    [:last_post_at => Time.now], 
    [:user_id => current_user.id],
    :forum_id,
    posts_attributes: [:id, :content, :topic_id, :user_id => current.user.id] )
end

Post Controller

# GET /posts/new
def new
  @post = Post.new
end

def create  
  @post = Post.new(
    :content => params[:post][:content], 
    :topic_id => params[:post][:topic_id], 
    :user_id => current_user.id)  

  if @post.save  
    @topic = Topic.find(@post.topic_id)  
    @topic.update_attributes(
      :last_poster_id => current_user.id, 
      :last_post_at => Time.now)  
    flash[:notice] = "Successfully created post."  
    redirect_to "/topics/#{@post.topic_id}"  
  else  
    render :action => 'new'  
  end  
end  

_form for View/Topic

<%= form_for(@topic) do |f| %>
  <% if params[:forum] %>
    <input type="hidden" 
    id="topic_forum_id" 
    name="topic[forum_id]" 
    value="<%= params[:forum] %>" />
  <% end %>  

  <div class="field">
    <%= f.label :name %><br>
    <%= f.text_field :name %>
  </div>
  <div class="field">
    <%= f.label :description %><br>
    <%= f.text_field :description %>
  </div>

  <%= f.fields_for :posts do |p| %>

    <%= p.label :content %><br />
    <%= p.text_area :content %>

  <% end %>
  <%= f.submit :class => "btn btn-primary" %>
<% end %>
2
  • What errors are you getting? Commented Oct 18, 2013 at 22:16
  • undefined method `[]' for nil:NilClass ONLY when :content => params[:post][:content] is in the create post located in the topic controller. If I remove that, the topic is created, but there is no new field in the post table. Actually, now when I create a topic, the content field isn't showing up in the form as well, just allows people to create a name and description field. Commented Oct 18, 2013 at 22:39

3 Answers 3

2

You'll likely be looking for a function called:

accepts_nested_attributes_for

You put this into the model you're working with (in your case Post) and it will pass paeans for the nested model through to the corresponding controller

There is a good RailsCast about this and I've gr some experience with it too. If you want me to post working live code, let me know (I'm on my iPhone)


Live Code

Models

#app/models/image_post.rb
belongs_to :post, :class_name => 'Post'
belongs_to :image, :class_name => 'Image'
accepts_nested_attributes_for :image, :allow_destroy => true

#app/models/post.rb
has_many :images, -> { uniq }, :class_name => 'Image', :through => :images_posts, dependent: :destroy
has_many :images_posts, :class_name => 'ImagePost'
accepts_nested_attributes_for :images_posts, :allow_destroy => true

Controller

    def new
            @post = Post.new
            @post.images_posts.build.build_image
    end

    def create
            #Using Inherited Resources Gem
            create! 
    end

    private
    def permitted_params
            {:post => params.require(:post).permit(:title, :body, images_posts_attributes: [:caption, image_attributes: [:image]] )}
    end

Form

<%= form_for [:admin, resource], :html => { :multipart => true }  do |f| %>
        <table class="resource_table">
                <thead>
                        <th colspan="2"><%= params[:action].capitalize %> <%= resource_class %></th>
                </thead>
                <tbody class="form">
                        <% attributes.each do |attr| %>
                                <tr class="<%= cycle('odd', '')%>">
                                        <td><%= resource_class.human_attribute_name(attr) %></td>
                                        <td>
                                                <% if attr == "body" %>
                                                        <%= f.text_area attr, :rows => 60, :cols => 80, :class => "redactor" %>
                                                <% else %>
                                                        <%= f.text_field attr, :value => resource.public_send(attr).to_s %>
                                                <% end %>
                                        </td>
                                </tr>
                        <% end %>
                        <%= f.fields_for :images_posts do |images_posts| %>
                                <%= images_posts.fields_for :image do |images| %>
                                        <tr>
                                                <td>Image</td>
                                                <td><%= images.file_field :image %></td>
                                        </tr>
                                <% end %>
                                <tr>
                                        <td>Caption</td>
                                        <td><%= images_posts.text_field :caption %></td>
                                </tr>
                        <% end %>
                        <tr class="dull">
                                <td colspan="2"><%= f.submit "Go" %></td>
                        </tr>
                </tbody>
        </table>
<% end %>
Sign up to request clarification or add additional context in comments.

7 Comments

I have accepts_nested_attributes_for :posts in Post (just forgot to add it to the code here). So can you post a working live code in case I'm missing something.
Btw we used a has_many :through relationship, so we have the extra model to deal with; but if you can't decipher it, please let me know
Okay I am slightly confused. Does Create! use the private params? and if not, where is the private params used? I feel like my code is very similar to this. I think I understand what I need to do now, but now I need to create a new question to solve a new problem. Haha. Thank you.
Hey create! is from inherited_resources sorry. What's your new problem? I'll help you fix it!
Using your suggestions (without the gem), I managed to get it so when you create the topic, it creates the post. However, some of the topic and post fields in the table are NULL, because I need to assign it special variables (Like :last_poster_id => current_user.id). I edited my original post to show my code. How do you use strong params that have fields that need certain variables?
|
0

Use accepts_nested_attributes

class topic
 accepts_nested_attributes :posts
end

class post
  accepts_nested_attributes :topic
end

Then in form you can use fields_for posts while creating topic form Also in post form fileds_for for topic

1 Comment

I think I already have all this and its still not saving when i create a new topic.
0

You may want to fetch the post params as

params[:topic].fetch(:post_attributes, nil)

Rails 4 has been sanitized the mass-assignment to be called as strong_params Example

1 Comment

I used Strong_params at first and it did create posts for me... However, I was unable to change the variable data before it was entered. like... :Last_poster_id => current_user.id wouldn't work, so last_poster_id would be null. def topic_params params.require(:topic).permit(:name, :description, [:last_poster_id => current_user.id], [:last_post_at => Time.now], :forum_id, posts_attributes: [:id, :content, :topic_id, :user_id] ) end

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.