views:

99

answers:

3

Ok, so I am working on a blog application of sorts. Thus far, it allows for a user to sign up for their own account, create posts, tags, comments, etc.

I have just implemented the ability to use www.myapp.com/brandon to set @user to find by username and therefore correctly display the users information at each url. So when you go to www.myapp.com/brandon you see all Brandon's posts, tags, and comments associated with those posts, etc. Works great.

I'm implementing this URL mapping through the routes.rb file by adding the following:

map.username_link '/:username', :controller => 'posts', :action => 'index'

And then just setting the @user variable in the PostController and corresponding views to find_by_username. Now the issue is this. Once at www.myapp.com/brandon when you click on a post title, it sends to myapp.com/posts/id without the username in the URL.

How do I tell rails to replace the /posts with /username.

Is it even possible to insert the user_username variable into this code?

map.resources :posts, :as => [what goes here] 
A: 

You should be able to create the link using:

= link_to "User Posts", subdomain_link_url(@user.username, @post)

In your PostController, then, I would use a before_filter to lookup and set the @user variable:

class PostController < ApplicationController
  before_filter :find_user

  def other_method
    # Some code here
  end

protected
  def find_user
    @user = User.find_by_username(params[:username])
  end
end
jerhinesmith
I just updated my question a bit. For one reason or another I couldn't get the code you mentioned above to work. Perhaps because I am already filtering by @user. That said, I was able to fix the problem with the show action and now just trying to replace the /posts with /username.
bgadoci
A: 

I don't know much about routes and stuff, so forgive me if this doesn't make sense, but doesn't it works for you?

map.resources :posts, :path_prefix => '/:username' do |post|
    post.resources :comments
end

I can see here that this will generate the following

            posts GET    /:username/posts(.:format)                            {:controller=>"posts", :action=>"index"}
                  POST   /:username/posts(.:format)                            {:controller=>"posts", :action=>"create"}
         new_post GET    /:username/posts/new(.:format)                        {:controller=>"posts", :action=>"new"}
        edit_post GET    /:username/posts/:id/edit(.:format)                   {:controller=>"posts", :action=>"edit"}
             post GET    /:username/posts/:id(.:format)                        {:controller=>"posts", :action=>"show"}
                  PUT    /:username/posts/:id(.:format)                        {:controller=>"posts", :action=>"update"}
                  DELETE /:username/posts/:id(.:format)                        {:controller=>"posts", :action=>"destroy"}
    post_comments GET    /:username/posts/:post_id/comments(.:format)          {:controller=>"comments", :action=>"index"}
                  POST   /:username/posts/:post_id/comments(.:format)          {:controller=>"comments", :action=>"create"}
 new_post_comment GET    /:username/posts/:post_id/comments/new(.:format)      {:controller=>"comments", :action=>"new"}
edit_post_comment GET    /:username/posts/:post_id/comments/:id/edit(.:format) {:controller=>"comments", :action=>"edit"}
     post_comment GET    /:username/posts/:post_id/comments/:id(.:format)      {:controller=>"comments", :action=>"show"}
                  PUT    /:username/posts/:post_id/comments/:id(.:format)      {:controller=>"comments", :action=>"update"}
                  DELETE /:username/posts/:post_id/comments/:id(.:format)      {:controller=>"comments", :action=>"destroy"}
j.
+3  A: 

You said there's going to be more than just posts on the page? comments and tags too? Sounds like we need some resource aggregation here...

Another concern: what if a user picks the name faq and you want domain.com/faq down the road? You can't possibly know all the URLs you will want in the future. Prefixing paths with /profiles is a great way to build a little "namespace" to prevent this from happening. So...

Why not a ProfilesController?

script/generate controller profiles index show

routes.rb

ActionController::Routing::Routes.draw do |map|

  map.resources :profiles,        :only => [:index, :show] do |profile|
    profile.resources :posts,     :only => [:index, :show]
    profile.resources :comments,  :only => [:index, :show]
    profile.resources :tags,      :only => [:index, :show]
  end

  # ...
end

This will give you the following routes

        profiles GET /profiles(.:format)                          {:controller=>"profiles", :action=>"index"}
         profile GET /profiles/:id(.:format)                      {:controller=>"profiles", :action=>"show"}
   profile_posts GET /profiles/:profile_id/posts(.:format)        {:controller=>"posts", :action=>"index"}
    profile_post GET /profiles/:profile_id/posts/:id(.:format)    {:controller=>"posts", :action=>"show"}
profile_comments GET /profiles/:profile_id/comments(.:format)     {:controller=>"comments", :action=>"index"}
 profile_comment GET /profiles/:profile_id/comments/:id(.:format) {:controller=>"comments", :action=>"show"}
    profile_tags GET /profiles/:profile_id/tags(.:format)         {:controller=>"tags", :action=>"index"}
     profile_tag GET /profiles/:profile_id/tags/:id(.:format)     {:controller=>"tags", :action=>"show"}

profiles_controller.rb

class ProfilesController < ApplicationController

  # show all profiles; profile browser
  # /profiles
  def index
  end

  # show one profile
  # /profiles/:id
  def show
    @user = User.find_by_username(params[:id])
  end

end

posts_controller.rb (and others)

class PostsController < ApplicationController

  before_filter :find_profile, :only => [:index, :show]

  # list all posts for this profile
  # /profiles/:profile_id/posts
  def index
  end

  # show one post for this profile
  # /profiles/:profile_id/posts/:id
  def show
  end

  protected 

    def find_profile
      @user = User.find_by_username(params[:profile_id])
    end

end

macek
You'll also want to have `class User < ActiveRecord::Base; def to_param; username; end; end` so that the params[:profile_id] is set correctly when you use `link_to @user.name, profile_path(@user)` and `link_to @post.title, profile_post_path(@user, @post)`.
Tim Snowhite
Thanks for taking the time to provide so much detail. When I implement the above, and navigate to /profiles/username it is defaulting to the profiles show page. I still have the following route set up: map.subdomain_link '/profiles/:username', :controller => 'profiles', :action => 'show'
bgadoci
Do I need to move all the posts/index.html.erb code to the profile show page? Then rework the code I am assuming?
bgadoci
@Tim Snowhite, what about `user_path(@user)`? Will that still using `@user.id`? I think he only wants `@user.username` for the profile page.
macek
@bgadoci, I'm working on expanding this answer for you. I'll keep you updated.
macek
Or do I need to add those routes to the .rb file?
bgadoci
Ah, we commented at the same time. sorry about that. Thank you so freaking much.
bgadoci
@macek, if he wants `user_path(@user) #=> /users/#{user_id}` as well as `profile_path(@user) #=> /profiles/#{username}` the easiest way will be to leave `User#to_param` as `id` and instead use `profile_path(:id => @user.username)`.
Tim Snowhite
@Tim Snowhite, that's what I assumed. Thank you for clarifying.
macek
@bgadoci, I created a sample rails project for you and hosted it on github. From your terminal, `[bgadoci ~]$ git clone [email protected]:macek/bgadoci-blog.git bgadoci_blog`. See http://github.com/macek/bgadoci-blog for more details :)
macek
@macek, man...that is awesome. Just cloned it and will be digging in tonight after family time. Cannot believe you would do that for me man. I really really really appreciate it.
bgadoci
@macek I haven't dug into your code share yet but I did clean up my mess a little. Just added you as a collaborating on the project I am working on so you can see where I am at if you are interested.
bgadoci