url slugs with special characters

45 views
Skip to first unread message

fugee ohu

unread,
Jan 25, 2019, 6:00:10 AM1/25/19
to Ruby on Rails: Talk
I wanna convert my news stories to use slug urls based on the :headline column instead of id's but some of the rows contain special characters like double quotes, exclamation points, do I need to gsub those out

Walter Lee Davis

unread,
Jan 25, 2019, 9:06:22 AM1/25/19
to rubyonra...@googlegroups.com

> On Jan 25, 2019, at 6:00 AM, fugee ohu <fuge...@gmail.com> wrote:
>
> I wanna convert my news stories to use slug urls based on the :headline column instead of id's but some of the rows contain special characters like double quotes, exclamation points, do I need to gsub those out

An interesting theory, but FriendlyId already does this, quite elaborately. The logic that does the "dumbification" is delegated to ActiveSupport's parameterize method, which takes everything not-ASCII and transliterates it into ASCII, and replaces any run of whitespace with a single dash, and removes punctuation. Next, the slug is checked for duplicates with any existing record, and a UUID is appended if so. It's really quite well done and very settled code. I have been using FriendlyId for 8 years or more without encountering any error that wasn't my own mistake.

In another of your many threads, you mention that you are trying to create a slug out of the article's text, rather than the headline (as the documentation encourages). You may want to try starting from a truncated copy of the article text (or even following the directions) before you assume that FriendlyId is at fault here. I doubt that your article text will fit into the size constraints of a URL segment, particularly if you worry about IE users seeing the thing at all*'

Walter

*The entire URL, including prefix, host, port, and path, must be no more than 1,024 characters ASCII in order to be visited by IE.

fugee ohu

unread,
Jan 25, 2019, 4:34:17 PM1/25/19
to Ruby on Rails: Talk
I'm trying to parameterize the headline to create the slug I'm getting rollbacks for each record and then " NameError: wrong constant name admin" .rvm/gems/ruby-2.3.3/gems/activesupport-5.0.0/lib/active_support/inflector/methods.rb:268:in `const_get'
 

fugee ohu

unread,
Jan 26, 2019, 5:27:16 AM1/26/19
to Ruby on Rails: Talk


On Friday, January 25, 2019 at 9:06:22 AM UTC-5, Walter Lee Davis wrote:
So I have to change the length of the varchar field and the length of the index as well? 

Walter Lee Davis

unread,
Jan 26, 2019, 12:56:04 PM1/26/19
to rubyonra...@googlegroups.com
I don't know what your schema looks like right now. Here's how I have always used FriendlyID:

1. I have a `title` column, normal string, 255 characters limit. The client or user can enter whatever she wants up to that limit.
2. I use the FriendlyID migration generator to create the slug column on my model.
3. I configure FriendlyID according to the instructions (extend, then friendly_id :title, use: :slugged in the model).
4. Profit.

There's really nothing else needed except changing find to friendly.find in the controller.

I don't give the client/user the ability to create a too-long slug, by starting from a source text that is short enough.

If you wanted to start from the article text (say, a true text field of thousands of characters), I would start by trimming that text down to the first couple hundred characters. And then, because slugs must be unique, I would imagine you would have quite a few natural collisions, and might end up with a fair amount of disambiguated slugs that end in UUID-shaped garbage strings.

I believe that FriendlyId has the ability to call methods (rather than being bound to just the actual database columns) when calculating the slug, so you could start from `article_body` (a text column, tens of thousands of characters or a clob) and then limit that with truncate or another string-splitting method, like this:

(in your model)

friendly_id :article_preview, use: :slugged

def article_preview
# cut off at 200 characters, without an ellipsis
article_text.truncate(200, '')
end

Does that make sense?

Walter

>
> --
> You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to rubyonrails-ta...@googlegroups.com.
> To post to this group, send email to rubyonra...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/rubyonrails-talk/0d80957a-d522-4f30-9aeb-a355ea132b0b%40googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

fugee ohu

unread,
Jan 26, 2019, 1:57:21 PM1/26/19
to Ruby on Rails: Talk
Yes I forgot that my :headline column is actually text so this would be necessary Also I don't see reason to use friendly_id for anything but the  show action, why try to find records by slug for edits, updates and deletes?
Message has been deleted

Walter Lee Davis

unread,
Jan 26, 2019, 3:04:14 PM1/26/19
to rubyonra...@googlegroups.com
No, there's no actual reason you have to do this for all routes. You can mix the two (Article.find and Article.friendly.find) within the same controller.

Another thing you may have missed in the documentation is that friendly.find will also find the actual record by its ID, too. So there's no harm in passing the ID in most of the routes and the slug in one route, one method will find either way. I suppose it may be slower that way, but only just a little. This happens here:

https://github.com/norman/friendly_id/blob/master/lib/friendly_id/finder_methods.rb#L20

Walter

> --
> You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to rubyonrails-ta...@googlegroups.com.
> To post to this group, send email to rubyonra...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/rubyonrails-talk/bb0d026c-f9ec-4286-8329-3f30a2d99b2a%40googlegroups.com.

fugee ohu

unread,
Jan 26, 2019, 5:27:04 PM1/26/19
to Ruby on Rails: Talk
TypeError: no implicit conversion of Symbol into Integer
from app/models/press_release.rb:17:in `truncated_headline'


class PressRelease < ApplicationRecord

  extend FriendlyId
  friendly_id :truncated_headline, use: :slugged

         
  def truncated_headline 
  # cut off at 200 characters, without an ellipsis 
headline.truncate(255, '') 
  end 

Walter Lee Davis

unread,
Jan 26, 2019, 6:58:17 PM1/26/19
to rubyonra...@googlegroups.com

> On Jan 26, 2019, at 5:27 PM, fugee ohu <fuge...@gmail.com> wrote:
>
> TypeError: no implicit conversion of Symbol into Integer
> from app/models/press_release.rb:17:in `truncated_headline'
>
>
> class PressRelease < ApplicationRecord
>
> extend FriendlyId
> friendly_id :truncated_headline, use: :slugged
>
>
> def truncated_headline
> # cut off at 200 characters, without an ellipsis
> headline.truncate(255, '')
> end
>

Aha. truncate takes named arguments past the first one. The correct signature is

headline.truncate(255, omission: '')

This should work.

Walter

fugee ohu

unread,
Jan 26, 2019, 11:49:10 PM1/26/19
to Ruby on Rails: Talk
Still rolling back 

Walter Lee Davis

unread,
Jan 27, 2019, 12:24:25 AM1/27/19
to rubyonra...@googlegroups.com
Show me an example from your development console. Copy and paste. Make sure that you include the part where we can see the parameters being passed into your controller. I suspect that you are trying to pass a type = 'admin' parameter somewhere, that's what the error looked like earlier. Type columns in polymorphic relationships must be passed a valid constant name, which will begin with an upper-case letter. If there is a model in that relationship named admin, you would pass Admin rather than admin.

Walter

Message has been deleted

fugee ohu

unread,
Jan 27, 2019, 7:35:13 AM1/27/19
to Ruby on Rails: Talk
 Loading development environment (Rails 5.2.0)
2.3.3 :001 > PressRelease.find_each(&:save)
  Query Trace > (irb):1:in `irb_binding'
   (24.1ms)  SET NAMES utf8,  @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO'),  @@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 2147483
  Query Trace > (irb):1:in `irb_binding'
  PressRelease Load (53.8ms)  SELECT  `press_releases`.* FROM `press_releases` ORDER BY `press_releases`.`id` ASC LIMIT 1000
  Query Trace > (irb):1:in `irb_binding'
   (7.1ms)  BEGIN
  Query Trace > (irb):1:in `irb_binding'
  PressRelease Exists (9.4ms)  SELECT  1 AS one FROM `press_releases` WHERE `press_releases`.`id` != 2 AND `press_releases`.`slug` = 'outskirts-of-love-is-available-now-some-autographed-copies-remain' LIMIT 1
  Query Trace > (irb):1:in `irb_binding'
   (7.9ms)  ROLLBACK
  Query Trace > (irb):1:in `irb_binding'
   (5.6ms)  BEGIN
  Query Trace > (irb):1:in `irb_binding'
  PressRelease Exists (9.6ms)  SELECT  1 AS one FROM `press_releases` WHERE `press_releases`.`id` != 3 AND `press_releases`.`slug` = 'shemekia-copeland-to-appear-in-new-york-and-teaneck' LIMIT 1
  Query Trace > (irb):1:in `irb_binding'
   (6.3ms)  ROLLBACK
  Query Trace > (irb):1:in `irb_binding'
   (6.0ms)  BEGIN
  Query Trace > (irb):1:in `irb_binding'
  PressRelease Exists (12.7ms)  SELECT  1 AS one FROM `press_releases` WHERE `press_releases`.`id` != 5 AND `press_releases`.`slug` = 'al-basile-creates-new-roots-music-masterpiece-with-b-s-expression-due-september-18-on-sweetspot-records-latest-release-is-most-fully-realized-album-yet' LIMIT 1
  Query Trace > (irb):1:in `irb_binding'
   (8.1ms)  ROLLBACK
  Query Trace > (irb):1:in `irb_binding'
   (6.0ms)  BEGIN
  Query Trace > (irb):1:in `irb_binding'
  PressRelease Exists (8.9ms)  SELECT  1 AS one FROM `press_releases` WHERE `press_releases`.`id` != 6 AND `press_releases`.`slug` = 'new-cd-from-british-blues-godfather-john-mayall-find-a-way-to-care-set-for-release-september-4th-on-forty-below-records-vinyl-lp-to-follow-in-fall' LIMIT 1
  Query Trace > (irb):1:in `irb_binding'
   (6.8ms)  ROLLBACK
  Query Trace > (irb):1:in `irb_binding'

