Flowdock

Notes posted to Ruby on Rails

RSS feed
May 25, 2016
0 thanks

Active Record Import

With activerecord-import, you’d just add your records to an array and call import:

records_to_import = pricing_data.map do |location, price|
  Inventory.new(location: location, price: price) 
end

Inventory.import records_to_import 
May 25, 2016
0 thanks
May 25, 2016 - (v1.0.0 - v3.1.0)
0 thanks
May 19, 2016 - (>= v4.1.8)
0 thanks

Careful with arel column

I use what @equivalent suggests a lot but be careful, you MUST state the direction otherwise methods like take/last/first will fail silently!

StatusChange.arel_table[‘created_at’]. asc

not:

StatusChange.arel_table[‘created_at’]

April 12, 2016
0 thanks

`value` or `text` method with parameter.

If your value or text method requires a parameter, like to_s(:select) then you need to create a separate method that references that in your model, like:

def to_s_select
  to_s(:select)
end

You can’t pass it in as a string like 'to_s(:select)'.

You have to use :to_s_select or 'to_s_select'.

March 23, 2016
1 thank

RE: RE: FALSE: Creates record by given attributes only if table is empty

keredson is still a little off on the behavior.

>> Where in reality this would grab the “first” record (say w/ email “john@smith.com”), and change its email to “derek@somwhere.com”, a fairly surprising action that doesn’t obviously fail, leading to some pretty subtle bugs.

This isn’t right, as if you look at the source it calls: “first || create(attributes, &block)”

So in the example of:

User.first_or_create(email: 'derek@somwhere.com')

it would find the first user with any email, and return it. And thats it. The attributes passed in as params are only used in the event that first returns no matches, and create is called.

I’m using it in a way similar to:

Foo.where(bar: baz_params[:bar]).first_or_create(baz_params)

This will find the first Foo where bar is equal to the bar sent from baz_params. If none is found, it will create it. It’s useful for me when importing large amounts of data where I know there will be duplicate records.

March 21, 2016
0 thanks

Should include information about optional block

If a block exists, will return true if any records in the relation is true for the given block. Otherwise, returns true is there are any records.

March 21, 2016
0 thanks

Description

Selects the first record within a relation if it exists, otherwise creates a new record with the optional attributes.

March 17, 2016
0 thanks

No grammatical error

rajivekjain:

“A, B, and C” is correct in English, and is preferred by most style manuals. “A, B and C” is also correct in English. See en.wikipedia.org/wiki/Serial_comma

March 17, 2016 - (>= v4.2.1)
0 thanks

Default values

By default :on_update and :on_delete have :restrict value.

March 11, 2016 - (>= v4.0.2)
1 thank

Ordering on associations using merge

For ordering on the attribute of an associated model you can add joins to query and merge order scope:

Product.joins(:category).merge(Category.order(priority: :desc))
March 6, 2016
1 thank

RE: FALSE: Creates record by given attributes only if table is empty

Dino’s comment was almost certainly due to a misunderstanding of the API, a mistake I made myself the first time I used it, and one I’ve witnessed multiple others make as well.

The fact that this method takes an attributes parameter leads one to think the passed params are the criteria for the selection. At first glance it would appear it would be used like this:

User.first_or_create(email: 'derek@somwhere.com')

Where in reality this would grab the “first” record (say w/ email “john@smith.com”), and change its email to “derek@somwhere.com”, a fairly surprising action that doesn’t obviously fail, leading to some pretty subtle bugs.

In reality it should be used like this:

User.where(email: 'derek@somwhere.com').first_or_create

And the attributes param. isn’t used in 99% of use cases. (If at all - the provision for the block that executes only on create fully duplicates what the attributes parameter can do in a much more obvious way.)

IMHO this is simply a bad API that one just needs to be aware of. But it’s unfair to knock dino for what’s likely a highly common misreading.

March 4, 2016 - (>= v4.0.2)
0 thanks

FALSE: Creates record by given attributes only if table is empty

I very much doubt that dino’s comment was ever correct, but it certainly isn’t correct now. The behavior liantics describes is correct.

February 14, 2016
0 thanks

Text values for enum

There is way to have text values for enum. It is useful to have localized select options and latin values in database. 1) User model: enum kind: { ‘текст’=>‘text’, ‘изображение’=>‘picture’, ‘звук’=>‘audio’, ‘видео’=>‘video’ } 2) Edit view: <%= select_tag ‘user[kind]’, options_for_select(User.kinds, @user.kind) %>

February 12, 2016 - (<= v4.2.1)
0 thanks

Generate Token

For generate a token, make this:

def generate_token
  self.token = SecureRandom.uuid
end

SecureRandom return a number random and the uuid make this number be unique. This a good idea for use in shopping cart, for example

February 3, 2016 - (v4.0.2 - v4.2.1)
0 thanks

Params of conditions

You can pass an proc for o callback with the conditions

before_action :initial_value, only: [:index, :show], unless: -> { @foo.nil? }

before_action :initial_value, only: [:index, :show], if: -> { @foo }
February 3, 2016 - (v4.0.2 - v4.2.1)
0 thanks

Params of conditions

You can pass an proc for o callback with the conditions

after_action :initial_value, only: [:index, :show], unless: -> { @foo.nil? }

after_action :initial_value, only: [:index, :show], if: -> { @foo }
January 28, 2016
0 thanks

the method to make 'day' disappear.

If you wanna show “year” and “month” only, you can use “order” to do it:

select_date(Date.current, order: [:year, :month])

That’s it.

January 22, 2016
3 thanks

Creates record by given attributes only if table is empty

This method first searches the table for ANY FIRST RECORD, not the one matching given attributes. If no record is found at all, it creates one using the specified attributes. This might be misunderstood in many cases.

January 6, 2016
0 thanks

What about Marshal remote code execution risks?

Good suggestion about using Marshal to avoid cycles, astgtciv, but what about the security risks of doing that?

See http://ruby-doc.org/core-2.2.2/Marshal.html where it states:

By design, ::load can deserialize almost any class loaded into the Ruby process. In many cases this can lead to remote code
execution if the Marshal data is loaded from an untrusted source.

As a result, ::load is not suitable as a general purpose serialization format and you should never unmarshal user supplied input or other
untrusted data.

If you need to deserialize untrusted data, use JSON or another serialization format that is only able to load simple,primitive’ types such
as String, Array, Hash, etc. Never allow user input to specify arbitrary types to deserialize into.
January 3, 2016
0 thanks

Setting HTTP_REFERER

If your integration test is checking for correct behavior of a redirect to the request referer, you can set the referring path in the headers hash with syntax like:

patch update_user_role_path, { user: {role: "vip"} }, { 'HTTP_REFERER' => user_url } 
assert_redirected_to user_url
December 2, 2015
0 thanks

Not quite opposite of new_record?

new_record? will not check if the record has been destroyed

December 2, 2015
1 thank

Not quite opposite of persisted?

persisted? will also check if the record has not been destroyed

November 23, 2015 - (v3.2.13)
0 thanks

Rails 3.2.19

As Jebin reported, we are not getting the value in array format when we set the hidden_field_tag with an Array variable, instead it is a String that we are getting.

November 10, 2015
0 thanks

instead of memoize

See this for deprecated github.com/rails/rails/commit/36253916b0b788d6ded56669d37c96ed05c92c5c

use

def something
  return @_var if defined? @_var
  # more code
end
November 3, 2015 - (v4.2.1)
0 thanks

Possible bug

Works as expected for non bang methods

>  a={x:1, y:2, z:3}                                                                      
=> {:x=>1, :y=>2, :z=>3}

> a.slice(:y)                                                                             
=> {:y=>2}

> a.except(:y)                                                                            
=> {:x=>1, :z=>3}

Bug on slice! it behaves like except!

> a.clone.slice!(:y)                                                                                                                                                                                
=> {:x=>1, :z=>3}

> a.clone.except!(:y)                                                                                                                                                                               
=> {:x=>1, :z=>3}

slice! should return {:y=>2} and modify a to no longer have it

October 19, 2015
0 thanks

Multiple files

To use multiple file upload need to use variable_name[].

like this:

file_field_tag 'files[]', :multiple => true  

and in controller:

if !params[ :files ].nil?
  params[ :files ].each{ |file|
     # do your staff
  }
end
October 13, 2015 - (>= v4.1.8)
0 thanks

"Class methods on your model are automatically available on scopes."

The final example above – “Class methods on your model are automatically available on scopes.” – contains a subtle but vital change from earlier versions of the doc – namely, “pluck” (current example) vs “map” (old example). The former works, the latter does not. See http://github.com/rails/rails/issues/21943 for confirmation that the old documentation is incorrect, and for a workaround.

(Spoiler alert: Use

all.map(&:title)

instead of just

map(&:title)

in order to achieve the same effect.)

October 13, 2015 - (>= v4.1.8)
0 thanks

"Class methods on your model are automatically available on scopes."

The final example above – “Class methods on your model are automatically available on scopes.” – does not work as written. See http://github.com/rails/rails/issues/21943 for confirmation that the old documentation is incorrect, and for a workaround.

(Spoiler alert: Use

all.map(&:title)

instead of just

map(&:title)

in order to achieve the same effect.)