Rails 3 - Determine if a HASH contains a record - ruby-on-rails

For a user I have the following as an example:
[#<Permission id: 1, project_id: 3, role_id: 1, user_id: 1>, #<Permission id: 43, project_id: 2, role_id: 1, user_id: 1>, #<Permission id: 44, project_id: 4, role_id: 1, user_id: 1>, #<Permission id: 45, project_id: 5, role_id: 2, user_id: 1>, #<Permission id: 46, project_id: 6, role_id: 3, user_id: 1>, #<Permission id: 47, project_id: 7, role_id: 1, user_id: 1>]
I'm able to do this:
<% if results.permissions.empty? %>
Which tells me if the results.permissions has 1 or more records.
But what I'd like to do is something like this:
<% if results.permissions.where(spaceid = 3).empty? %>
What I'm trying to do is take a project_id variable and filter that with the results.permission object.
Suggestions?
Thanks!

If you are using a :has_many association you should be able to do the following:
results.permissions.find_by_project_id(3)
or if you want to get all the records with that id, you could use:
results.permissions.find_all_by_project_id(3)

Related

Trying to deleting from Active Record collection ONLY using delete_if

I want to remove elements from an Active Record collection, for this I'm trying to use delete_if. Below is my collection:
categories = Category.all
groups = Group.all
result = []
groups.each do |g|
result.push({ :name => g[:name], :amount => g[amount_column], :drilldown => [] })
categories.where( { :group_id => g.id } ).each do |c, index|
result.last[:drilldown].push({ :name => c[:name], :amount => c[amount_column], :drilldown => nil })
end
# lastly, remove these categories from this collection (not working)
categories.delete_if {|c| c.group_id == g.id }
# tried this too - categories.select! { |c| c.group_id != g.id }
end
abort(categories.size.inspect)
..I want to do something with the categories of each group, then remove them form the array. After the loop block I'll want to be left with the categories which do not belong to a group - that is why I delete those of each group there. Here is the data for groups and categories when they are first fetched (sorry it's a lot but just to note that some category.group_id and group.id match:
#categories
#<ActiveRecord::Associations::CollectionProxy [#<Category id: 13, name: "Internet", user_id: 1, created_at: "2014-03-09 13:15:19", updated_at: "2014-03-15 05:13:47", amount: #<BigDecimal:7f0c283806e0,'0.0',9(18)>, group_id: nil, amount_in: #<BigDecimal:7f0c28380578,'0.0',9(18)>, amount_out: #<BigDecimal:7f0c283804b0,'0.0',9(18)>>, #<Category id: 15, name: "Electricity", user_id: 1, created_at: "2014-03-09 13:15:39", updated_at: "2014-03-15 05:14:03", amount: #<BigDecimal:7f0c2838f5a0,'0.0',9(18)>, group_id: nil, amount_in: #<BigDecimal:7f0c2838f460,'0.0',9(18)>, amount_out: #<BigDecimal:7f0c2838f2f8,'0.0',9(18)>>, #<Category id: 6, name: "Phone", user_id: 1, created_at: "2014-02-18 10:07:47", updated_at: "2014-03-15 05:16:21", amount: #<BigDecimal:7f0c2838e470,'0.0',9(18)>, group_id: nil, amount_in: #<BigDecimal:7f0c2838e308,'0.0',9(18)>, amount_out: #<BigDecimal:7f0c2838e240,'0.0',9(18)>>, #<Category id: 9, name: "Trains", user_id: 1, created_at: "2014-02-22 03:08:08", updated_at: "2014-03-15 05:16:21", amount: #<BigDecimal:7f0c2838d340,'-0.5E3',9(18)>, group_id: nil, amount_in: #<BigDecimal:7f0c2838d138,'0.0',9(18)>, amount_out: #<BigDecimal:7f0c2838cf08,'-0.5E3',9(18)>>, #<Category id: 5, name: "Resaurants", user_id: 1, created_at: "2014-02-17 12:12:44", updated_at: "2014-03-15 05:16:21", amount: #<BigDecimal:7f0c2839be18,'-0.235E3',9(18)>, group_id: 16, amount_in: #<BigDecimal:7f0c2839bc38,'0.0',9(18)>, amount_out: #<BigDecimal:7f0c2839baa8,'-0.235E3',9(18)>>, #<Category id: 14, name: "Gas", user_id: 1, created_at: "2014-03-09 13:15:27", updated_at: "2014-03-15 05:16:21", amount: #<BigDecimal:7f0c2839a680,'0.0',9(18)>, group_id: 16, amount_in: #<BigDecimal:7f0c2839a3d8,'0.0',9(18)>, amount_out: #<BigDecimal:7f0c2839a1d0,'0.0',9(18)>>, #<Category id: 3, name: "Snowboarding", user_id: 1, created_at: "2014-02-11 09:43:52", updated_at: "2014-03-15 05:16:21", amount: #<BigDecimal:7f0c28398d30,'-0.1111E4',9(18)>, group_id: 16, amount_in: #<BigDecimal:7f0c28398b28,'0.0',9(18)>, amount_out: #<BigDecimal:7f0c28398a38,'-0.1111E4',9(18)>>]>
# groups
#<ActiveRecord::Associations::CollectionProxy [#<Group id: 16, name: "Testing", user_id: 1, amount: #<BigDecimal:31c0ce8,'-0.1346E4',9(18)>, created_at: "2014-03-09 13:48:50", updated_at: "2014-03-15 05:35:57", amount_in: #<BigDecimal:31d3118,'0.0',9(18)>, amount_out: #<BigDecimal:26b9728,'-0.1346E4',9(18)>>, #<Group id: 17, name: "test", user_id: 1, amount: #<BigDecimal:31d2a88,'0.0',9(18)>, created_at: "2014-03-15 05:38:36", updated_at: "2014-03-15 05:39:00", amount_in: #<BigDecimal:31d14f8,'0.0',9(18)>, amount_out: #<BigDecimal:2e4e650,'0.0',9(18)>>]>
.. but my delete_if does nothing (abort shows the same size with or without the delete_if). Please note that there are group.id = 16, and category.group_id = 16 so the delete_if should delete those ones - but it doesn't. Is there anything that I'm doing wrong?
Try this ,I think it will help
categories.delete_if {|x| x.group_id==16}
This will update categories in place, selecting all categories with group_id not equal to g.id.
categories.select! { |c| c.group_id != g.id }

How to get an array of attributes hashes from an array of records?

I want to print all questions and status fields.
How can I extract the required data in an array ?
This is my array : #category_questions
[#<Question id: 38, user_id: 1, question: "hi", question_status: 1, created_at: "2013-06-04 18:32:28", updated_at: "2013-06-04 18:32:28">, #<Question id: 40, user_id: 1, question: "urll", question_status: 1, created_at: "2013-06-04 18:34:57", updated_at: "2013-06-04 18:34:57">, #<Question id: 41, user_id: 1, question: "urll", question_status: 1, created_at: "2013-06-04 18:35:31", updated_at: "2013-06-04 18:35:31">]
I tried #category_questions[iteration_number][:some field] but it did not work.
To get an array of hashes:
#category_questions.map do |question|
{question: question.question, status: question.question_status}
end
To get an array of arrays:
#category_questions.map {|question| [question.question, question.question_status] }

Does postgres offset/limit not work the same way as mysql?

I have a rails app (postgres + postGIS) with a post model with a rating column (integer). If I go into the console and do:
Post.order("rating DESC").map(&:id)
=> [9, 15, 19, 6, 17, 5, 4, 16, 1, 3, 13, 20, 14, 10, 8, 12, 7, 2, 18, 11]
yet if I try to cycle through those one at a time with limit and offset, I get bizarre results.
Post.order("rating DESC").limit(1).offset(0)
=> [#<Post id: 5, body: "Hi", rating: 4, location: #<RGeo::Geographic::SphericalPointImpl:0x81bb34c0 "POINT (-118.495 34.017)">, user_id: 8, created_at: "2012-07-25 22:43:41", updated_at: "2012-07-25 22:43:41">]
Why is that post #5? It should be #9. Anyway then it gets even more wacko when I apply an offset.
>Post.order("rating DESC").limit(1).offset(1)
=> [#<Post id: 5, body: "Hi", rating: 4, location: #<RGeo::Geographic::SphericalPointImpl:0x81bb34c0 "POINT (-118.495 34.017)">, user_id: 8, created_at: "2012-07-25 22:43:41", updated_at: "2012-07-25 22:43:41">]
>Post.order("rating DESC").limit(1).offset(2)
=> [#<Post id: 5, body: "Hi", rating: 4, location: #<RGeo::Geographic::SphericalPointImpl:0x81bb34c0 "POINT (-118.495 34.017)">, user_id: 8, created_at: "2012-07-25 22:43:41", updated_at: "2012-07-25 22:43:41">]
>Post.order("rating DESC").limit(1).offset(3)
=> [#<Post id: 5, body: "Hi", rating: 4, location: #<RGeo::Geographic::SphericalPointImpl:0x81bb34c0 "POINT (-118.495 34.017)">, user_id: 8, created_at: "2012-07-25 22:43:41", updated_at: "2012-07-25 22:43:41">]
>Post.order("rating DESC").limit(1).offset(4)
=> [#<Post id: 15, body: "I luv coffee", rating: 4, flagged: 0, location: #<RGeo::Geographic::SphericalPointImpl:0x82260df4 "POINT (-118.495 34.017)">, user_id: 1, created_at: "2012-07-25 22:43:41", updated_at: "2012-07-25 22:43:41">]
Do you notice that rating is 4 for the only results that you're showing? You're sorting on rating with no secondary sort key so there's no guarantee about what order ties will appear in or even that the ties will be ordered the same way in two different calls.
Try adding a tie breaker to your order:
Post.order('rating DESC, id')
and then include the rating in what you're looking at:
Post.order('rating desc, id').select('id, rating').map { |p| [ p.id, p.rating ] }
Post.order('rating desc, id').select('id, rating').limit(1).offset(3).map { |p| [ p.id, p.rating ] }
#...
That should give you sensible and consistent results.

Update all record matching some conditions but keeping "position-indexed" values in a database table column

I am using Ruby on Rails 3.0.7 and I have a position database table column in order to handle a sortable list of records. I would like to update that column for all records matching some conditions on destroying a record which position value is "in the middle of all position values", but keeping the order (numerically) in the position column.
That is, for example, if in the following list of class objects I destroy the record with position 3 and user_id 1
#<Article id: 1, position: 1, user_id: 1>,
#<Article id: 2, position: 1, user_id: 2>,
#<Article id: 3, position: 2, user_id: 1>,
#<Article id: 4, position: 3, user_id: 1>,
#<Article id: 5, position: 1, user_id: 3>,
#<Article id: 6, position: 4, user_id: 1>,
#<Article id: 7, position: 5, user_id: 1>,
#<...> # A lot of others records having 'user_id' = 1
I would like to update all other records related to user_id 1 so to have
#<Article id: 1, position: 1, user_id: 1>,
#<Article id: 2, position: 1, user_id: 2>,
#<Article id: 3, position: 2, user_id: 1>,
#<Article id: 5, position: 1, user_id: 3>,
#<Article id: 6, position: 3, user_id: 1>,
#<Article id: 7, position: 4, user_id: 1>,
#<...> # A lot of others records having 'user_id' = 1
Of course, all that being careful to performance.
How can I do that (maybe in a single clause\statement)?
I know that the update_all method can help someway, but I don't know how to auto-increment position values using that.
I guess what you are looking for in SQL is this?
update articles set position = position - 1
where position > pos_of_deleted and user_id = uid_of_deleted
With update_all it should convert to something like this:
Article.update_all("position = position - 1",
["position > ? and user_id = ?",
pos_of_deleted, uid_of_deleted])
That will pull all positions above the deleted position down one notch..

ActiveRecord conditional query with Dates not working

irb(main):104:0> s = Status.all
=> [#<Status id: 1, card_id: 1, user_id: 1, next: "2001-01-01 00:00:00", level: 1, created_at: nil, updated_at: nil>, #<Status id: 2, card_id: 2, user_id: 1, next: "2001-01-01 00:00:00", level: 1, created_at: nil, updated_at: nil>, #<Status id: 3, card_id: 3, user_id: 1, next: "2011-01-01 00:00:00", level: 1, created_at: nil, updated_at: nil>]
irb(main):105:0> s[2].next < Time.now
=> false
irb(main):106:0> s[1].next < Time.now
=> true
irb(main):107:0> Status.where("next < ?", Time.now)
=> [#<Status id: 1, card_id: 1, user_id: 1, next: "2001-01-01 00:00:00", level: 1, created_at: nil, updated_at: nil>, #<Status id: 2, card_id: 2, user_id: 1, next: "2001-01-01 00:00:00", level: 1, created_at: nil, updated_at: nil>, #<Status id: 3, card_id: 3, user_id: 1, next: "2011-01-01 00:00:00", level: 1, created_at: nil, updated_at: nil>]
I would expect the Status.where statement to only return 2 objects. It seems like the less than condition in the where clause is not working. If I switch it to an greater than, the query returns [].
next is set up as a datetime in the migration
Why is this conditional where query not working?
Thanks
You're right that this should work, assuming the database server has the correct time. What kind of database are you querying? Please update your question with that and the query generated by the .where() method.
At first you should try to force DB formating in your query : Time.now.to_s(:db)
If it doesn't work, using a time zone could be a good idea.
Time.zone.now.to_s(:db)

Resources