08:04
Swimming_Bird joined
08:24
<mwlang>
jeremyevans: I need to fix that select_limit_sql issue that came along with 3.9 that breaks the TOP N on MSDE 2000. Its impacting more code than I anticipated.
08:25
<mwlang>
I'll be happy to do the patch and run the specs, but I'm not quite sure where to start with doing detection of the DBMS to determine its pre-2005
08:38
<jeremyevans>
mwlang: You can use the server_version method to do the detection
08:38
<jeremyevans>
mwlang: I think < 9000000 is pre-2005, but I'm not sure
08:39
<mwlang>
ok, I'll do a little research.
08:39
<mwlang>
I've found the version info for Reporting Services, but not yet for DBMS. The 2000 documentation is long gone from MSDN
08:43
<Mathetes>
[00URL] How to identify your SQL Server version and edition
08:45
<mwlang>
odd....select serverproperty('productversion') returns a :untitled => nil
08:45
<mwlang>
but select @@version does return the info embedded in a long string of info.
08:48
<jeremyevans>
mwlang: You can use the server_version *method* to do the detection
08:48
<jeremyevans>
mwlang: i.e. DB.server_version
09:20
<mwlang>
hmmm...would a desired approach be to create a sub-adaptor called mssql2000 and have it house the select_limit_sql method? (I'm assuming we don't want to do a server_version test every execute of select_limit_sql)
09:25
<jeremyevans>
mwlang: Actually, the test on every execute of select_limit_sql is the correct way to handle it
09:26
<jeremyevans>
mwlang: It's not as expensive as you think.
09:26
<mwlang>
jeremyevans: ok, then that's how I'll implement it.
14:34
<IceD^>
I have model with `type` field for which I want custom accessors (it'll accept MyType instances and convert them into db representation, MyType is custom non-db class)
14:34
<IceD^>
how to do this?
14:34
<IceD^>
I assume, I can write def type and def type=
14:34
<IceD^>
but how to access real field from these methods?
14:35
<bougyman>
i would rename that field right now.
14:35
<bougyman>
not because you have to, but because of fewer headaches.
14:36
<IceD^>
means - have _type in db and simply use type and type= accessors?
14:36
<bougyman>
yeah, i wouldn't do that.
14:36
<bougyman>
i'd name it something more descriptive and use it in both places.
14:36
<IceD^>
don't understand
14:36
<bougyman>
you shouldn't need accessors if it's a model, sequel already has accessors for the db fields.
14:37
<IceD^>
let me explain
14:37
<spox>
IceD^: are they custom types?
14:37
<IceD^>
there is AccountType class which is loaded from yaml file
14:37
<IceD^>
I don't want and don't need to keep it in db
14:37
<IceD^>
it has uuid field which is used to identify account type
14:38
<IceD^>
for Account model I have type field in db which will store uuid
14:38
<bougyman>
i'd name that field uuid
14:38
<IceD^>
and I'd like to get real type when using account.type
14:38
<bougyman>
and have the 'type' method in your model look up the uuid field and match it in your YAML lookup list.
14:38
<IceD^>
and - I'd like to prevent users from accessing that uuid directly
14:38
<IceD^>
they only need type
14:39
<IceD^>
but... I can live with them accessible, I think
14:48
<IceD^>
and while I'm here
14:48
<IceD^>
what's preffered way for accessing fields
14:48
<IceD^>
model.field or model[:field]?
14:53
<IceD^>
it's necessary to use self.type_uuid in the accessors
15:34
<IceD^>
/home/iced/dev/wimm/model/account.rb:5: undefined method `validates' for Account:Class (NoMethodError)
15:35
<IceD^>
ahha - it looks like it's in plugin now
15:41
<IceD^>
how do I enable this plugin?
15:45
<jeremyevans>
IceD^: You can call super in the accessors after you do the conversion
15:45
<IceD^>
jeremyevans, already solved - I missed self.
15:50
<jeremyevans>
IceD^: And model.field is preferrable to model[:field]
15:50
<IceD^>
jeremyevans, guessed this as well - as there can be virtual fields e.g.
15:51
<jeremyevans>
IceD^: Yep
15:51
<IceD^>
btw - sequel is great but documentation really suck
15:52
<IceD^>
cheat sheet is great but not enough
15:52
<jeremyevans>
IceD^: Patches are welcome :)
15:53
<jeremyevans>
IceD^: And the RDoc documentation is fairly good. Introductory documentation is lacking, admittedly.
15:53
<IceD^>
rdoc is good, but it's damn hard to find smth in it unless you are familiar with sequel already ;)
15:54
<jeremyevans>
IceD^: True. The best way to improve the situation is to submit documentation patches
15:54
<IceD^>
writing docs isn't my favorite thing :)
15:54
<jeremyevans>
IceD^: Is there a particular area you are having a problem with?
15:55
<IceD^>
I decided to test sequel while writing my home accounting util (gnucash is killing me with it `usability`)
15:56
<IceD^>
and so far I'm doing good
15:56
<IceD^>
but that's my 15 years of programming experience
15:56
<jeremyevans>
IceD^: That's good. If you think that there's a particular area that we should cover more in the documentation, please let me know
15:56
<IceD^>
average coder will get lost in sequel
15:57
<IceD^>
it's necessary to add smth like activerecord intro docs
15:57
<IceD^>
common use cases
15:57
<IceD^>
or - expand cheat sheet with more information about models
15:57
<IceD^>
non-model issues are described pretty good here
15:57
<jeremyevans>
IceD^: I suppose we have different ideas of the average coder, but the documentation certainly assumes a familarity with both ruby and SQL
15:58
<IceD^>
but common person who simply want models (like activerecord, yes) - he will get lost, definitelly
15:59
<IceD^>
some small howto with master/detail models, virtual fields, validation will be great to have
15:59
<jeremyevans>
IceD^: I don't think it's definite, but I'm sure it can happen to a significant number of people
16:02
<IceD^>
and suggestion to feature - if field value is subclass of, let's say, Sequel::VirtualField (or has .from_value and .to_value methods) - it should work transparantly
16:02
<IceD^>
I'm always missing this feature in all orms, I used
16:03
<jeremyevans>
IceD^: Can you be more specific?
16:03
<keithcascio>
Would someone please remind me of the canonical name of the idiom: select || (insert && select) ?
16:03
<jeremyevans>
IceD^: Are you saying the setter methods should always check if the passed object has .to_value?
16:04
<jeremyevans>
keithcascio: find_or_create
16:04
<IceD^>
jeremyevans, not necessary - probably smth like virtual_field :field
16:04
<jeremyevans>
IceD^: I'm still not sure how you would want that to be used. Could you give an example?
16:05
<IceD^>
already given about an hour ago, but:
16:05
<IceD^>
Account model with type field
16:06
<IceD^>
in application we are using non-model AccountType class which can be mapped to type field and provides some additional info
16:06
<IceD^>
like one_to_one, but not in the db scope
16:06
<jeremyevans>
IceD^: Note that the composition plugin supports that, but it was added after 3.9.0
16:07
<IceD^>
sequel (3.9.0)
16:07
<jeremyevans>
IceD^: You need the master branch from github
16:07
<IceD^>
when >3.9.0 will be released?
16:07
<jeremyevans>
IceD^: Early next month. Generally releases are done in the first week of the month
16:08
<jeremyevans>
IceD^: Assuming there are enough changes to warrant a release
16:08
<IceD^>
nice ;) I can wait :)
16:09
<keithcascio>
What is the most idiomatic way to do FindOrCreate using Sequel?
16:10
<keithcascio>
I tried this:
16:10
<keithcascio>
def find_or_create(model, *args)
16:10
<keithcascio>
(model[*args] || ((model.insert(*args)) && model[*args])).id
16:11
<jeremyevans>
keithcascio: Model.find_or_create already exists. The FindOrCreate association extension is an example of a custom extension.
16:12
<Mathetes>
[00URL] Module: Sequel::Model::ClassMethods [Sequel: The Database Toolkit for Ruby]
16:15
<keithcascio>
Thank you Jeremy, that is exactly what I was looking for
16:21
<keithcascio>
jeremy: as far as you know, does find_or_create() work well with the :caching plugin? so far I'm seeing more SELECTs in the log than I expect
16:22
<jeremyevans>
keithcascio: No. The caching plugin only caches Model.[], and find_or_create uses Model.find()
16:22
<jeremyevans>
keithcascio: The caching plugin caches only by primary key, and find is called with an arbitrary hash
16:29
<keithcascio>
jeremy: that makes sense. It makes sense for the :caching to cache only by primary key, and it makes sense that find(), and thus find_and_create(), accepts an arbitrary hash
16:30
<IceD^>
I want to create decimal column in db
16:30
<jeremyevans>
IceD^: OK
16:30
<IceD^>
e.g. decimal(10,2)
16:30
<jeremyevans>
IceD^: OK
16:30
<IceD^>
how do I specify this in equel::Schema::Generator.column
16:31
<IceD^>
should go to sleep - it's specified in :size desciption
16:31
<jeremyevans>
decimal :column_name, :size=>[10,2]
16:41
<keithcascio>
jeremy: the following works as I want:
16:41
<keithcascio>
def lookup_or_create(model, *args)
16:41
<keithcascio>
(model[args] || model.create(args)).id
16:41
<keithcascio>
I think
16:42
<keithcascio>
no it does not work
16:48
<jeremyevans>
keithcascio: It still won't use caching. Model.[] is only cached is given a primary key
16:48
<jeremyevans>
keithcascio: If you give it a hash, it won't cache
16:49
<keithcascio>
jeremy: right, I was giving it an array, so it was caching, but then model.create() failed
16:49
<keithcascio>
def lookup_or_create(model, *args)
16:49
<keithcascio>
(model[args] || model.create(model.primary_key_hash(args))).id
16:49
<jeremyevans>
keithcascio: Composite primary key I assume?
16:50
<jeremyevans>
keithcascio: That will probably work
16:50
<keithcascio>
jeremyevans: I think it will, but right now I'm getting a exception, but I think I understand why
16:51
<jeremyevans>
keithcascio: You probably want the *args in the primary key hash
16:51
<keithcascio>
jeremyevans: it's the exception thrown on line 933 in base.rb: "method xxxxx= doesn't exist or access is restricted to it" (Sequel::Error)
16:52
<keithcascio>
jeremyevans: because I didn't define any accessors in my model subclass
16:52
<keithcascio>
jeremyevans: I apologize for how new I am to this, and I appreciate your help
16:53
<jeremyevans>
keithcascio: Use Model.unrestrict_primary_key
16:53
<jeremyevans>
keithcascio: Primary key access is restricted by default in the mass assignment methods
16:53
<jeremyevans>
keithcascio: The default is to assume surrogate keys instead of natural
16:55
<keithcascio>
jeremyevans: nice, that worked
16:55
<keithcascio>
jeremyevans: yes, for the purposes of my application, I'm using natural keys
16:56
<keithcascio>
jeremyevans: the Postgres primary key for each table is actually a surrogate "id" serial
16:56
<keithcascio>
jeremyevans: so when I define the model subclasses, I have to set_primary_key() explicitly
16:57
<keithcascio>
jeremyevans: so the following is working for me:
16:57
<keithcascio>
class Job < Sequel::Model(:job); set_primary_key [:policy, :schedule]; unrestrict_primary_key end
16:57
<jeremyevans>
keithcascio: If the database primary key is a surrogate, why do you want to define your own natural?
16:58
<jeremyevans>
keithcascio: I can't think of a good reason to do that
16:58
<keithcascio>
jeremyevans: for the purposes of this particular app, the lookups are always going to be over the natural key, never the primary key
16:58
<keithcascio>
jeremyevans: I'm thinking of the app as a "schema translation", I assume quite typical
16:59
<keithcascio>
jeremyevans: it takes a text stream as input, which is a representation of another proprietary "schema", and populates a relational database with that data
16:59
<jeremyevans>
keithcascio: Even if the lookups just use the natural keys, you shouldn't set the Sequel primary key different from the database primary key
17:00
<keithcascio>
jeremyevans: so every time my app encounters an "object" it must lookup a "handle" to it in the destination database
17:00
<keithcascio>
jeremyevans: I thought you might say that about "Sequel primary key different from the database primary key"
17:00
<jeremyevans>
keithcascio: I think I understand, but I still think you shouldn't use a different primary key
17:01
<keithcascio>
jeremyevans: thank you for your advice
17:01
<jeremyevans>
keithcascio: What problem does that solve?
17:01
<keithcascio>
jeremyevans: I agree that concepts are important and should not be subverted
17:01
<jeremyevans>
keithcascio: I'm trying to understand your reasoning for making the primary key different from the databases'
17:01
<keithcascio>
jeremyevans: OK I will explain more
17:02
<keithcascio>
jeremyevans: let's say I'm talking about one iteration of the main loop of my program, which looks at a single line of input
17:02
<jeremyevans>
keithcascio: OK
17:03
<keithcascio>
jeremyevans: that line contains enough "natural" information to lookup records for several "objects" from several different database tables, but of course lacks the surrogate primary keys
17:04
<jeremyevans>
keithcascio: Which is fine, you can still lookup by something that is not a key
17:04
<keithcascio>
jeremyevans: I need to look up the surrogate key for each "object", and I want caching to work
17:04
<jeremyevans>
keithcascio: Ah. So you are trying to use the caching plugin, which only caches based on primary key, by telling Sequel your primary key is different
17:05
<keithcascio>
jeremyevans: yes
17:05
<jeremyevans>
keithcascio: Not the approach I would recommend, but the reason now makes sense :)
17:05
<jeremyevans>
keithcascio: Personally, I'd not use the caching plugin, and just handle caching manually
17:06
<keithcascio>
jeremyevans: OK, I assume what I'm doing is abusive of the concepts involved, which I would prefer to avoid
17:06
<jeremyevans>
keithcascio: The caching plugin isn't really magical, you should just look at the source code to see what it is doing, and replicate the important parts in your app
17:07
<keithcascio>
jeremyevans: this app just seems so typical, I felt that a database toolkit should support what I'm doing
17:07
<jeremyevans>
keithcascio: It's possible something as simple as checking a populating a hash should work
17:07
<keithcascio>
jeremyevans: yes, a simple hash suffices
17:08
<keithcascio>
jeremyevans: and it would be simple to implement
17:08
<jeremyevans>
keithcascio: Well, apparently Sequel does, but I haven't encountered your use case before :)
17:08
<keithcascio>
jeremyevans: this has gotta be a very common use case
17:08
<keithcascio>
jeremyevans: you've got some huge "legacy" app that doesn't expose any kind of typical relational API
17:09
<keithcascio>
jeremyevans: you're only access to it's data is through command-line programs that dump out enormous amounts of semi-structured text
17:10
<keithcascio>
jeremyevans: you want to put all that in a modern, structured relational schema
17:10
<keithcascio>
jeremyevans: it's a "schema translation"
17:10
<keithcascio>
jeremyevans: the source "database" probably keeps its own primary keys, but you have no access to them
17:10
<jeremyevans>
keithcascio: What your describing probably isn't that rare, but the details are different enough that a ready made tool doesn't already exist
17:11
<keithcascio>
jeremyevans: interesting
17:11
<jeremyevans>
keithcascio: Adding your own cache via a hash is probably about 2 lines of code, and it's what I would always do
17:11
<jeremyevans>
keithcascio: I wouldn't have even thought to use models or plugins
17:11
<keithcascio>
jeremyevans: this is an interesting conversation for me, thank you
17:12
<jeremyevans>
keithcascio: Since this is a strict procedural import, I'd have stuck with basic datasets
17:12
<keithcascio>
jeremyevans: I appreciate that perspective
17:13
<keithcascio>
jeremyevans: this isn't the first time I've had to write a schema translation like this
17:13
<keithcascio>
jeremyevans: I did it at my former place of employment as well
17:14
<jeremyevans>
keithcascio: I've done some similar things, but usually they've been small enough that it was fairly easy to just write the script manually
17:14
<keithcascio>
jeremyevans: it's been a common use case in my life
17:14
<keithcascio>
jeremyevans: I believe in the principle that a programmer should struggle not to write code
17:15
<keithcascio>
jeremyevans: I believe in idiom
17:15
<jeremyevans>
keithcascio: Sequel would make it fairly easy to write a library that took an import format, and export schema, and a mapping, and handling importing into a database
17:15
<jeremyevans>
keithcascio: But that's not something that Sequel handles all by itself, and I'm not aware of another library like Sequel that handles it either
17:16
<keithcascio>
jeremyevans: from what I've gathered, Sequel is the state of the art, so I wouldn't expect much out of another toolkit
17:17
<jeremyevans>
keithcascio: I certainly feel it's the most advanced ruby database library :)
17:18
<jeremyevans>
keithcascio: If I found myself doing the same type of import over and over, I'd certainly write the library to make it simpler
17:21
<keithcascio>
jeremyevans: the library you describe -- great idea
17:22
<jeremyevans>
keithcascio: If it's something you are interested in working on, I'd be happy to answer any questions you have regarding Sequel
17:23
<keithcascio>
jeremyevans: I haven't committed myself to a particular style of solution just yet
17:24
<keithcascio>
jeremyevans: I've written so much code in my life, and I've seen programmers in a rush to write code, I'm not quite so desperate
17:25
<keithcascio>
jeremyevans: when I approach a task, the first thing I want to educate myself about is: what concepts have been developed by others who care about this arena?
17:26
<jeremyevans>
keithcascio: A wise approach.
17:26
<keithcascio>
jeremyevans: that's what relational database theory is, after all
17:26
<keithcascio>
jeremyevans: it's people who've been racking their brains for decades, asking themselves: "what are the important use cases?"
17:27
<keithcascio>
jeremyevans: "how can we build a powerful system that automates the things that seem to come up frequently?"
17:27
<keithcascio>
jeremyevans: it's the essence of declarative programming itself
17:27
<keithcascio>
jeremyevans: thank you, btw
17:28
<jeremyevans>
keithcascio: I agree. And thank you for the interesting discussion :)
17:28
<keithcascio>
jeremyevans: the practice of programming is relatively young
17:29
<keithcascio>
jeremyevans: smart people try to introduce technology/concepts that streamline the work: e.g. RDMS theory, functional programming theory
17:29
<keithcascio>
jeremyevans: but there is surprising resistance to these styles
17:30
<keithcascio>
jeremyevans: people just want to learn how to write a for(;;) loop and write that same for(;;) loop over and over
17:30
<keithcascio>
jeremyevans: but that's not the future
17:32
<keithcascio>
jeremyevans: the future is more declarative, "logical"
17:38
<keithcascio>
jeremyevans: I am at the point where I finally understand the sense in which SQL is a logical programming language: you give the RDBMS a theorem and it finds a proof of that theorem -- beautiful
17:40
<keithcascio>
jeremyevans: designers had to figure out "how do we _say_ such and such?" and "how do we _compute_ such and such is the most general possible case?"
17:41
<keithcascio>
jeremyevans: "in the most general possible case?
17:42
<jeremyevans>
keithcascio: Sorry, got pulled away
17:42
<jeremyevans>
keithcascio: The beauty of SQL is that it is declarative and doesn't require internal knowledge from the user
17:43
<jeremyevans>
keithcascio: The downside is that you can't generally control how the database gets the information
17:43
<jeremyevans>
keithcascio: But most decent databases have good optimizers, and do a better job than most users would be able to do
17:44
<keithcascio>
jeremyevans: for sure
17:44
<keithcascio>
jeremyevans: another beauty is just to learn the concepts that appear in modern databases
17:45
<keithcascio>
jeremyevans: it's been a way for me to clarify my thinking
17:46
<keithcascio>
jeremyevans: I might have imagined doing something another way, resisted the RDBMS way, but ultimately realized the established way was far more elegant and general
17:46
<keithcascio>
jeremyevans: of course, as you note, there are limitations