Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
xtal
Jan 9, 2011

by Fluffdaddy

Jam2 posted:

code:
  def method_missing(method)
    if value = method.to_s[/plus(\d+)/, 1]
      puts value, "yes"
    end
  end
2) What is the purpose of the 1 after the comma?

It's the second argument to String#[]:

quote:

If a Regexp is supplied, the matching portion of str is returned. If a numeric or name parameter follows the regular expression, that component of the MatchData is returned instead.

xtal fucked around with this message at 08:44 on Jun 19, 2011

Adbot
ADBOT LOVES YOU

xtal
Jan 9, 2011

by Fluffdaddy
I think you can get the current working directory with Dir.pwd.

xtal fucked around with this message at 05:52 on Mar 30, 2012

xtal
Jan 9, 2011

by Fluffdaddy
Ruby 2.0 has been released, on the same day as Ruby's 20th birthday. :yotj:

xtal
Jan 9, 2011

by Fluffdaddy

Lexicon posted:

In ruby, is there an easy way to tell at the point of execution whether "self" refers to a class or an instance? I'm debugging some meta-programming hell (that I didn't write) and self.extend is getting called on a class instead of an instance somehow, and causing class-wide definitions that I don't want to exist. Basically, I want the opportunity to insert in "debugger if self is a class" so I can see where it's being called from. Any thoughts?

Pedantry: everything in Ruby is an instance. :) Fixnum.is_a?(Class) is true not because Fixnum is a class per se, but because Fixnum is literally an instance of Class.

xtal
Jan 9, 2011

by Fluffdaddy
Given an exported GPG private key and its passphrase, how can I decrypt a string encrypted with the corresponding public key? Haven't had any luck with GPG-related gems, which all seem to rely on pinentry/gpg-agent instead of a provided passphrase.

xtal
Jan 9, 2011

by Fluffdaddy
Installing GPG is fine, but I'd like to do it without needing to --import the key or deal with pinentry. Suppose this is more of a GPG question than a Ruby question now, though.

xtal fucked around with this message at 02:35 on Jul 9, 2013

xtal
Jan 9, 2011

by Fluffdaddy

Molten Llama posted:

You can use a regex. Nobody's saying don't use a regex at all—just don't cook up your own or try to be too restrictive. There are edge cases (like really short domains and really long domains). Standards change. TLDs multiply. If you're doing excessive validation, you're driving away customers who are now also angry.

There's a reason today's "canonical" email regexes like the one Devise uses effectively amount to "is there one @ and at least one .?" That regex will work today and for years to come. The one that validates the length of a domain, or checks against a hard-coded master list of TLDs (yes, I've seen that), or requires all TLDs to be 3 characters, or declares uppercase characters to be verboten, or allows only one . in the domain is gonna have issues. (And even matching for a . will fail for some uses, but you probably already know if that's a design constraint.)

Find a widely-used, permissive regex. Validate it against of variety of input. If an address doesn't feel right despite matching, don't dismiss out of hand—verify it through some other means, like a confirmation email where it's appropriate, or the gem kitten smoothie found where it's not.

ThIs!{is}a$perfectly&valid^email=but_/many%regexes+will#fail~it@example.com. Several of those characters show up fairly frequently at large corporations.
Or for an even more common, frequently-failed use case, the simple user+tag@domain.xxx. Fails crappy regexes all the time. Valid. Useful.

Pedantry that you're probably already aware of: checking for a dot is also unecessary; validations should only check for an "@". TLDs can have MX records, especially in intranets or with custom hosts files.

xtal
Jan 9, 2011

by Fluffdaddy
I actually test if my classes inherit from ActiveRecord::Base sometimes. You can't have too many tests.

xtal
Jan 9, 2011

by Fluffdaddy
Not as much of a concern as code correctness, that's for sure! Plus use Guard.

xtal
Jan 9, 2011

by Fluffdaddy
What's the ideal way to test Rails 4 concerns? Trying to switch my code base to use them more and they're being really irritating.

edit: http://www.dotnetguy.co.uk/post/2012/08/26/rails-rspec-testing-your-modules/

xtal fucked around with this message at 17:40 on Aug 25, 2013

xtal
Jan 9, 2011

by Fluffdaddy

Novo posted:

