Search code examples
ruby-on-railsdatabaseactiverecordruby-on-rails-4models

How to setup this relationship and display the correct data


Not sure how to set this relationship up correctly. 3 tables: Users, Posts, Statuses

Models -

User Model
has_many :posts

Post Model
belongs_to :user
has_one :status

Status Model
#Not sure about this.

Tables –

Users: name, email, password_digest
Posts: user_id, status_id, post_title, post_content
Statuses:  user_id, status_title, status_active

The user can create their own statuses, so I am not sure if the status should belong to the User or the Post.

In the Users controller, for the new action I have the following to help generate the status options in a dropdown list when making a new Post:

def new

@post = Post.new
@options_statuses = Status.where(:admin_user_id => session[:id])

end

The code to create the new Post(from within a partial):

<%= f.label(:status_id, "Status") %><br/>
<%= f.select(:status_id, @options_statuses.map { |s| [ s.status_title, s.id ] }) %><br/><br/>

<%= f.label(:post_title, "Title") %><br/>
<%= f.text_field(:post_title) %><br/><br/>

<%= f.label(:post_content, "Content") %><br/>
<%= f.text_area(:post_content) %><br/><br/>

The Post info is saved correctly to the database. The problem is when i want to show the posts via the Index or Show actions. Currently I have the following:

<% @posts.each do |post| %>

<%= post.status_id %> - <%= post.created_at %><br/>  
<%= post.post_title %> - <%= post.post_content %>

<% end %>

Instead of showing the status_id, I would actually like to display the status_title but am not sure how to do this.

Any help is greatly appreciated.


Solution

  • First of all, since your Post model has a status_id attribute, this means Post should belong_to :status instead of the has_one :status. Status should then either has_one :post or has_many :posts.

    Now, for your question: You can achieve this by delegating title to the associated status object. (Hint: think of these objects as objects here -- forget about the database behind them!) Here's how:

    # Post model
    delegate :title, to: :status, prefix: true
    

    This will define a method behind the scenes that looks like this:

    # Post model
    def status_title
      status.title
    end
    

    For more on delegate see the api docs.