simple_format changes the text itself - ruby-on-rails

In Rails 3.0, the helper method simple_format changes the parameter itself.
I expected that it only returns the wrapped text.
2.0.0-p648 :001 > Rails.version
=> "3.0.20"
2.0.0-p648 :002 > s = "Hello"
=> "Hello"
2.0.0-p648 :003 > helper.simple_format(s)
=> "<p>Hello</p>"
2.0.0-p648 :004 > s
=> "<p>Hello</p>"
I checked with Rails 4.2 and it doesn't change the text.
Can someone please explain it?
Sam

The difference between implementations of this method in Rails 4.2 and Rails 3.0 is that in Rails 3.0 the passed string is modified (mutated by gsub!) and in Rails 4.2 it's not (it just returns a new modified string):
Rails 4.2:
2.4.0 :006 > s = "hello"
=> "hello"
2.4.0 :007 > simple_format s
=> "<p>hello</p>"
2.4.0 :008 > s
=> "hello"
The source code of different implementations can be found in the documentation

Related

Check values in a hash

I am working on a legacy Rails project that uses Ruby 1.8 .
I have an hash of key-value where value is a float number.
For example, my_hash = ['foo'=>12.20, 'bar'=>10.0]. How can I check if my_hash contains all zero values? e.g. ['foo'=>0, 'bar'=>0, 'whatever'=>0] or ['foo'=>0.0, 'bar'=>0, 'whatever'=>0.0].
I know I can loop through & check element one by one, but I just wonder is there a more elegant way?
use below code if my_hash is:
[{"foo"=>0.0, "bar"=>0, "whatever"=>0.0}]
my_hash.first.values.all?{|item| item.zero?}
or if my_hash is array, just:
my_hash.all?{|item| item.zero?}
Check all values in the hash are zero or not?
2.2.3 :006 > h={"foo"=>0.0, "bar"=>0, "whatever"=>0.0}
=> {"foo"=>0.0, "bar"=>0, "whatever"=>0.0}
2.2.3 :007 > h.values.all?{|a| a.zero?}
=> true
If it is an array of hash then
2.2.3 :001 > h = ['foo'=>0.0, 'bar'=>0, 'whatever'=>0.0]
=> [{"foo"=>0.0, "bar"=>0, "whatever"=>0.0}]
2.2.3 :004 > h[0].values.all?{|a| a.zero? }
=> true
OR
2.2.3 :014 > h
=> [{"foo"=>0.0, "bar"=>0, "whatever"=>0.0}]
2.2.3 :015 > h.first.values.all?{|a| a.zero?}
=> true
Any element is zero
2.2.3 :009 > h={"foo"=>0.0, "bar"=>2, "whatever"=>1.1}
=> {"foo"=>0.0, "bar"=>2, "whatever"=>1.1}
2.2.3 :010 > h.values.any?{|a| a.zero?}
=> true
2.2.3 :011 > h={"foo"=>0.2, "bar"=>2, "whatever"=>1.1}
=> {"foo"=>0.2, "bar"=>2, "whatever"=>1.1}
2.2.3 :012 > h.values.any?{|a| a.zero?}
=> false

ActiveRecord class (enum) behaving incorrectly with patch in config/initializers

I'm using ruby 2.2.3 and rails 4.2.4.
Background: I need the ability to re-use values across enums within the same model so I have patched in the latest version of Active Record's enum.rb as config/initializers/enum_patch.rb since they are adding prefix/suffix support in Rails 5 which will enable this functionality.
Issue: After patching in the code, Enum is no longer working correctly. See below:
class GatheringSession < ActiveRecord::Base
GatheringStates = %i(ready running finished errored)
enum :gathering_state => GatheringStates
...
end
Console (no patch). Correct behaviour:
2.2.3 :001 > gs2 = GatheringSession.last
=> #<GatheringSession id: 120, gathering_state: 2 ... >
2.2.3 :002 > gs2.gathering_state
=> "finished"
2.2.3 :003 > gs2.ready?
=> false
2.2.3 :004 > gs2.finished?
=> true
2.2.3 :005 > gs2.ready!
=> true
2.2.3 :007 > gs2.ready?
=> true
2.2.3 :008 > gs2.finished?
=> false
2.2.3 :009 > gs2.finished!
=> true
2.2.3 :010 > gs2.finished?
=> true
Console (patch):
2.2.3 :001 > gs2 = GatheringSession.last
=> #<GatheringSession id: 120, gathering_state: 2 ... >
2.2.3 :002 > gs2.gathering_state
=> 2
2.2.3 :003 > gs2.ready?
=> false
2.2.3 :004 > gs2.finished?
=> false
2.2.3 :005 > gs2.ready!
(0.2ms) BEGIN
SQL (0.8ms) UPDATE `gathering_sessions` SET `gathering_state` = 'ready', `updated_at` = '2015-10-31 00:28:36' WHERE `gathering_sessions`.`id` = 120
Mysql2::Error: Incorrect integer value: 'ready' for column 'gathering_state' at row 1: UPDATE `gathering_sessions` SET `gathering_state` = 'ready', `updated_at` = '2015-10-31 00:28:36' WHERE `gathering_sessions`.`id` = 120
(0.1ms) ROLLBACK
ActiveRecord::StatementInvalid: Mysql2::Error: Incorrect integer value: 'ready' for column 'gathering_state' at row 1: UPDATE `gathering_sessions` SET `gathering_state` = 'ready', `updated_at` = '2015-10-31 00:28:36' WHERE `gathering_sessions`.`id` = 120
...
from /Users/william/.rvm/gems/ruby-2.2.3/gems/activerecord-4.2.4/lib/active_record/persistence.rb:263:in `update!'
from /Users/william/code/repo/config/initializers/enum_patch.rb:193:in `block (4 levels) in enum'
After doing a little bit of testing, I've realized the problem is not the new code that I've patched in, but the fact that I'm patching in code period. Even when using the same code that is shipped with Rails 4.2.4 (here) I get the same (incorrect) behaviour.
Does anyone have an idea why this is happening and how I can fix it?