This is dumb; you might as well be writing tests to make sure your models respond to Object methods.

TDD is writing tests first and having them tell you what code to write. Testing your class's inheritance is a perfectly logical starting point and there's literally no downside aside from an extra few milliseconds when you first start your tests.

xtal
Jan 9, 2011

by Fluffdaddy
Keep using your VM.

xtal
Jan 9, 2011

by Fluffdaddy
Heroku is trash. Don't use Heroku. If you just care about getting your app live and not about system administration (and are comfortable paying a premium for that luxury) use cloud66 or another alternative.

xtal
Jan 9, 2011

by Fluffdaddy

atastypie posted:

Heroku is good enough for small projects. It has gotten worse over the last few years, or maybe it's only S3 that has gotten worse, but it's still perfectly fine to recommend.

Cloud66 is really interesting. Can you talk about your experience with it? We run about ~12 apps on Heroku and would consider switching, but we sure as poo poo don't want to be doing any ops.

edit: oh cloud66 is $9/mo per app and not per server, as it won't spin up more than a single app per server. Still cheaper than Heroku but not by as much as I thought. Here I was imagining a big ol' server running a bunch of apps on it, or multiple instances of one app on a single server, but nope

It's a buttload cheaper than Heroku. Adding a DigitalOcean worker is $5 compared to $36, and you just pay a $9 surcharge. It's cheaper and more performant in every possible combination with the exception of Heroku's free tier, which spins down your app after 15 minutes of inactivity. For any website being used by more than its author, that's unacceptable. Plus Heroku lies to their customers and is down all the time and stuff.

But if it is just for the author, then it doesn't really matter!

xtal fucked around with this message at 22:22 on Sep 6, 2013

xtal
Jan 9, 2011

by Fluffdaddy
Coming back to Rails development and I see that unicorn is included in the default Gemfile now. Is that the preferred web server or do people still use Thin / Passenger?

xtal
Jan 9, 2011

by Fluffdaddy

Lexicon posted:

Dude, this is nothing compared to the Java/Struts/Spring/whatever the gently caress else days of yore (uphill both ways, etc).

It probably could be easier, but this is all fairly complex computing machinery.

I don't think that's fair, I set up Java for development in 15 minutes and 10 of it was downloading packages because I haven't ever had anything Java on my computer. It's not hard to set up a development environment in either language anymore.

xtal
Jan 9, 2011

by Fluffdaddy

Sailor_Spoon posted:

Yes, you can just let bundler handle all the gem installation. The only downside is that you might have to preface your middleman calls with "bundle exec".

Bundler doesn't strictly sandbox gems like using gemsets, or python's virtualenv. Think of it as a filter on the larger pool of gems that you have installed, making sure that only the ones you've specified are activated.

If you use binstubs, you won't need to use bundle exec. And if you use the --path option, you can install them in your vendor/ruby (or any other) folder and not globally. The only non-default gem I have installed globally is bundler.

xtal
Jan 9, 2011

by Fluffdaddy

Sil posted:

I'm reading about Vagrant and in their docs they do

code:
$script = <<SCRIPT
echo I am provisioning...
date > /etc/vagrant_provisioned_at
SCRIPT
to define a multiline string. Is this just syntactic sugar for the,"""string with preserved newlines""", triple double quotes?

OK, never mind I tracked it down via google. It's just a different type of string literal. For some reason searcing ruby-doc.org for << doesn't find anything.

Ruby doesn't have triple-quote literals in the sense that Python does. It just concatenates two adjacent string literals together implicitly. """something"""" is just "" + "something" + "".

xtal
Jan 9, 2011

by Fluffdaddy
Rails is great for JavaScript apps actually if you think of it as Sinatra with an asset pipeline. Your Rails app will only handle compiling your JavaScript and reading or writing to the database via a RESTful API. Your JavaScript will do the routing and the rendering. It's not practically correct to say that one or the other does the modeling: they both do the modeling, but JavaScript reads from your API and your API reads from your database. They're both different representations of the same model.

You also don't necessarily need to write JavaScript, but I get what you're saying. You could make a full web app in Opal or ClojureScript or whatever that simply interfaces with your Rails API. Consider also that it's very easy to build a new phone app or desktop app or command line tool or whatever when your API is your first-class citizen.

xtal fucked around with this message at 01:06 on Jul 11, 2014

xtal
Jan 9, 2011

by Fluffdaddy
If you're storing a date in your database and using a time zone that isn't UTC, that's the real problem.

xtal
Jan 9, 2011

by Fluffdaddy

KoRMaK posted:

It's great, I've written a handful of "has_many" style class methods that reduce a bunch of boilerplate code.

Reducing boilerplate is good metaprogramming. find_by_.. is bad metaprogramming. It's a delicate balance that I think focuses on keeping the explicit explicit and avoiding so-called magic.

(In your case, aren't you reimplementing modules and include?)

xtal fucked around with this message at 01:43 on Aug 19, 2014

xtal
Jan 9, 2011

by Fluffdaddy

KoRMaK posted:

Well, uh, to be honest.

My module builds a bunch of find_by.. style things. Mine are for jquery tokenizers. They build a json object for them. They all take the form tokenize_.. and automate the ActiveRecord and other relationship methods and different ways to render them that the rest of the app can automatically expect and automate a lot of individual file editing I would have to do.

It's okay to use a has_many method to create several methods dynamically. It's not okay to overload method_missing to do (e.g.) regular expression matching and dispatching on dynamic data. Things should be explicit, opt-in and understandable, but it's hard to describe exactly where that line is.

quote:

I'm not sure what you mean, can you clarify?

If you're using metaprogramming to DRY up method definition with static data you might as well just put those things in a module. But that doesn't seem to apply to your case.

xtal
Jan 9, 2011

by Fluffdaddy
This is real pedantry but the self is unnecessary in that code. You can just use to_s.split.... You only need to use the self-dot notation to differentiate from local variables.

Also, it's good practice to capture and pass on the block when making delegating functions. You might as well use *args, &blk in all cases.

xtal fucked around with this message at 19:36 on Aug 26, 2014

xtal
Jan 9, 2011

by Fluffdaddy

KoRMaK posted:

Don't worry about it, I like hearing this stuff.

...I use self like this. I just don't feel safe not using it.

What? Can you give me a code example of what that would look like?

Ruby code:
def receiver(uno, dos, &blk)
  # do some stuff
end

def delegator(*args, &blk)
  receiver(*args, &blk)
end
Same concept as your code, but also passing along the block. The ampersand is used to (a) capture references to blocks on the receiver (b) pass along blocks on the sender, much like the asterisk either packs or unpacks depending on where you use it.

&blk (which could be &anything) stands in competition to yield. The difference is that yield will fail if there is no block, and the block is not assigned to a variable. With &blk, the block isn't required (the variable will be set to nil) and you have a named function object that you can wrap or pass on to other functions.

When you call something with an ampersand argument it means "try to convert this object to a Proc, then pretend that Proc is a block I've just sent you." Symbols implement to_proc, which is why you can use select(&:positive?).

xtal fucked around with this message at 20:05 on Aug 26, 2014

xtal
Jan 9, 2011

by Fluffdaddy

KoRMaK posted:

I'm not following what you are getting at. How would this have improved what I wrote? Can you rephrase your example in the context of the example I gave?

I reworded my post a bit, not that it made a substantial difference. The idea is basically that if you're making a delegating function with *args, there's no downside to sending along the &block in addition. It'll save headaches down the road, and the delegator doesn't need to know what the receiver does or doesn't support -- it should pass along everything and the receiver should validate it.

xtal
Jan 9, 2011

by Fluffdaddy

KoRMaK posted:

Oh... Ohhhhh.

But what If I have a more than one when? I don't think it will work.

In the meantime, I created a bunch of procs in a hash and another hash
with the cases and the proc hash key as a value and it's working pretty
well.

You're not going to be able to do that. Wrap the method:

code:
def my_method(bar)
  case bar
    when 1
      my_other_method
    else
      their_method(bar)
  end
end
Case statements are almost always a bad thing (for reasons including this one) so if it weren't a library my suggestion would be to remove it outright. (If this is your library and the goal is to make the case statement open to external extension, replace the case statement with a hash that's made accessible by your library.)

xtal
Jan 9, 2011

by Fluffdaddy

necrotic posted:

It's actually for anything really. There's app/concerns, app/models/concerns, and app/controllers/concerns. Its for functionality that is reusable across multiple objects (usually of a common type, like a model or controller) but not every object. Its kind of a band-aid around fat controllers and models in my opinion. Once you include them you still end up with a fat controller or model, its just hidden away in another module.

Concerns increase modularity and composability, and that leads to better controllers and models and such. It doesn't prevent (or relate to) the problem of making objects that do too much.

Whenever you're adding code to a controller or model, do your best to generalize it and move it to a concern, even if it will only be used by that controller (at first.)

xtal
Jan 9, 2011

by Fluffdaddy

EVGA Longoria posted:

Anyone have an idiomatic example of reading rc files for configuration? Specifically, I'm looking to read bowerrc files, which can be in the global root, the user's home, or any directory in the tree up from current working directory.

Easy enough to do, but I'd rather not reinvent the wheel if it's already been done in a pretty manner.

I don't think that you need a library for something like that. I don't know of any. It's pretty easy to whip up in an ad-hoc fashion. This function uses recursion to traverse from the current directory to the root in search of filename.

Ruby code:
require 'pathname'

def find(filename, cwd = Pathname.pwd)
  if (pathname = cwd.join(filename)).file?
    pathname
  elsif !cwd.root?
    find(filename, cwd.dirname)
  end
end

conf = find ".bowerrc" || "/etc/bowerrc"

xtal fucked around with this message at 20:42 on Jan 6, 2015

xtal
Jan 9, 2011

by Fluffdaddy

MALE SHOEGAZE posted:

:rolleyes: :rolleyes: :rolleyes:


By putting most of your code in the app/models folder, you're at least strongly implying that those classes depend on the ruby on rails framework. It's extremely likely that that dependency isn't actually necessary, but nevertheless, all of your code is now tightly coupled to the rails framework, and in fact tightly coupled to the rest of your application.

By pulling that code out of your rails application, and sticking it in the library, you're at least implying that your code should be easily composable throughout the rest of your application. Not only that, but you're setting yourself up to make it easy to break that code out into external services, or to reuse it in other applications.

Basically, the app folder is for implementation code, which means you're not writing interface code, which means you're probably wasting a lot of time.

Or you're doing it right but sticking everything in models because

The lib folder is a junk drawer that really shouldn't exist. If something is part of your application but doesn't cleanly fit into app/models or app/controllers or app/something, put it in app/someotherthing. If it's not part of your application, put it in a gem. There's nothing wrong with having app/sweepers, app/services, and so on in your Rails app.

xtal
Jan 9, 2011

by Fluffdaddy
Separating your application by feature is a great idea that a lot of new frameworks and tools are using. But I don't think that means moving everything from app/views/posts and such to app/posts -- it's more nuanced than that. If you were to cut out the app/posts component and convert it to a gem, would those views or controllers still work and still be useful? Maybe, but probably not. The controller probably has less to do with the posts module and more to do with your routing and rendering layer. So maybe you'd end up with app/controllers/posts_controller.rb, and also app/posts/post_creator.rb, app/posts/post_finder.rb, and so on.

xtal
Jan 9, 2011

by Fluffdaddy
HTTPS should be your default choice for all apps. You can get free SSL from StartSSL or for free with a domain from Gandi or NameCheap.

xtal
Jan 9, 2011

by Fluffdaddy

Cocoa Crispies posted:

If your Sinatra app is big enough that you are bothering to use Code Climate on it and care about your grade, make it a Rails app.

Sinatra is a great choice for large applications. Well, the HTTP server and router part of it.

xtal
Jan 9, 2011

by Fluffdaddy
You're really missing out if you write Ruby without contracts.ruby. (Duck-)type safety and multimethods are very welcome additions to the language.

If you agree, also check out Crystal.

xtal
Jan 9, 2011

by Fluffdaddy
e: didn't mean to post this

xtal fucked around with this message at 08:51 on Sep 6, 2016

xtal
Jan 9, 2011

by Fluffdaddy

Peristalsis posted:

Is it okay to use Ruby's object_id as a hash key?

I tried using objects as keys, but that backfired. For example, this code seems to work:
code:
foo = Bar.new
foo.my_attr = "bleah"
my_hash = {}
my_hash[foo] = "meh"
my_hash[foo]  # => "meh"
# Changing an attribute of foo doesn't hurt anything:
foo.my_attr = "yuck"
my_hash[foo]  # => "meh"
but as soon as I saved foo, it failed:
code:
...
foo.save
my_hash[foo]  # => nil
foo.object_id doesn't seem to change when I save foo, or even when I destroy it, but I guess I'm a little gun-shy at this point. The reason this is coming up is that I need to have a hash associating things with a set of model objects, each of which may or may not be persisted. Ruby 2.1.1p76 and Rails 4.2.5, if that matters. (Though if that matters, I probably shouldn't do it .)

When you use an object as a hash key it calls the `hash` method on the object. (eta: I am actually not 💯 about this.) For `ActiveRecord::Base` this delegates to `id.hash`. The reason this breaks when you save is that it is given an ID which changes the result of the hash function. Using `object_id` is probably fine but I think the most elegant approach is overloading the `hash` method on whatever class you're working with.

xtal fucked around with this message at 17:33 on Sep 6, 2016

xtal
Jan 9, 2011

by Fluffdaddy

Peristalsis posted:

Alas, I can't, which is why this came up.


I appreciate both your inputs - I'll think on this some more. At least I've done due diligence to make sure there's no obvious approach or ubiquitous pattern to avoid this issue.

For now, I've kept the model objects as keys, and put a big, ugly comment in the code that it's brittle, and only works here because the code is strictly being used in a view, and the objects won't change or be persisted between the hash being constructed and being accessed. I need to move on with the work (this is all just to reformat a single, confusing display on a form), but I'll keep thinking about better ways to go about this. It's already an obnoxiously complex data structure, and every other approach I think of makes it even worse (and might not work any better, if object_id isn't reliable, either). I'm hoping to avoid creating a whole new class just to populate some data to show on a screen, but if the overall approach I'm taking turns out to work and be sensible, then that may be the less bad alternative.

Whether or not `object_id` works depends on how you're using it. It will stay the same after you save it, but it will change if you copy the object or load another one from the database. It's the ID of the object in Ruby space, defined on `Object`.

I think that all you need is something like this, provided there is some attribute on the record that is unique (for the purpose of hash equivalence.) Then you can use `Something`s as hash keys that will persist between saves and retrievals.

Ruby code:
class Something < ApplicationRecord
  delegate :hash, to: :some_unique_identifier_such_as_name
end

xtal
Jan 9, 2011

by Fluffdaddy

Peristalsis posted:

Also, is RVM the normal way to use RoR on Macs? I recently acquired a used MacBook, and would like to be able to use it to work on this program. I just don't know what the standard way is to use Macs for rails development.

The preferred option is to use the latest Ruby version installed through Homebrew. The next best option is virtualizing your applications through Vagrant or Docker and installing the necessary Ruby version in each one.

Maintaining multiple versions of Ruby is one of the worst parts of the languages tooling and you should avoid it if you can.

If for some reason you genuinely need multiple versions of Ruby on one host, use a more simple and secure option than RVM which is basically worst thing you can use. You can compile Ruby versions to separate `$PREFIX`es and change your `$PATH` to point to the one used by your project for example. There are tools to automate this, I believe they're called chrb and rb.

xtal
Jan 9, 2011

by Fluffdaddy

8ender posted:

Docker has made our dev environment mostly portable with the gigantic caveat that Docker with Virtualbox on a mac uses a tremendous amount of resources all the time.

Isn't it possible to use Docker on a Mac without an explicit Linux VM now? I don't know, because I've always used Vagrant, but virtualizing your development environment is easy to set up (google and copy and paste into a Vagrantfile) and literally all upsides. Most of all you don't mess around with that poo poo that works at the shell-level and will ruin your day when you're scripting or logging in over SSH.

xtal
Jan 9, 2011

by Fluffdaddy
Concurrent writing is one caveat but using a dynamically-typed database is not a good idea irrespective of scale

Adbot
ADBOT LOVES YOU

xtal
Jan 9, 2011

by Fluffdaddy
Say you're the back-end developer on a project with several front-end developers, and they ask for a shared development server so they don't need to run a Rails server locally. Is it crazy for me to say no? My concern is that they will end up wanting arbitrarily many servers to avoid colliding work, and I would rather solve this problem by reducing the friction for running your own server.

xtal fucked around with this message at 00:51 on Sep 21, 2016

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply