Rails where not behaving as expected - ruby-on-rails

I'm trying to retrieve a set of items using where in rails. If I retrieve all I see:
2.2.2 :027 > JourneyLeg.all
JourneyLeg Load (0.2ms) SELECT "journey_legs".* FROM "journey_legs"
=> #<ActiveRecord::Relation [
#<JourneyLeg id: 1, start_station: 24, end_station: 25, departure_time: "2000-01-01 06:37:00", arrival_time: "2000-01-01 06:45:00", journey: 6, created_at: "2015-07-25 11:32:42", updated_at: "2015-07-25 11:32:42">,
#<JourneyLeg id: 2, start_station: 25, end_station: 26, departure_time: "2000-01-01 06:46:00", arrival_time: "2000-01-01 06:50:00", journey: 6, created_at: "2015-07-25 11:32:42", updated_at: "2015-07-25 11:32:42">]>
And now I want to only return items where start_station is 24, so I use JourneyLeg.where(:start_station => 24)
2.2.2 :028 > JourneyLeg.where(:start_station => 24)
JourneyLeg Load (0.1ms) SELECT "journey_legs".* FROM "journey_legs" WHERE "journey_legs"."id" = ? [["start_station", 24]]
=> #<ActiveRecord::Relation []>
But for some reason this is querying id and not start_station (and hence not finding anything) but I have no idea why.
Update 1
Thanks to the comment from David, I spotted that the issue is caused by the fact I have an attribute on the model called start_station which is an integer but also a has_one relationship called start_station
has_one :start_station, :class_name => "Station", :primary_key => "start_station", :foreign_key => "id"
If I remove this relationship or rename it, then the following works as expected with the various suggestions:
JourneyLeg.where(:start_station => 24)
JourneyLeg.where(start_station: 24)

Try this
JourneyLeg.where("start_station = '24'")

This should work based on Documentation of where
JourneyLeg.where({:start_station => 24})
I have tried this with my local application's model called Article, following variant of where works (Rails 4.2.2, Ruby 2.0.0p247)
Variant 1
irb(main):006:0> Article.where({id: 2})
Article Load (1.0ms) SELECT "articles".* FROM "articles" WHERE "articles"."id" = ? [["id", 2]]
=> #<ActiveRecord::Relation [#<Article id: 2, title: "World", text: nil, created_at: "2015-07-25 21:09:16", updated_at: "2015-07-25 21:09:16">]>
Variant 2
irb(main):009:0> Article.where({:id => 2})
Article Load (0.0ms) SELECT "articles".* FROM "articles" WHERE "articles"."id" = ? [["id", 2]]
=> #<ActiveRecord::Relation [#<Article id: 2, title: "World", text: nil, created_at: "2015-07-25 21:09:16", updated_at: "2015-07-25 21:09:16">]>
Variant 3
irb(main):010:0> Article.where(id: 2)
Article Load (0.0ms) SELECT "articles".* FROM "articles" WHERE "articles"."id" = ? [["id", 2]]
=> #<ActiveRecord::Relation [#<Article id: 2, title: "World", text: nil, created_at: "2015-07-25 21:09:16", updated_at: "2015-07-25 21:09:16">]>

Related

ActiveRecord 'where' query not working for certain string columns in postgresql

I'm new to activerecord and postgresql and I have the following issue with regards to a activerecord query. Please help me understand why this is happening and how I can resolve it.
I have multiple text columns which is declared in a standard way in my schema file.
create_table "time_entries", force: :cascade do |t|
t.string "user"
t.string "email"
etc ....
end
I'm trying to find records with 'user' = 'Test'.
TimeEntry.where(user: "Test")
works fine, however
TimeEntry.where("user = 'Test'")
does not work.
I can see that the two query yields different sql queries but I'm trying to understand why this works for the 'email' field but not for the 'user' field.
User Field Query:
irb(main):011:0> TimeEntry.where(user: "Test")
TimeEntry Load (0.5ms) SELECT "time_entries".* FROM "time_entries" WHERE "time_entries"."user" = $1 [["user", "Test"]]
=> #<ActiveRecord::Relation [#<TimeEntry id: 1, user: "Test", email: "test#testemail.com", task: nil, description: "TEST CRM", billable: "No", start_date: "2016-01-03", start_time: "2000-01-01 14:20:22", end_date: "2016-01-03", end_time: "2000-01-01 14:26:29", duration: "2000-01-01 00:06:07", tags: nil, amount: 111, created_at: "2017-01-03 15:39:51", updated_at: "2017-01-03 15:39:51", project_id: 1, resource_id: nil>]>
irb(main):012:0> TimeEntry.where("user = 'Test'")
TimeEntry Load (0.4ms) SELECT "time_entries".* FROM "time_entries" WHERE (user = 'Test')
=> #<ActiveRecord::Relation []>
irb(main):013:0>
Email Field Query:
irb(main):013:0> TimeEntry.where(email: "test#testemail.com")
TimeEntry Load (0.3ms) SELECT "time_entries".* FROM "time_entries" WHERE "time_entries"."email" = $1 [["email", "test#testemail.com"]]
=> #<ActiveRecord::Relation [#<TimeEntry id: 1, user: "Test", email: "test#testemail.com", task: nil, description: "TEST CRM", billable: "No", start_date: "2016-01-03", start_time: "2000-01-01 14:20:22", end_date: "2016-01-03", end_time: "2000-01-01 14:26:29", duration: "2000-01-01 00:06:07", tags: nil, amount: 111, created_at: "2017-01-03 15:39:51", updated_at: "2017-01-03 15:39:51", project_id: 1, resource_id: nil>]>
irb(main):014:0> TimeEntry.where("email = 'test#testemail.com'")
TimeEntry Load (0.4ms) SELECT "time_entries".* FROM "time_entries" WHERE (email = 'test#testemail.com')
=> #<ActiveRecord::Relation [#<TimeEntry id: 1, user: "Test", email: "test#testemail.com", task: nil, description: "TEST CRM", billable: "No", start_date: "2016-01-03", start_time: "2000-01-01 14:20:22", end_date: "2016-01-03", end_time: "2000-01-01 14:26:29", duration: "2000-01-01 00:06:07", tags: nil, amount: 111, created_at: "2017-01-03 15:39:51", updated_at: "2017-01-03 15:39:51", project_id: 1, resource_id: nil>]>
Thanks for your help.
Ok, seems this issue occurs due to 'user' being a reserved keyword in postgres.
The following code works fine:
TimeEntry.where('time_entries.user = ?', 'Test')
or
TimeEntry.where('"user" = ?','Test')

Method find_by_user_id_and_friend_id does not seem to work - Rails 5

i am unsure why the method
Friendship.find_by_user_id_and_friend_id(user, friend) &
Friendship.find_by_user_id_and_friend_id(friend, user) gives a nil,
could one kindly explain this to me
why does the method Friendship.find_by_user_id_and_friend_id(user,
friend) give a nil and the method
Friendship.find_by_user_id_and_friend_id(user.id, friend.id) does
not? basically could one explain the difference to me
2.3.0 :065 > user
=> #<User id: 1, email: "richill#gmail.com", created_at: "2016-11-22 15:56:19", updated_at: "2016-12-06 11:39:29", firstname: "richill", lastname: "artloe">
2.3.0 :068 > friend
=> #<User id: 2, email: "emma#gmail.com", created_at: "2016-11-22 16:19:25", updated_at: "2016-11-22 16:19:25", firstname: "emma", lastname: "watson">
Friendship.create(user: user, friend: friend, status: 'pending')
Friendship.create(user: friend, friend: user, status: 'requested')
2.3.0 :078 > Friendship.find_by_user_id_and_friend_id(user, friend)
Friendship Load (0.2ms) SELECT "friendships".* FROM "friendships" WHERE "friendships"."user_id" = ? AND "friendships"."friend_id" = ? LIMIT ? [["user_id", nil], ["friend_id", nil], ["LIMIT", 1]]
=> nil
2.3.0 :079 >
2.3.0 :079 > Friendship.find_by_user_id_and_friend_id(friend, user)
Friendship Load (0.2ms) SELECT "friendships".* FROM "friendships" WHERE "friendships"."user_id" = ? AND "friendships"."friend_id" = ? LIMIT ? [["user_id", nil], ["friend_id", nil], ["LIMIT", 1]]
=> nil
2.3.0 :080 >
i believe i am suppose to get something like the below results:
>> Friendship.find_by_user_id_and_friend_id(user, friend)
=> #<Friendship:0x2bf74ec #attributes={"status"=>"pending", "accepted_at"=>nil,
"id"=>"1", "user_id"=>"1", "position"=>nil, "created_at"=>"2007-01-03 18:34:09",
"friend_id"=>"1198"}>
>> Friendship.find_by_user_id_and_friend_id(friend, user)
=> #<Friendship:0x490a7a0 #attributes={"status"=>"requested", "accepted_at"=>nil
, "id"=>"2", "user_id"=>"1198", "position"=>nil, "created_at"=>"2007-01-03 18:34
:20", "friend_id"=>"1"}>
very strange. it works when placed like this
Friendship.find_by_user_id_and_friend_id(user.id, friend.id)
=> #<Friendship id: 1, user_id: 1, friend_id: 2, status: "pending", created_at: "2016-12-06 11:55:06", updated_at: "2016-12-06 11:55:06">
but does not work when placed like this:
Friendship.find_by_user_id_and_friend_id(user, friend)
=> nil
could one explain why this is to me
what is the difference
2.3.0 :016 > Friendship.find_by_user_id_and_friend_id(user, friend)
Friendship Load (0.2ms) SELECT "friendships".* FROM "friendships" WHERE "friendships"."user_id" = ? AND "friendships"."friend_id" = ? LIMIT ? [["user_id", nil], ["friend_id", nil], ["LIMIT", 1]]
=> nil
2.3.0 :017 > Friendship.find_by_user_id_and_friend_id(user.id, friend.id)
Friendship Load (0.2ms) SELECT "friendships".* FROM "friendships" WHERE "friendships"."user_id" = ? AND "friendships"."friend_id" = ? LIMIT ? [["user_id", 1], ["friend_id", 2], ["LIMIT", 1]]
=> #<Friendship id: 1, user_id: 1, friend_id: 2, status: "pending", created_at: "2016-12-06 11:55:06", updated_at: "2016-12-06 11:55:06">
2.3.0 :018 >
the find_by_id method is the same as using the where method except it only returns the first record that is found. (See the source code)
Since the method is searching for id's I believe you need to pass the id directly rather than the instance of your object for it to work. This is the same when you use the .find method.

