I’m new to rails and programming in general and I’m all turned around atm. I’ve got user’s creating posts where they add a category tag to the post, the category tag is a boolean attribute of the post model, for instance :music, :boolean, :default => false.
I’d like user’s to have a link to “Music” that renders a new page that shows all posts where :music => true. Now I understand how to create a variable and run through a block of the posts such as @music_posts = Post.where(:music => true) but I’m confused on how to make the route /posts/music and I’m not sure about my def music_posts method. Any explanation for help would be greatly appreciated.
routes.rb
resources :posts do
member do
get :likers
end
collection do
get :search
end
end
resources :users do
member do
get :following, :followers, :likes
end
end
root :to => "pages#home"
class PagesController < ApplicationController
def home
@title = "Home"
@featured_posts = Post.featured.limit(10)
if user_signed_in?
@user = current_user
@post = current_user.posts.build
@feed_items = current_user.feed.paginate(:per_page => "10", :page => params[:page])
#render :layout => 'special_layout'
end
end
end
class PostsController < ApplicationController
before_filter :authenticate_user!, :only => [:create, :edit, :update, :destroy]
before_filter :authorized_user, :only => [:destroy, :edit, :update]
def create
@user = current_user
@post = current_user.posts.build
if @post.update_attributes(params[:post])
flash[:success] = "Post created!"
redirect_to root_path
else
@feed_items = current_user.feed.paginate(:per_page => "10", :page => params[:page])
render 'pages/home'
end
end
def index
@posts = Post.paginate(:page => params[:page])
end
end
end
def show
@post = Post.find(params[:id])
end
def edit
@post = Post.find(params[:id])
end
def update
@post = Post.find(params[:id])
respond_to do |format|
if @post.update_attributes(params[:post])
format.html { redirect_to(post_path(@post), :notice => 'Post was successfully updated.') }
else
format.html { render :action => "edit" }
end
end
end
def destroy
@post.destroy
redirect_to root_path
end
def likers
@title = "Likers"
@post = Post.find(params[:id])
@likers = @post.likers.paginate(:page => params[:page])
render 'show_likers'
end
def music_posts
@music_posts = Post.where(:music => true)
render 'show_music_posts'
end
private
def authorized_user
@post = Post.find(params[:id])
redirect_to root_path unless current_user?(@post.user)
end
end
Edit: attempting
routes
enter code here
match ‘posts/categories/*tag’ => ‘posts#categories’
posts controller
def categories
if params[:tag].present?
@posts = Post.where('#{params[:tag]} = ?', true).paginate(:page => params[:page])
end
render 'categories'
end
I need a custom view to show them, is this all correct?
I am making the presumption that you might have more tags than just music, if not you could have a simpler approach by hardcoding a music route.
I believe what you want is Route Globbing, you can find details here http://guides.rubyonrails.org/routing.html (just go to the Route Globbing section).
Basically you would create a route like:
This would mean that any URL like “…/posts/something” would route to your index method in the posts controller, and would pass the “something” in as params[:tag]. You could then check if params[:tag] exists, and if so filter your results based on that, otherwise display all. It would let you have just one index method to cover all scenarios. Your index method would look something like:
Doing it this way allows you to have more tags than just music, and keeps it dynamic.
One thing to note, with this route, the wildcard will take anything after /posts/ and make it pass in as the parameter, this can override your other routes like new, create, etc. Make sure you order your routes correctly for the right precedence. Even better would be to make your route /posts/tags/music to avoid this problem.