guyzmo

Activity Graph

Page 1 of 1

2019-03-22

[11:20:06] guyzmo: hi 👋 I got a weird bug with ActiveRecord sum. I got `class Foo; has_many :bars; end` and `class Bar; belongs_to :foo; end`. Bar has an integer attribute `Bar.total`. Within Foo, if I do `foo.bars.count` I got 4 elements, and each has a `total` value of 20. If I do `Foo.bars.map(&:total).sum` I get 80. If I do `Foo.bars.sum(:total)` I get 20, but I'd expect both to valuate to 80. Am I misunderstanding
[11:20:08] guyzmo: something on how `.sum` works?
[11:21:46] guyzmo: no, I did not
[11:22:49] guyzmo: I even tried giving an SQL string as parameter to sum(): `Foo.bars.sum('foos.total')` and it still gives me 20
[11:23:13] guyzmo: is there a way to inspect the sum method, like I could do a to_sql with an associationproxy?
[11:25:19] guyzmo: well, if I do that, that would be close to be talking about foos and bars, because I'd be removing a lot of unnecessary code to focus on the issue
[11:26:04] guyzmo: but definitely I do believe this is PEBCAK, my fault… I'm just struggling to find out what I did wrong
[11:27:50] guyzmo: ah! Just read some SO answer : /And it will call sum in the SQL database, so the result gets influenced by the parameters of the query, e.g. groups, joins, etc./
[11:28:27] guyzmo: indeed, I left that bars is not a straight path to Bar, I the query is a SELECT DISTINCT + joins
[11:28:48] guyzmo: (it's a has_many with condition)
[11:30:29] guyzmo: ok, looks like it's that
[11:30:59] guyzmo: if I do Foo.where(id: Foo.bars.ids).sum(:total) I get the correct sum
[11:32:33] guyzmo: so either I run a subselect or I do it in plain ruby
[11:33:38] guyzmo: (or I make the query more complex to correctly handle the aggregate)
[11:33:56] guyzmo: sevenseacat - thank you for reading me :)
[11:35:35] guyzmo: syndikate - that depends on how long you want your memoization to live
[11:35:47] guyzmo: syndikate - and what you want to use it for
[11:36:27] guyzmo: syndikate - if you want to memoize for the life span of the controller instance (up until the request is served, AFAICT), you can do it as an attribute
[11:37:46] guyzmo: if you want to memoize it for the life span of your whole process (given you have no threads and no multiprocess enabled), you can do it using a class member, but I would advise against that
[11:38:11] guyzmo: if you want to memoize it for a long time, just use Rails.cache
[11:38:47] guyzmo: you mean the set_book call?
[11:39:26] guyzmo: because BookController's methods are idempotent, meaning that they don't rely on state
[11:40:09] guyzmo: to give them state, you need to link them to the model, thus the @book = Book.find call you do at the start of a method
[11:40:32] guyzmo: then the model you want is contextualized to the query you give to the controller
[11:41:59] guyzmo: what you pasted is not memoizing
[11:42:04] guyzmo: it's just setting an attribute
[11:42:27] guyzmo: you could replace the before_action with a call to Book.find at the start of your method
[11:42:36] guyzmo: that's *exactly* the same thing
[11:43:19] guyzmo: the before_action is just some syntactic sugar to avoid repeating yourself at the start of every action method where you would translate params[:id] into a book
[11:44:10] guyzmo: @book will *always* be nil when you call http://yourhost/book/<id> before entering set_book
[11:44:36] guyzmo: each time you call a controller method, your BookController instance is a new one
[11:45:01] guyzmo: you just need to do @book = Book.find(params[:id])
[11:45:28] guyzmo: to translate the id query paramater into a book instance, so you can work on the model in your controller method
[11:46:05] guyzmo: if the code has been written by someone not stupid (which should be expected)
[11:46:12] guyzmo: maybe the ||= has been done on purpose
[11:46:37] guyzmo: and maybe there's another before_action that might set @book before the before_action you have which might instanciate @book before
[11:46:44] guyzmo: (maybe in a superclass)
[11:47:08] guyzmo: actually, this is one of the reasons I avoid the 'callbacks'
[11:47:20] guyzmo: because it's always a source of surprises
[11:48:01] guyzmo: I prefer to repeat myself, because I believe the rule of least expectation surpasses the DRY rule
[12:14:39] guyzmo: *.net *.split

2019-03-21

[08:00:31] guyzmo: ss942 - that's because when you do limit(5) the query takes only the needed time to take 5 elements out of the database, without looking further
[08:01:50] guyzmo: ss942 - when you add `order(...)` (same thing goes for `distinct`), the db needs to crawl through the whole table to compare all the values, to display them in order

2019-03-20

[09:54:54] guyzmo: hi! I have a many to many association: `class A -> class AB -> class B`, I wrote a method that given an `A` instance, I can build a new `AB` (there are several checks, and calculations I need to do at build time), then I save `A`, I save the `AB`s instances, but I need to reload all associations of `A` to get the new `AB`s and `B`s accessible… I there a way to reset all associations of an instance
[09:54:56] guyzmo: without listing them explicitely?
[09:55:29] guyzmo: or without rebuilding the instance (I could do `A.find(a.id)`)
[09:56:25] guyzmo: because in `A`, I got a lot of `has_many`, `has_many .. through` to get ABs, Bs, some with order, some with filters etc.
[09:57:07] guyzmo: (and I also got some `has_one`s that are dependent on the `has_many`s)
[09:58:22] guyzmo: I'm crawling through the RTFM, and I found `reset`, `reload` on each association, I can get all associations on the class using reflect methods, but I don't find how I can get all associations of an instance to call reset on it, or call some reset on the instance itself
[10:04:56] guyzmo: so to end with a question mark: is there a way to reset all the association caches of an instance?
[10:05:09] guyzmo: of an activerecord model instance*
[10:11:36] guyzmo: yup, that's what I'm trying to use
[10:15:53] guyzmo: something like : A.reflect_on_all_associations.map(&:name).each { |assoc| self.send(assoc)&.reset }
[10:18:13] guyzmo: though, I need to call reset_assoc on has_ones
[10:18:58] guyzmo: and I don't find a method on association that easily checks whether this is a has_many or a has_one
[10:20:57] guyzmo: (befond checking the association class)
[10:25:38] guyzmo: actually I need to reset the through as well :)
[10:27:06] guyzmo: hm… I thought I've read somewhere it was `reset_#{has_one_assoc}`… but that does not work
[10:30:53] guyzmo: ah there's only reload_
[16:03:24] guyzmo: @nakuku - I'd vote for authorization error, but what really matters is what feedback you give to your users

2019-03-07

[01:45:36] guyzmo: Ping timeout: 250 seconds
[01:47:04] guyzmo: has joined #RubyOnRails
[08:26:34] guyzmo: sagax - AFAICT, you can just name it SomeStatus, and it'll stay as is
[08:27:15] guyzmo: Otherwise the plural of `SomeStatus` is `SomeStatuses` 😉
[16:54:46] guyzmo: hi! I posted an issue about scope overriding, and I was wondering if it was worth doing a PR about that? https://github.com/rails/rails/issues/35499
[16:54:59] guyzmo: or if there's a 'better' way I'm not aware of

2019-03-06

[13:32:35] guyzmo: beingjohnm - I use rspec for my tests, I upgraded last week, and they worked the same after the update :)
[13:33:15] guyzmo: though the strong_params stuff has been a really pain for me :-/
[16:05:01] guyzmo: beingjohnm - I never tried the stock test framework, but rspec really does the job beautifully
[16:06:04] guyzmo: I guess it shouldn't be that hard to switch, it's basically behaviour driven, meaning you define your `describe`/`context` stuff and do `expect(<your predicates>)` within `it{}` blocks
[16:06:24] guyzmo: the whole idea being that using scopes, you create meaningful sentences
[16:09:13] guyzmo: I got a question about my switch to rails 5: I'm using STI with 3 classes, one mother class, and two children classes. They have a common scopes API, and I'm redefining some scopes in each child to match the differences
[16:09:48] guyzmo: but since I switched to rails 5, I get an annoying warning 'Creating scope :foobar. Overwriting existing method ChildA.foobar.'
[16:10:06] guyzmo: is there a way I could mark those scopes intended for being overriden as ok to be overriden ?

2019-03-01

[12:14:06] guyzmo: hello 👋
[12:15:37] guyzmo: I need to debug a crash happening in a gem, I tried adding a `binding.pry` within the gem, but it's totally ignored, so I'd like to set a breakpoint at start up of the rails session within pry
[12:16:18] guyzmo: is there a way to launch the rails server and go straight in the debugger just at the right moment before leaving it go in its "main loop"?
[12:16:33] guyzmo: a bit like you can do with gdb run in C
[12:16:53] guyzmo: so then I can set my breakpoints at start of the session
[12:17:56] guyzmo: I guess I might need to add the binding.pry at some place in the init, and add some env variable to control whether I want it started or not, but then my question would be where would be the best place to put that?
[12:18:41] guyzmo: would the init time be the right place? like config/initializers/development.rb? or somewhere in my main app code? or…?
[15:47:55] guyzmo: I finally went with `binding.pry if ENV['START_PRY'].present?` within `development.rb` and it's working

2019-02-13

[10:55:42] guyzmo: hi! I got a weird issue with path autoloading in rails. I wrote a lib (using trailblazer) that sits in `app/operations/foo/create.rb`, which includes a module `app/operations/foo/common.rb`. When I push to my staging env (running in RAILS_ENV dev mode), the `common` module does not get included (saying that an included symbol does not exist). If I ssh to the staging env, and I edit the
[10:55:44] guyzmo: `app/operations/foo/create.rb` file, save it without modifications, it then works
[10:56:44] guyzmo: in `config/application.rb` I have added: `config.paths.add "app/operations", glob: "**/*.rb" ; config.autoload_paths += ["#{config.root}/app/operations/*"]`
[10:57:50] guyzmo: Having to ssh and touch the file each time I push to the staging env is a pain… and I'm worrying that when I push in a production env it'll break without solution :-/
[10:58:36] guyzmo: I'm pretty sure I forgot something or did something stupid here… But I cannot tell what, anybody have any idea? 🙏
[11:03:06] guyzmo: indeed, I do create a Foo::Create class within it, that includes a Foo::Common module
[11:03:19] guyzmo: and the Foo::Common module sits in app/operations/foo/common.rb
[11:03:54] guyzmo: I even switched the include statement to `include ::Foo::Common` out of despair, but I guess it does not matter much
[11:04:43] guyzmo: I also have `app/operations/bar/common.rb` that defines `Bar::Common`, but I guess it should not conflict
[11:07:47] guyzmo: it does not reproduce in my local dev env (which is dockerized)
[11:08:01] guyzmo: only when I push to the staging env
[11:08:25] guyzmo: yup, my staging env is basically the same as my local env
[11:08:48] guyzmo: (except for the part where it's running on premises)
[11:11:21] guyzmo: it does not, the env is about the same
[11:12:51] guyzmo: yeah, that's why it's driving me insane /o\

2019-02-07

[00:29:42] guyzmo: istrasci - yes, you can use or, but beware that using `or` can be tricky
[18:45:57] guyzmo: hi, I got a complex schema, basically I got : Node from which inherits Leaf and CompositeLeaf, where composite contains a list of leaves. I have defined a bunch of scopes (which are similar, but are mostly different, basically used for filtering) on both Leaf and CompositeLeaf so I can list them in a UI. Now I want to use Node to list all Leaf and CompositeLeaf stuff. I have managed to use union (using
[18:45:59] guyzmo: active_record_union), where I can call a scope on Node, it calls the scope on both Leaf and LeafComposite. But now I'm struggling with chaining the scopes efficiently.
[18:48:45] guyzmo: (or at all)
[18:49:37] guyzmo: the way I'm handling the union for now is a mess of merge+union, and the merge is aliased as `nodes`, which when chained conflicts with further scopes
[18:53:50] guyzmo: so one way to handle this would be to make all the successive scope calls piled and applied respectively to each side of the union. i.e.: Node.scope1.scope2 would call Leaf.scope1.scope2 union LeafComposite.scope1.scope2
[18:55:41] guyzmo: another way would be for me to write all scopes on node as pure SQL, which will be highly unmaintainable and another way would be to avoid all joins by making all values needed for filtering local to the Node class, which would be prone to errors/issues and make migrations harder
[19:00:09] guyzmo: so my question would what directions would you people take in this situation?
[19:01:26] guyzmo: I'm getting to a point where I believe my options are to make complex hacks or complex hacks, but not getting the code simpler, so I feel something's wrong
[20:06:52] guyzmo: ok, I rode back home, and had a 'simpler' idea: within the method I have that builds a query by associating the scopes depending on parameters given through the API, I instead make a list of those, and then I inject them on the class. There I can either do a normal chain of scopes, or build the two chains, and make the union after

2019-02-06

[12:45:48] guyzmo: hi, got a quick question with AR queries: I got a has_many association like: `class A do has_many :foobars end` with a model foobar with an attribute x. I want to make a scope selecting all the As for which the first Foobar item has x
[12:45:58] guyzmo: set to nil
[12:46:29] guyzmo: how could I make such a scope/query with AR?
[12:53:34] guyzmo: hm I guess I could do with a .group(:id, 'foobars.x').having('foobars.x is null')
[12:57:03] guyzmo: nope, not even close :-/
[13:08:35] guyzmo: hm… the group/having is giving me the list of As with foobars containing least one x set to nil, so I can use that for another scope I need...
[13:09:03] guyzmo: tbuehlmann - yup, I thought about something like that, but how can I express that in a single query?
[13:11:03] guyzmo: tbuehlmann - actually I got a `foobar_position` to enforce the order, but for the sake of the discussion we can consider the first of the query result (whatever the order is)
[13:53:22] guyzmo: tbuehlmann - nope, foobar_position is unique for a given foobar_id
[13:54:15] guyzmo: tbuehlmann - I've been discussing about it with a colleague, and I could use a MIN(foobar_position) in a subquery… I'm not excited about using a subquery, though
[13:55:31] guyzmo: if only I could do a `having('min(foobars).x is null')` that would be great ^^
[13:57:48] guyzmo: is there anything else than postgres ? :)
[13:58:45] guyzmo: sylario - yup, that's what I'm heading to
[14:11:52] guyzmo: I think I haven't I've ever used over/partition in SQL
[14:12:31] guyzmo: or if I did it was in SQL class a decade ago :-p
[14:13:20] guyzmo: thank you a lot, and as a double bonus, I've (re?)learned something today :)
[14:14:44] guyzmo: oh, and is `A.from()` an AR idiom to convert some random SQL output into a model?
[14:19:25] guyzmo: so as I'm at it : is there a better way to output something like `A.where(id: B.somequery_that_returns_A_ids)` to basically tell ActiveRecord that I want to cast the query's output to some other model?
[14:23:10] guyzmo: so the A.where is the way to go
[14:23:18] guyzmo: double thanks :)
[14:45:23] guyzmo: haxx0r - https://askubuntu.com/questions/766334/cant-login-as-mysql-user-root-from-normal-user-account-in-ubuntu-16-04
[14:46:11] guyzmo: by default when you connect as root, it's not asking for a password as it uses a unix socket to connect, and just checks that you're connecting from a superuser account (aka root)
[14:46:41] guyzmo: so it's likely that the 1234 password is wrong
[14:47:49] guyzmo: and anyway, you'd better create an user for your project with enough privileges for rake db:create to do its job, which AFAICT does not need to be having full privileges over the DBMS
[14:48:22] guyzmo: more exactly that's the answer you'll want: https://askubuntu.com/a/801950/583565
[18:49:51] guyzmo: cagmz - actually, when in doubt, you /should/ use the Time object
[18:50:05] guyzmo: (rubocop taught me that ;-) )
[18:51:04] guyzmo: Time is using bindings from the systems, so it's much more efficient, DateTime is more complex and a full ruby implementation. It's useful only for some corner cases (which I don't remember) you're unlikely to need it for

2019-01-29

[10:40:38] guyzmo: has joined #RubyOnRails
[10:42:40] guyzmo: instead of doing `Foo.where(id: Bar.all.pluck(:foo_id))` would there be a way I could do `Bar.all.foos` that would be semantically the same, but with a straightforward syntax?
[10:43:45] guyzmo: (my goal being that I want to do that in a `has_many` on `Bar` that would return all foos of current `bar` instance)
[10:51:37] guyzmo: damn, my question is ill asked
[10:51:44] guyzmo: let me rephrase it better
[10:53:23] guyzmo: I got a `Mission` that has a prop (has_one) `Location` under the name `destination`. I got a `DeliveryRound` that has a prop (has_many) `Mission` under the name `missions`. In `DeliveryRound` I want to have a list of all `Location` under the attribute name `destinations`
[10:54:30] guyzmo: so now, what I'm doing is a `has_many :destinations, lambda { |dr| Location.where(id: dr.missions.pluck(destination_id)) }, class_name: 'Location'`
[10:55:24] guyzmo: (I'm writing it as we speak, and I'm about to test that, though I believe it should work fine)
[10:57:50] guyzmo: but that syntax feels weird to read (not straightforward), and I'm pretty sure it translates to a subquery in SQL. So I'm thinking there should be a more concise way to write the same query, that would translate in SQL to a join
[10:58:39] guyzmo: something that would looks like `dr.missions.destinations` which would return a collection of `Location`
[11:00:19] guyzmo: ok, now I feel dumb ☺
[11:01:01] guyzmo: now that you say it, it's obvious… why was I trying to over-complicate things ?
[11:08:36] guyzmo: (and thank you)
[15:03:44] guyzmo: Ping timeout: 250 seconds
[17:50:52] guyzmo: has joined #RubyOnRails