Word truncation #16190

Merged
merged 1 commit into from Jul 16, 2014

Conversation

Projects
None yet
3 participants
@oss92
Contributor

oss92 commented Jul 16, 2014

Patched the truncate strings method to include truncation by word

Examples:

'Once upon a time'.truncate(4, word: true)
=> "Once upon a time"

'Once upon a time in a world far far away'.truncate(4, word: true)
=> "Once upon a time..."

'Once<br>upon<br>a<br>time<br>in<br>a<br>world'.truncate(5, word: true, separator: '<br>')
 => "Once<br>upon<br>a<br>time<br>in..."

'Once<br>upon<br>a<br>time<br>in<br>a<br>world'.truncate(5, word: true, separator: '<br>', omission: '[...]')
 => "Once<br>upon<br>a<br>time<br>in[...]"
@rafaelfranca

This comment has been minimized.

Show comment
Hide comment
@rafaelfranca

rafaelfranca Jul 16, 2014

Member

Can we implement another method instead of adding a new option?

Member

rafaelfranca commented Jul 16, 2014

Can we implement another method instead of adding a new option?

@oss92

This comment has been minimized.

Show comment
Hide comment
@oss92

oss92 Jul 16, 2014

Contributor

yes we can, I will implement it an create a new pull request

Contributor

oss92 commented Jul 16, 2014

yes we can, I will implement it an create a new pull request

@matthewd

This comment has been minimized.

Show comment
Hide comment
@matthewd

matthewd Jul 16, 2014

Member

You can just update this pull request; no need for a new one.

If we're going to add such a method, hopefully we can make it a bit more performant, too... this sounds like it would be allocating a lot of objects.

Member

matthewd commented Jul 16, 2014

You can just update this pull request; no need for a new one.

If we're going to add such a method, hopefully we can make it a bit more performant, too... this sounds like it would be allocating a lot of objects.

@oss92

This comment has been minimized.

Show comment
Hide comment
@oss92

oss92 Jul 16, 2014

Contributor

okay will do. Thanks for the advice regarding the pull request

Contributor

oss92 commented Jul 16, 2014

okay will do. Thanks for the advice regarding the pull request

@oss92

This comment has been minimized.

Show comment
Hide comment
@oss92

oss92 Jul 16, 2014

Contributor

Done and tested, less objects allocated and everything is working fine.

Also added rtruncate to get the rest of a truncated string. This is useful in web apps when truncating strings and having a 'read more...' link, the rest of the string is now easily gotten.

Example
'Once upon a time in a world far far away'.truncate(27, omission: '') + 'Once upon a time in a world far far away'.rtruncate(27, omission: '')
=> "Once upon a time in a world far far away"

Contributor

oss92 commented Jul 16, 2014

Done and tested, less objects allocated and everything is working fine.

Also added rtruncate to get the rest of a truncated string. This is useful in web apps when truncating strings and having a 'read more...' link, the rest of the string is now easily gotten.

Example
'Once upon a time in a world far far away'.truncate(27, omission: '') + 'Once upon a time in a world far far away'.rtruncate(27, omission: '')
=> "Once upon a time in a world far far away"

+ #
+ # 'Once upon a time in a world far far away'.truncate(27, omission: '') + 'Once upon a time in a world far far away'.rtruncate(27, omission: '')
+ # # => "Once upon a time in a world far far away"
+ def rtruncate(truncate_at, options = {})

This comment has been minimized.

@matthewd

matthewd Jul 16, 2014

Member

👎

This comment has been minimized.

@matthewd

matthewd Jul 16, 2014

Member

I don't think it's sufficiently useful.

(Also, the '(Read more) ...' example seems at best misleading... if you're passing a different omission than you gave to truncate, things are surely going to get confusing?)

@matthewd

matthewd Jul 16, 2014

Member

I don't think it's sufficiently useful.

(Also, the '(Read more) ...' example seems at best misleading... if you're passing a different omission than you gave to truncate, things are surely going to get confusing?)

This comment has been minimized.

@oss92

oss92 Jul 16, 2014

Contributor

The read more part is just an example, yes it may be a bit misleading for some developers but the method is useful for, as I said, getting the rest of the truncated string without having to sub! two strings from each other.

@oss92

oss92 Jul 16, 2014

Contributor

The read more part is just an example, yes it may be a bit misleading for some developers but the method is useful for, as I said, getting the rest of the truncated string without having to sub! two strings from each other.

This comment has been minimized.

@matthewd

matthewd Jul 16, 2014

Member

Yeah, I understand the use case... the problem is just that adding a new method to AS requires a pretty high standard of justification, and (personally) I don't think this clears it.

@matthewd

matthewd Jul 16, 2014

Member

Yeah, I understand the use case... the problem is just that adding a new method to AS requires a pretty high standard of justification, and (personally) I don't think this clears it.

This comment has been minimized.

@oss92

oss92 Jul 16, 2014

Contributor

Okay, after all it is off-point from the 'word truncation' so it can be removed

@oss92

oss92 Jul 16, 2014

Contributor

Okay, after all it is off-point from the 'word truncation' so it can be removed

@oss92

This comment has been minimized.

Show comment
Hide comment
@oss92

oss92 Jul 16, 2014

Contributor

The documentation is identical to that of truncate but that's for consistency. Shall I change these lines or do you think the rtruncate method is not at all useful?

Contributor

oss92 commented Jul 16, 2014

The documentation is identical to that of truncate but that's for consistency. Shall I change these lines or do you think the rtruncate method is not at all useful?

+ split(options[:separator])[0...words_count].join(options[:separator])
+ else
+ split[0...words_count].join(' ')
+ end

This comment has been minimized.

@matthewd

matthewd Jul 16, 2014

Member

The split here is still allocating a separate string for every word... what about something like:

def truncate_words(words_count, options={})
  sep = options[:separator] || /(?<=\w)\b/
  sep = Regexp.escape(sep.to_s) unless Regexp === sep
  if self =~ /^((?:.+?#{sep}){#{words_count - 1}}.+?)#{sep}.*/
    $1 + (options[:omission] || '...')
  else
    dup
  end
end
@matthewd

matthewd Jul 16, 2014

Member

The split here is still allocating a separate string for every word... what about something like:

def truncate_words(words_count, options={})
  sep = options[:separator] || /(?<=\w)\b/
  sep = Regexp.escape(sep.to_s) unless Regexp === sep
  if self =~ /^((?:.+?#{sep}){#{words_count - 1}}.+?)#{sep}.*/
    $1 + (options[:omission] || '...')
  else
    dup
  end
end

This comment has been minimized.

@oss92

oss92 Jul 16, 2014

Contributor

Yes something like this is much better actually

It just has this problem of a character sticking to the word at the end
For one of the test for my method against yours
Expected: "Hello Big World!"
Actual: "Hello Big World..."

But overall it is much better, it should be the one used because of its efficiency.

@oss92

oss92 Jul 16, 2014

Contributor

Yes something like this is much better actually

It just has this problem of a character sticking to the word at the end
For one of the test for my method against yours
Expected: "Hello Big World!"
Actual: "Hello Big World..."

But overall it is much better, it should be the one used because of its efficiency.

This comment has been minimized.

@matthewd

matthewd Jul 16, 2014

Member

Ah, depending on what you want, try /\s+/ or /\b(?=\w)/.

Or, after building $1 + omission, it could compare the length of the result to decide whether it should still just return dup after all.

@matthewd

matthewd Jul 16, 2014

Member

Ah, depending on what you want, try /\s+/ or /\b(?=\w)/.

Or, after building $1 + omission, it could compare the length of the result to decide whether it should still just return dup after all.

This comment has been minimized.

@oss92

oss92 Jul 16, 2014

Contributor

Yes it works now if
sep = options[:separator] || /\s+/

For me this is better than comparing the length at the end. All tests are fine now. Now, shall I commit this on the same branch or will you create your own pull request with that?

@oss92

oss92 Jul 16, 2014

Contributor

Yes it works now if
sep = options[:separator] || /\s+/

For me this is better than comparing the length at the end. All tests are fine now. Now, shall I commit this on the same branch or will you create your own pull request with that?

This comment has been minimized.

@oss92

oss92 Jul 16, 2014

Contributor

Pardon me I still have limited experience with "open-source"

@oss92

oss92 Jul 16, 2014

Contributor

Pardon me I still have limited experience with "open-source"

This comment has been minimized.

@matthewd

matthewd Jul 16, 2014

Member

Yep, go ahead and update with that... and then squash down to a single commit, and add a CHANGELOG entry.

Then we can see whether anyone else has a 👍/👎 opinion on adding the new method. 😄

@matthewd

matthewd Jul 16, 2014

Member

Yep, go ahead and update with that... and then squash down to a single commit, and add a CHANGELOG entry.

Then we can see whether anyone else has a 👍/👎 opinion on adding the new method. 😄

@oss92

This comment has been minimized.

Show comment
Hide comment
@oss92

oss92 Jul 16, 2014

Contributor

Ready to merge 😄

Contributor

oss92 commented Jul 16, 2014

Ready to merge 😄

@matthewd matthewd merged commit a9d3b77 into rails:master Jul 16, 2014

1 check was pending

continuous-integration/travis-ci The Travis CI build is in progress
Details

matthewd added a commit that referenced this pull request Jul 16, 2014

@matthewd

This comment has been minimized.

Show comment
Hide comment
@matthewd

matthewd Jul 16, 2014

Member

Thanks!

I moved your changelog entry to the top, and fixed an issue with handling of multi-line strings in my suggested regexp.

After I pushed, I noticed that your git committer name is "root" 😟. You can submit a PR to https://github.com/fxn/rails-contributors/blob/master/app/models/names_manager.rb to fix up your entry on http://contributors.rubyonrails.org/, if you like. 😅

Member

matthewd commented Jul 16, 2014

Thanks!

I moved your changelog entry to the top, and fixed an issue with handling of multi-line strings in my suggested regexp.

After I pushed, I noticed that your git committer name is "root" 😟. You can submit a PR to https://github.com/fxn/rails-contributors/blob/master/app/models/names_manager.rb to fix up your entry on http://contributors.rubyonrails.org/, if you like. 😅

@oss92

This comment has been minimized.

Show comment
Hide comment
@oss92

oss92 Jul 16, 2014

Contributor

I shall add my commit SHA and my name to this method, correct me if I am mistaken please. Thanks

self.authors_of_special_cased_commits(commit)
Contributor

oss92 commented Jul 16, 2014

I shall add my commit SHA and my name to this method, correct me if I am mistaken please. Thanks

self.authors_of_special_cased_commits(commit)
@matthewd

This comment has been minimized.

Show comment
Hide comment
@matthewd

matthewd Jul 16, 2014

Member

👍

Member

matthewd commented Jul 16, 2014

👍

@oss92 oss92 referenced this pull request in rails/rails-contributors Jul 17, 2014

Merged

Added commit SHA and name for contribution #49

@oss92 oss92 deleted the oss92:word_truncation branch Jul 17, 2014

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment