0

I have a Project model that belongs to a User. A User has_many Projects. I have setup FriendlyID according to the gem instructions for User model, however it is not working in this scenario.

<%= link_to gravatar_for(project.user, size: 50), project.user %>

The above creates a link with the numerical ID of the user (project.user) instead of a friendly URL (i.e. http://localhost:3000/users/102 instead of what I want, http://localhost:3000/users/*random-gen-string*).

User.rb file:

class User < ApplicationRecord
  extend FriendlyId
  friendly_id :generated_slug, use: :slugged

  def generated_slug
    require 'securerandom'
    @random_slug ||= persisted? ? friendly_id : SecureRandom.hex(15)
  end

I think the problem is that project.user is set in the projects_controller.rb to the user ID (via current_user.projects.build...). If I could somehow access the Friendly ID for User in the projects_controller.rb I may be able to save it in the database and access it like project.user_friendly_id. Not sure..

Relevant code in projects_controller:

def create
 @project = current_user.projects.build(project_params)
 # code
end

What is the best way to go about making the above link link to the Friendly ID and not the user (i.e. http://localhost:3000/users/*random-gen-string* is what I want instead of http://localhost:3000/users/102)?

MZaragoza
  • 10,108
  • 9
  • 71
  • 116
user3180
  • 1,369
  • 1
  • 21
  • 38

3 Answers3

1

Update:

As discussed in the chatroom, User.find_each(&:save!) reveals the errors when saving the User model. In the above case, the lack of password input was preventing the User records from being saved. Removing the validation temporarily allowed saving the User and thus regenerating slugs.

(Original answer left for history) You can override the to_param method in your User model like this

class User < ApplicationRecord
  # some code

  def to_param
    slug
  end

And then that is used to generate the link. More on that in the guides.

Eyeslandic
  • 14,553
  • 13
  • 41
  • 54
  • Do I need to change project.user to something? I tried the above code, (using generated_slug instead of slug) and project.user returned nill. "No route matches {:action=>"show", :controller=>"users", :id=>nil} missing required keys: [:id]" – user3180 Dec 30 '16 at 19:31
  • `user_path(slug: project.user.slug)` probably. – Eyeslandic Dec 30 '16 at 19:35
  • Isn't the slug generated at this time? You might want to check that too. – Eyeslandic Dec 30 '16 at 19:36
  • I just checked, my existing users at least have "slug: nil". I ran this: User.find_each(&:save) / but still slugs are nill – user3180 Dec 30 '16 at 19:43
  • What are you trying to do in your `generated_slug` method, I think the problem must be in there. You can just have it return `SecureRandom.hex(15)` since friendly_id doesn't update the slug unless you set it to `nil` yourself. – Eyeslandic Dec 30 '16 at 19:47
  • Generated slug is just trying to create a random string for user as a slug. I tried returning just SecureRandom.hex(15) and running User.find_each(&:save) but the users' still have slug: nil – user3180 Dec 30 '16 at 19:52
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/131929/discussion-between-richard-and-iceman). – user3180 Dec 30 '16 at 19:55
0

When you build your link_to you can call the user.slug to ensure that you get the proper info

<%= link_to gravatar_for(project.user, size: 50), project.user.slug %>

that will generate the link that you are expecting http://localhost:3000/users/random-gen-string

MZaragoza
  • 10,108
  • 9
  • 71
  • 116
  • `gravatar_for` is for displaying the image, the second part is the url, `project.user` – Eyeslandic Dec 30 '16 at 13:31
  • then just move the slug for the proper part of the `link_to`, Good Eye – MZaragoza Dec 30 '16 at 13:33
  • That doesn't produce a working link, slug is just a string and will create `a href='some slug'` – Eyeslandic Dec 30 '16 at 13:43
  • <%= link_to gravatar_for(project.user, size: 50), project.user.slug %> I believe "project.user.slug" evaluates to nil because after I do this the link just points to the root URL – user3180 Dec 30 '16 at 19:35
0

Here is an example of cities with increasing order of specificity.

 def slug_candidates
[
  :name,
  [:name, :city],
  [:name, :street, :city],
  [:name, :street_number, :street, :city]
]

end

In case of conflicting slugs it is better to use user-friendly names then UUID (e.g. 2bc2-d3dd-4f29-b2ad)