Rails 4 ActiveRecords: Save multiple records at once with validation

Hi i have the following situation. I can save this array of hashes
products = [{
:name=> 0,
:key => 12345,
:label => "test1",
},{
:name=> 0,
:key => 12145,
:label => "test",
}]
at once with
products.map {|p| Product.new(p).save }
or
Product.create(products)
Product.create!(products)
but the all my uniqueness validations like
validates :key, presence: true, uniqueness: true
are ignored, using the rails console. I am able to save this hash multiple times. Does anyone has some advice? Thanks in advance!
SOLUTION
As simple as restarting my rails console. After that my logs look like the logs from #Akadisoft.
Also using this way:
products.map {|p| Product.new(p).save }
which return an array with booleans [false,true] either the record was saved or not, which is nice for further evaluation.
I have tried your exact solution and everything works as intented..
The first time I ran the command Product.create(products) I have the following result
=> #<ActiveRecord::Relation [#<Product id: 1, key: "12345", name: 0, label: "test1", created_at: "2015-12-09 19:21:01", updated_at: "2015-12-09 19:21:01">, #<Product id: 2, key: "12145", name: 0, label: "test", created_at: "2015-12-09 19:21:01", updated_at: "2015-12-09 19:21:01">]>
We can see that it created two products (id:1 and id:2).
Now the second I run the exact same command here is the result:
[#<Product id: nil, key: "12345", name: 0, label: "test1", created_at: nil, updated_at: nil>, #<Product id: nil, key: "12145", name: 0, label: "test", created_at: nil, updated_at: nil>]
irb(main):015:0>
We can see the ID is nil because it didn't save the products. I can also see in the console output that DB transaction were rollbacked.
I tried this on console and it only added one record.
14:42 $ rails c
Loading development environment (Rails 4.2.5)
2.2.2 :001 > products = [{:key =>1},{:key=>1}]
=> [{:key=>1}, {:key=>1}]
2.2.2 :002 > products.map {|p| Product.new(p).save }
(0.1ms) begin transaction
Product Exists (0.1ms) SELECT 1 AS one FROM "products" WHERE "products"."key" = 1 LIMIT 1
SQL (0.8ms) INSERT INTO "products" ("key", "created_at", "updated_at") VALUES (?, ?, ?) [["key", 1], ["created_at", "2015-12-09 19:42:32.488255"], ["updated_at", "2015-12-09 19:42:32.488255"]]
(0.4ms) commit transaction
(0.0ms) begin transaction
Product Exists (0.1ms) SELECT 1 AS one FROM "products" WHERE "products"."key" = 1 LIMIT 1
(0.0ms) rollback transaction
=> [true, false]
2.2.2 :003 > Product.all
Product Load (0.2ms) SELECT "products".* FROM "products"
=> #<ActiveRecord::Relation [#<Product id: 1, key: 1, created_at: "2015-12-09 19:42:32", updated_at: "2015-12-09 19:42:32">]>

Updating Rails 4 Nested Attributes

I'm having a hard time with Rails and nested attributes and would really appreciate some help.
Here is the output from my console session where I was attempting to get the updated values to save but as you can see, they don't seem to take on the next line when I perform the find again:
irb(main):070:0* e = Equipment.find(26)
Equipment Load (0.5ms) SELECT "equipment".* FROM "equipment" WHERE "equipment"."id" = $1 LIMIT 1 [["id", 26]]
=> #<Equipment id: 26, name: "fdsfsdsdfsd2", created_at: "2015-11-02 15:26:43", updated_at: "2015-11-02 16:38:55", site_id: 57, type_id: 3>
irb(main):071:0> e.update({"name"=>"fdsfsdsdfsd2", "site_id"=>"57", "type_id"=>"3", "equipment_properties_attributes"=>{"0"=>{"id"=>"15", "value"=>"2015-10-34", "property_id"=>"4"}, "1"=>{"id"=>"16", "value"=>"fsdfdsfsd", "property_id"=>"5"}}})
(0.6ms) BEGIN
EquipmentProperty Load (0.7ms) SELECT "equipment_properties".* FROM "equipment_properties" WHERE "equipment_properties"."equipment_id" = $1 AND "equipment_properties"."id" IN (15, 16) [["equipment_id", 26]]
(0.2ms) COMMIT
=> true
irb(main):072:0> e.equipment_properties
EquipmentProperty Load (0.5ms) SELECT "equipment_properties".* FROM "equipment_properties" WHERE "equipment_properties"."equipment_id" = $1 [["equipment_id", 26]]
=> #<ActiveRecord::Associations::CollectionProxy [#<EquipmentProperty id: 15, equipment_id: 26, property_id: 4, value: "2015-10-34", created_at: "2015-11-02 15:26:51", updated_at: "2015-11-02 15:26:51">, #<EquipmentProperty id: 16, equipment_id: 26, property_id: 5, value: "fsdfdsfsd", created_at: "2015-11-02 15:26:51", updated_at: "2015-11-02 15:26:51">]>
irb(main):073:0> e = Equipment.find(26)
Equipment Load (0.5ms) SELECT "equipment".* FROM "equipment" WHERE "equipment"."id" = $1 LIMIT 1 [["id", 26]]
=> #<Equipment id: 26, name: "fdsfsdsdfsd2", created_at: "2015-11-02 15:26:43", updated_at: "2015-11-02 16:38:55", site_id: 57, type_id: 3>
irb(main):074:0> e.equipment_properties
EquipmentProperty Load (0.6ms) SELECT "equipment_properties".* FROM "equipment_properties" WHERE "equipment_properties"."equipment_id" = $1 [["equipment_id", 26]]
=> #<ActiveRecord::Associations::CollectionProxy [#<EquipmentProperty id: 15, equipment_id: 26, property_id: 4, value: "2015-10-30", created_at: "2015-11-02 15:26:51", updated_at: "2015-11-02 15:26:51">, #<EquipmentProperty id: 16, equipment_id: 26, property_id: 5, value: "fsdfdsfsd", created_at: "2015-11-02 15:26:51", updated_at: "2015-11-02 15:26:51">]>
The same thing is happening with the web interface. I can provide additional details if anyone needs them but I am allowing the parameters through and on creation, the initial values are saved.
I've been beating my head against this all morning and I suspect it is something stupid but I'm just not sure what to try next. Thanks!
UPDATE 1:
Equipment Model:
class Equipment < ActiveRecord::Base
belongs_to :site
belongs_to :type
has_and_belongs_to_many :properties
has_many :equipment_properties
accepts_nested_attributes_for :equipment_properties, reject_if: :all_blank, allow_destroy: true
end
And also the equipment_properties model:
class EquipmentProperty < ActiveRecord::Base
belongs_to :equipment
belongs_to :property
has_one :type, through: :equipment
end
Also, of relevance might be that I can update the individual equipment_property without nesting and that does work.
UPDATE 2:
I managed to add this to the controller and it saves the values now. Not pretty but it works I guess...
equipment_params[:equipment_properties_attributes].each do |property|
ep = EquipmentProperty.where(id: property[1][:id]).first
#logger.debug "EP Value: #{ep.value}"
#logger.debug "Property Value: #{property[1][:value]}"
ep.value = property[1][:value]
ep.save
end
This is what I ended up adding to the controller to resolve this. Definitely a hack though and I'm not sure why the updates are taking:
equipment_params[:equipment_properties_attributes].each do |property|
ep = EquipmentProperty.where(id: property[1][:id]).first
#logger.debug "EP Value: #{ep.value}"
#logger.debug "Property Value: #{property[1][:value]}"
ep.value = property[1][:value]
ep.save
end

Time not updating in heroku

I'm seriously confused what could be going wrong.
I'm logged into heroku run console and trying to update a timestamp on my database.
I've run User.find(6) to see that the user has a :next_click = 2000-01-01... i don't know why it's that value, but anyway, I do User.update 6, {:next_click => Time.utc(2015)} and it seems to update properly saying 2015-01-01 00:00:00, however when I do another User.find(6) it seems the time has switched back because it's not 2015-01-01 00:00:00.
I'm really confused why it's not. Any insight?
SEE ATTACHED SCREENSHOT
irb(main):033:0> User.update 6, {:next_click => Time.utc(2015) }
User Load (34.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 6]]
(1.8ms) BEGIN
(2.2ms) UPDATE "users" SET "next_click" = '2015-01-01 00:00:00.000000', "updated_at" = '2012-05-24 00:13:26.197358' WHERE "users"."id" = 6
(2.2ms) COMMIT
=> #<User id: 6, name: "mazlix", gold: 10, points: 10, next_click: "2015-01-01 00:00:00", created_at: "2012-05-23 23:40:39", updated_at: "2012-05-24 00:13:26">
irb(main):034:0> User.find(6)
User Load (2.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 6]]
=> #<User id: 6, name: "mazlix", gold: 10, points: 10, next_click: "2000-01-01 00:00:00", created_at: "2012-05-23 23:40:39", updated_at: "2012-05-24 00:13:26">
The same thing happens with u = User.find(6) u.next_click = Time.utc(2013) then u.save
irb(main):001:0> u = User.find(6)
User Load (38.8ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 6]]
=> #<User id: 6, name: "mazlix", gold: 10, points: 10, next_click: "2000-01-01 00:00:00", created_at: "2012-05-23 23:40:39", updated_at: "2012-05-24 00:57:28">
irb(main):002:0> u.next_click = Time.utc(2013)
=> 2013-01-01 00:00:00 UTC
irb(main):003:0> u
=> #<User id: 6, name: "mazlix", gold: 10, points: 10, next_click: "2013-01-01 00:00:00", created_at: "2012-05-23 23:40:39", updated_at: "2012-05-24 00:57:28">
irb(main):004:0> u.save
(10.9ms) BEGIN
(3.7ms) UPDATE "users" SET "next_click" = '2013-01-01 00:00:00.000000', "updated_at" = '2012-05-24 03:05:46.059530' WHERE "users"."id" = 6
(2.2ms) COMMIT
=> true
irb(main):005:0> u
=> #<User id: 6, name: "mazlix", gold: 10, points: 10, next_click: "2013-01-01 00:00:00", created_at: "2012-05-23 23:40:39", updated_at: "2012-05-24 03:05:46">
irb(main):006:0> User.find(6)
User Load (33.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 6]]
=> #<User id: 6, name: "mazlix", gold: 10, points: 10, next_click: "2000-01-01 00:00:00", created_at: "2012-05-23 23:40:39", updated_at: "2012-05-24 03:05:46">
app/models/user.rb:
class User < ActiveRecord::Base
attr_accessible :gold, :name, :next_click, :points
end
You've created a time column. Slightly confusingly, even though in ruby Time stores time + date, in the database world the concept of a pure time of day (ie just hours/minutes/seconds) exists and that's what you get when you add a column of type :time to your migration.
Ruby itself doesn't have a class that represents a time without a date so rails uses an instance of Time but ignores the date bit.
If you want a column that stores both time and date, change the column to a :datetime one (you'll still get a Time instance back in most cases.
In your ActiveRecord can use the data type :timestamp or :datetime to store the correct date format.

Resources