Difference between Ruby’s Hash and ActiveSupport’s HashWithIndifferentAccess

What is the difference between Ruby’s Hash and ActiveSupport’s HashWithIndifferentAccess? Which is the best for dynamic hashes?
Below is the simple example that will show you difference between simple ruby hash & a "ActiveSupport::HashWithIndifferentAccess"
HashWithIndifferentAccess allows us to access hash key as a symbol or string
Simple Ruby Hash
$ irb
2.2.1 :001 > hash = {a: 1, b:2}
=> {:a=>1, :b=>2}
2.2.1 :002 > hash[:a]
=> 1
2.2.1 :003 > hash["a"]
=> nil
ActiveSupport::HashWithIndifferentAccess
2.2.1 :006 > hash = ActiveSupport::HashWithIndifferentAccess.new(a: 1, b:2)
NameError: uninitialized constant ActiveSupport
from (irb):6
from /home/synerzip/.rvm/rubies/ruby-2.2.1/bin/irb:11:in `<main>'
2.2.1 :007 > require 'active_support/core_ext/hash/indifferent_access'
=> true
2.2.1 :008 > hash = ActiveSupport::HashWithIndifferentAccess.new(a: 1, b:2)
=> {"a"=>1, "b"=>2}
2.2.1 :009 > hash[:a]
=> 1
2.2.1 :010 > hash["a"]
=> 1
class HashWithIndifferentAccess is inherited from ruby "Hash" & above special behavior is added in it.
In Ruby Hash:
hash[:key]
hash["key"]
are different. In HashWithIndifferentAccess as the name suggests, you can access key either way.
Quoting official documentation to this:
Implements a hash where keys :foo and "foo" are considered to be the
same.
and
Internally symbols are mapped to strings when used as keys in the
entire writing interface (calling []=, merge, etc). This mapping
belongs to the public interface. For example, given:
hash = ActiveSupport::HashWithIndifferentAccess.new(a: 1)
You are
guaranteed that the key is returned as a string:
hash.keys # => ["a"]

Different result for Regexp match with Rails and Rubular?

I am using Rails 4.0.0 with Ruby 2.0.0 p247. I am writing an URL regexp matcher but I have no idea why it does not work:
2.0.0-p247 :033 > REGEXP = %r{\Ahttps:\/\/#{ Rails.configuration.aws[:bucket] }\.s3(-#{Rails.configuration.aws[:region]}|)\.amazonaws\.com\/(?<path>uploads\/.+\/(?<filename>.+))\?.+\z}.freeze
=> /\Ahttps:\/\/test-gem\.s3(-eu-west-1|)\.amazonaws\.com\/(?<path>uploads\/.+\/(?<filename>.+))\?.+\z/
2.0.0-p247 :034 > url = "https://test-gem.s3.amazonaws.com/uploads/2alrg16mvx6r-29590d114fb3257846c1a03330418da9/3031674-poster-p-1-for-25.jpg"
=> "https://test-gem.s3.amazonaws.com/uploads/2alrg16mvx6r-29590d114fb3257846c1a03330418da9/3031674-poster-p-1-for-25.jpg"
2.0.0-p247 :035 > REGEXP.match(url)
=> nil
But when I try to debug in things like Rubular, it does work. Any idea? Thanks!
Remove \?.+ in the end if your regexp
Might be a bug with Ruby 2.0.0. I'm using 2.1.3 and it works like you'd expect.
> r = /\Ahttps:\/\/test-gem\.s3(\A-eu-west-1\z|)\.amazonaws\.com\/(?<path>uploads\/.+\/(?<filename>.+))\z/
=> /\Ahttps:\/\/test-gem\.s3(\A-eu-west-1\z|)\.amazonaws\.com\/(?<path>uploads\/.+\/(?<filename>.+))\z/
> r.match("https://test-gem.s3.amazonaws.com/uploads/2alrg16mvx6r-29590d114fb3257846c1a03330418da9/3031674-poster-p-1-for-25.jpg")
=> #<MatchData
"https://test-gem.s3.amazonaws.com/uploads/2alrg16mvx6r-29590d114fb3257846c1a03330418da9/3031674-poster-p-1-for-25.jpg"
path:"uploads/2alrg16mvx6r-29590d114fb3257846c1a03330418da9/3031674-poster-p-1-for-25.jpg"
filename:"3031674-poster-p-1-for-25.jpg">

Rails n elements before last

In Rails I often do this:
Model.last(5).first
This retrieves element last-5.
Is there a built-in way of doing this?
The more common way is offset()
Model.offset(5).last
Edit (for lazy people):
1.8.7 :001 > User.first.id
=> 1
1.8.7 :002 > User.last.id
=> 143455
1.8.7 :003 > User.offset(5).last.id
=> 143450

Resources