Reputation: 342
I have Post and SubCategory models that have a belongs_to and has_many relationship respectively.
In the Show view of Post, in addition to showing an individual Post, I need to run the index action of the SubCategory controller to show the current SubCategory and all of it's Post in a left Nav area.
What's the best way to go about this?
EDIT I was already utilizing Application Controller so I think this is the best route to go especially if I want to do the same thing in other views.
class ApplicationController < ActionController::Base
protect_from_forgery
before_filter :load_application_wide_varibales
def load_application_wide_varibales
def get_subcategory_and_post
@sub_category = SubCategory.all
end
end
class PostController < ActionController::Base
before_filter :get_subcategory_and_post, only: [:show]
def show
@post = Post.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: @post }
end
end
class SubCategoryController < ActionController::Base
before_filter :get_subcategory_and_post
end
def current_user
@current_user ||= User.find(session[:user_id]) if session[:user_id]
end
helper_method :current_user
end
end
Posts Show View
<% @sub_category.each do |subcat| %>
<div class="leftnav">
<h1 class="name"><%= subcat.name %></h1>
<% subcat.posts.each do |post| %>
<ul>
<li><%= link_to (post.name), post %></li>
</ul><% end %>
</div>
<% end %>
<div class="rightContent">
<p id="notice">
<%= notice %>
</p>
<p>
<b>Name:</b>
<%= post.name %>
</p>
<p>
<b>Content:</b>
<%= post.content %>
</p>
</div>
Post model:
class Post < ActiveRecord::Base
belongs_to :sub_category
belongs_to :users
validates :name, :content, :sub_category_id, :presence => true
attr_accessible :content, :name, :sub_category_id
after_save :expire_post_all_cache
after_destroy :expire_post_all_cache
def self.to_csv(options = {})
CSV.generate(options) do |csv|
csv << column_names
all.each do |post|
csv << post.attributes.values_at(*column_names)
end
end
end
def self.all_cached
Rails.cache.fetch('Post.all') { all }
end
def expire_post_all_cache
Rails.cache.delete('Post.all')
end
end
SubCategory model:
class SubCategory < ActiveRecord::Base
attr_accessible :name
belongs_to :category
has_many :posts
validates :name, :category_id, :presence => true
end
Working Posts Show view:
<div class="leftnav">
<h1 class="name"><%= @post.sub_category.name %></h1>
<% @post.sub_category.posts.each do |post|%>
<ul>
<li><%= link_to (post.name), post %></li>
</ul><% end %>
</div>
<div class="rightContent">
<p id="notice"><%= notice %></p>
<p>
<b>Name:</b>
<%= @post.name %>
</p>
<p>
<b>Content:</b>
<%= @post.content %>
</p>
</div>
Upvotes: 0
Views: 144
Reputation: 3911
redirect_to your_controller_action_url and return
This will render another controllers action. However, this is contrary to how logic should be separated in controllers and typically considered to be a bad practice.
Your best bet would be to abstract the logic in the SubCategory controller to ApplicationController
and then both the post and sub-category controllers can use it.
Here's an example with fake methods:
class ApplicationController < ActionController::Base
def get_subcategory_and_post
# Logic here
end
end
class PostController < ActionController::Base
before_filter :get_subcategory_and_post, only: [:show]
def show
# Logic here
end
end
class SubCategoryController < ActionController::Base
before_filter :get_subcategory_and_post
end
Upvotes: 0
Reputation: 4943
I would make a partial (something like _subcategory_list) that takes a subcategories collection and renders them. Then your Post view can call render(partial: 'subcategory/subcategory_list', locals: { subcategories: @post.subcategories })
and your SubCategory list view can do the same except pass in its @subcategories value.
Upvotes: 2