Walter Lee Davis

unread,
Jan 27, 2019, 2:43:46 PM1/27/19
to rubyonra...@googlegroups.com
Okay, since you're not in the development console, and aren't handling a PUT or PATCH, you don't have parameters to look at here. So this is less useful than I had hoped. Please answer these questions, preferably inline, so I don't have to play hunt-and-peck to figure this out.

1. When you added FriendlyId to your app, did you use the built-in generator to add the friendly_id_slugs table to your app?

2. After you added gem 'friendly_id' to your Gemfile, and ran bundle install, did you at any point after that do anything that caused the friendly_id gem to upgrade to a newer version? Hint: look through the git history on your Gemfile.lock file, and look for any (upward, I'm guessing) movement of the version number of the friendly_id gem. The line you are looking at will be the one that reads something like

friendly_id (5.2.5)

with nothing else on the same line. Any other reference to friendly_id will be in dependencies, not the actual version of the gem that your app is loading and running.

3. What happens if you change &:save to &:save! (with a bang!) in order to die spectacularly and throw a visible error?

4. What happens if you unroll the Symbol-to-Proc sugar into its long-hand equivalent? Example:

YourModel.find_each do |instance|
instance.save!
puts instance.errors.full_messages
end

That should die after the first model with errors, and throw out a more useful error message than ROLLBACK.

If the answer to #2 is Yes, then you will probably need to read through the upgrade instructions on the FriendlyId project README on GitHub, and figure out what you didn't do. That's not likely to be the problem, but I put it out there because this project has had some tectonic shifts in its schema, and all of them are covered with extra migrations that you optionally run when you update. Missing any of these could cause the whole thing to fail. But that's only likely if you started with FriendlyId a while ago, and then did something unrelated with Bundler that caused this gem to upgrade further than you were expecting. Particularly if you see that the version has changed in the major number, like from 3.x.x to 4.x.x, that's when you would want to be very careful to check those instructions.

Walter


fugee ohu

unread,
Jan 27, 2019, 3:55:46 PM1/27/19
to Ruby on Rails: Talk
I'm working in the rails console

In Gemfile.lock     friendly_id (5.2.5)
 is listed under GEM and   friendly_id (~> 5.2.4)
 is listed under DEPENDENCIES

Also at system prompt gem list shows 5.1.0 is installed as well as a left over dependency for spree_core 3.2.8 which I'm not using anymore

 $ gem list friendly_id

*** LOCAL GEMS ***

friendly_id (5.2.5, 5.1.0)

fugee ohu

unread,
Jan 27, 2019, 4:11:53 PM1/27/19
to Ruby on Rails: Talk
 ActiveRecord::RecordInvalid: translation missing: en-US.activerecord.errors.messages.record_invalid
from (irb):1

fugee ohu

unread,
Jan 27, 2019, 4:13:43 PM1/27/19
to Ruby on Rails: Talk
Nothing under the GIT section in Gemfile.lock related to this gem

Walter Lee Davis

unread,
Jan 27, 2019, 4:44:58 PM1/27/19
to rubyonra...@googlegroups.com
I think you missed the point of this. Use git log Gemfile.lock to see the various save points of this file over time, and see if the line that includes friendly_id(your.version.number) has ever changed in that time.

Walter

Walter Lee Davis

unread,
Jan 27, 2019, 4:47:48 PM1/27/19
to rubyonra...@googlegroups.com
This is interesting. Try removing the .full_messages part and run this again. You have an invalid record, which means it can't be saved. You have to figure out what the error is. What validations do you have on the object? What validations do you have on the related models? What requirements are you missing? That's where your problem is -- this has zero to do with friendly_id.

Walter

>
> --
> You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to rubyonrails-ta...@googlegroups.com.
> To post to this group, send email to rubyonra...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/rubyonrails-talk/0055fa7d-84e6-4082-83ca-f9e18aeb78ad%40googlegroups.com.

fugee ohu

unread,
Jan 27, 2019, 5:01:14 PM1/27/19
to Ruby on Rails: Talk
  belongs_to :poster, polymorphic: true
  attr_accessor :club_id
  attr_accessor :festival_id
  attr_accessor :user_venue_id
  has_many :pictures, as: :imageable

  def self.search(search)
    where("headline LIKE ? OR storyline LIKE ? OR publicist LIKE ?", "%#{search}%", "%#{search}%", "%#{search}%")
  end
  
  def truncated_headline 
  # cut off at 200 characters, without an ellipsis 
headline.truncate(255, omission: '') 
  end 
  
  validates :publicist, :headline, :storyline, :dateline, :genre_id, :presence => true
  validates :venue_state,  :presence => true, :if =>  Proc.new { |e| e.venue_country == "US" && !(e.press_release_type="tour") }
  validates :venue_state,  :presence => false, :if =>  Proc.new { |e| e.venue_country != "US" }
  validates :venue, :venue_country, :venue_city, :venue_address, :showdate, :showtime,  :presence => true, :unless =>  Proc.new { |e| e.poster_type == 'Admin' || (e.press_release_type="tour") }
  validates :showdate,  :presence => true, :if =>  Proc.new { |e| e.club_id.present? || (e.festival_id.present?) || (e.user_venue_id.present?) || (e.venue_name.present?) }
  validates :showdate,   :date => { :after => Time.now + 2.hour }, :if =>  Proc.new { |e| e.user_id.present? }
  validates :image_url, allow_blank: true,  format: {with: %r{\.(gif|jpg|png)\Z}i, message: 'must be a URL for GIF, JPG or PNG image.'}
  validates :showdate,  :presence => true, :if =>  Proc.new { |e| e.user_id.present? }
  
  
  VENUE_STATE_TYPES = 
  [
    ['Alabama', 'AL'],
    ...
    ['Wyoming', 'WY']
  ]


end

Walter Lee Davis

unread,
Jan 27, 2019, 5:31:11 PM1/27/19
to rubyonra...@googlegroups.com
Interesting, but meaningless without seeing what the error is when you try to save a record. Try opening up this application in console, selecting the first record in the press releases, and saving it. See what you get in the console error message.

rails c development

pr = PressRelease.first
pr.touch
pr.save!

What happens here?

All the console stuff you have been showing so far appears to be in production, and the errors don't include a stack trace or any detail besides the database ROLLBACK.

Try to repeat the error in development, or set your log level to info in production and try to repeat it there.

Walter

> --
> You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to rubyonrails-ta...@googlegroups.com.
> To post to this group, send email to rubyonra...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/rubyonrails-talk/1b6f26b5-8b6a-4e97-8467-261ea7f2e489%40googlegroups.com.

fugee ohu

unread,
Jan 27, 2019, 8:03:04 PM1/27/19
to Ruby on Rails: Talk
I'm working in development env but my  database is real data from mysqldump of production database

fugee ohu

unread,
Jan 27, 2019, 8:34:58 PM1/27/19
to Ruby on Rails: Talk
 2.3.3 :003 > pr.save
  Query Trace > (irb):3:in `irb_binding'
   (7.1ms)  BEGIN
  Query Trace > (irb):3:in `irb_binding'
  PressRelease Exists (11.8ms)  SELECT  1 AS one FROM `press_releases` WHERE `press_releases`.`id` != 2 AND `press_releases`.`slug` = 'outskirts-of-love-is-available-now-some-autographed-copies-remain' LIMIT 1
  Query Trace > (irb):3:in `irb_binding'
   (6.5ms)  ROLLBACK
 => false 

Walter Lee Davis

unread,
Jan 28, 2019, 10:23:43 AM1/28/19
to rubyonra...@googlegroups.com
Try this:

PressRelease.update_all slug: nil

Then try running your &:save! again.

Walter

fugee ohu

unread,
Jan 28, 2019, 8:47:55 PM1/28/19
to Ruby on Rails: Talk
Still getting ROLLBACK's 

Walter Lee Davis

unread,
Jan 29, 2019, 8:31:18 AM1/29/19
to rubyonra...@googlegroups.com
p = PressRelease.first

p.valid?

p.errors.inspect

What do you see?

Walter



fugee ohu

unread,
Jan 29, 2019, 9:55:01 PM1/29/19
to Ruby on Rails: Talk
 "#<ActiveModel::Errors:0x00557931a9a9e8 @base=#<PressRelease id: 2, publicist: \"Alligator Records\", headline: \"OUTSKIRTS OF LOVE Is Available Now! Some Autograph...\", storyline: \"Alligator Records News, Blues & More \\r\\nOUTSKIRTS O...\", dateline: \"2015-09-23 00:00:00\", created_at: \"2015-09-23 22:57:00\", updated_at: \"2019-01-28 01:32:11\", image_url: \"9.png\", storyline_html_tail: nil, user_id: nil, artist_id: nil, venue_name: nil, venue_address: nil, venue_phone: nil, showdate: nil, showtime: nil, showtime_second: nil, poster_type: nil, poster_id: nil, additional_info: nil, venue_country: nil, venue_state: nil, venue_city: nil, genre_id: 1, tour_id: nil, press_release_type: \"tour\", venue_id: nil, venue_type: nil, venue_address0: nil, postal_code: nil, venue_f_address: nil, venue_postal_code: nil, top_story: nil, slug: nil>, @messages={:poster=>[\"translation missing: en-US.activerecord.errors.models.press_release.attributes.poster.required\"]}, @details={:poster=>[{:error=>:blank}]}>" 

Walter Lee Davis

unread,
Jan 29, 2019, 11:12:29 PM1/29/19
to rubyonra...@googlegroups.com
Great. Now you have your answer. The poster is required, and not valued, so the save won't work. Figure out why the poster is required, and you will fix your application. To be clear, this has nothing at all to do with FriendlyId.

Walter

fugee ohu

unread,
Jan 30, 2019, 6:21:28 AM1/30/19
to Ruby on Rails: Talk
Because PressRelease belongs_to :poster 

fugee ohu

unread,
Jan 31, 2019, 5:38:22 AM1/31/19
to Ruby on Rails: Talk
Having this problem on another database When I run errors on a row it says :name is blank but if I check the database I can't find any rows with null :name field, they all have values
 => #<ActiveModel::Errors:0x0055c65e1b4ef8 @base=#<Picture id: 2, comment: "Henry McCarty", imageable_id: 1, imageable_type: "Photo", content_type: nil, created_at: "2018-09-20 02:08:02", updated_at: "2018-10-25 13:41:24", name: "Billy_the_Kid_Ferrotype.jpg", designation: nil, blog_id: nil, caption: "Unretouched original ferrotype of Bonney c. 1880", details: "Henry McCarty", copyright_claim: false, source_page: nil, slug: nil>, @messages={:name=>["translation missing: en-US.activerecord.errors.models.picture.attributes.name.blank"]}, @details={:name=>[{:error=>:blank}]}> 

class Picture < ActiveRecord::Base
 belongs_to :imageable, polymorphic: true
 
  def truncated_details
truncated_details=details.truncate(1024, omission:'')
  end

 extend FriendlyId
 friendly_id :truncated_details, use: :slugged  
 
 validates :name, presence: true
 mount_uploader :name, PictureUploader
 has_many :person_pictures
 has_many :people, through: :person_pictures
 has_many :photo_pictures
 has_many :photos, through: :photo_pictures
 attr_accessor  :person_id
 attr_accessor  :picture_id
 def formatted_name
  "#{name.thumb}"
 end

end

fugee ohu

unread,
Jan 31, 2019, 1:04:00 PM1/31/19
to Ruby on Rails: Talk
What about the through models in has_many_through relationships where i've applied friendly_id to the outside models Should I setup the through models to use friendly_id
Reply all
Reply to author
Forward
0 new messages