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
kayakyakr
Feb 16, 2004

Kayak is true
Alternatively, I can offer you an unpaid internship writing tests for our cludge of a startup app :v:

Adbot
ADBOT LOVES YOU

semicolonsrock
Aug 26, 2009

chugga chugga chugga
Seems reasonable ! That's what I've been doing so far, just gradually making progress on a pet project.

(And ty for the offer of a second, unpaid job)

kayakyakr
Feb 16, 2004

Kayak is true
I felt bad calling my startup a cludge. It's actually pretty decent code on the back end. It's the front end that can get cludgy. An ember monolith, as it is.

But we really do need to get the testing suite sorted out. We've got sporadic integration tests, unit tests, tests that do nothing, tests that are testing features that aren't in the system anymore. It's a big mess. My first attempt to get one of the partners to write tests for some functionality (as a way to help him learn ruby and rails) wound up with a 2000 line monstrosity >_<.

So #1) What's a fair value for a "bounty" on a test to bring in an outside entry/junior developer, and #2) anyone have any suggestions for integrating JS testing for the Ember stuff into a Rails test suite?

hmm yes
Dec 2, 2000
College Slice
If you're looking to sharpen your skills you could consider trying to close some issues for open source gems. It doesn't matter which one. It's a little like jumping into the deep end of a pool without knowing how to swim, but it will encourage you to do good things like write tests, analyze someone else's code, document changes, and create good pull requests. It isn't building a Rails app, but I would argue that you will learn more and have a bigger impact than if you just worked on a pet project. Even if your PRs get rejected :shobon:

semicolonsrock
Aug 26, 2009

chugga chugga chugga

atastypie posted:

If you're looking to sharpen your skills you could consider trying to close some issues for open source gems. It doesn't matter which one. It's a little like jumping into the deep end of a pool without knowing how to swim, but it will encourage you to do good things like write tests, analyze someone else's code, document changes, and create good pull requests. It isn't building a Rails app, but I would argue that you will learn more and have a bigger impact than if you just worked on a pet project. Even if your PRs get rejected :shobon:

That sounds interesting! I'll look into them as they come up. Is there a good place to see these aggregated? Or is it more case-by-case?

DONT THREAD ON ME
Oct 1, 2002

by Nyc_Tattoo
Floss Finder

semicolonsrock posted:

That sounds interesting! I'll look into them as they come up. Is there a good place to see these aggregated? Or is it more case-by-case?

Well, github would be the obvious choice, but someone it's actually impossible to find things on github.

The Journey Fraternity
Nov 25, 2003



I found this on the ground!
Could always look at a site like http://www.ruby-toolbox.com to see what the most popular ones are, then dive into one on Github to see what its open issues are.

Pollyanna
Mar 5, 2005

Milk's on them.


kayakyakr posted:

What's a fair value for a "bounty" on a test to bring in an outside entry/junior developer?

As an entry/junior developer who just went through the job search wringer, don't do this. One of the companies I interviewed with wanted me to basically work there for 3 days on one of their problems as part of the interview process, which felt like too much of a time investment to me, especially when I had interviews going at the same time. It didn't reflect well on the company, in my opinion. Not saying you'll be doing exactly that, but it tends to turn us off.

As for integrating Ember with Rails and Rails testing, my advice is don't. The best way to combine Rails with front-end frameworks, in my opinion, is to keep them decoupled from each other by making the Rails app an API that the front-end app consumes. Basically, make them two separate projects. This has the side effect of not causing merge conflicts if two people working on different "ends" touch the same file - I constantly ran into this issue while working on some projects, and this helped immensely.

Pollyanna fucked around with this message at 18:48 on Feb 19, 2015

prom candy
Dec 16, 2005

Only I may dance
I'm pretty sure asking people to produce work for you for free as part of the interview process is illegal.

KoRMaK
Jul 31, 2012



What does bounty on a test mean?

kayakyakr
Feb 16, 2004

Kayak is true

KoRMaK posted:

What does bounty on a test mean?

Instead of an hourly fee or a project fee, I would want to pay a completion fee for each test file. Basically, I could estimate how long it would take me to write the test, apply a rate, and set that as the bounty so it would be worth, say, $100 for each completed spec.

Pollyanna posted:

As an entry/junior developer who just went through the job search wringer, don't do this. One of the companies I interviewed with wanted me to basically work there for 3 days on one of their problems as part of the interview process, which felt like too much of a time investment to me, especially when I had interviews going at the same time. It didn't reflect well on the company, in my opinion. Not saying you'll be doing exactly that, but it tends to turn us off.

Not part of the interview process, just a way to set contracting rates. That is a pretty BS thing. If they're going to ask you to work there for 3 days, they had better be paying you for it. In general, when hiring for a mid+ level position, I will either want to see a github with various projects or will ask for a 2-3 hour example project (generally just setting up the project, doing some data modeling and scaffolding) or a 2-3 hour modification to a project I set up.

For jr/entry level, I really just want to see that you can intelligently talk about programming, problem solving, and general technology.

Pollyanna posted:

As for integrating Ember with Rails and Rails testing, my advice is don't. The best way to combine Rails with front-end frameworks, in my opinion, is to keep them decoupled from each other by making the Rails app an API that the front-end app consumes. Basically, make them two separate projects. This has the side effect of not causing merge conflicts if two people working on different "ends" touch the same file - I constantly ran into this issue while working on some projects, and this helped immensely.

The two are decoupled. They live in the same project, but the rails side operates as API while the Ember side operates on its own. I do still want integration/regression tests on the whole thing, though, as that's where most of our issues are occurring.

Merge conflicts are a part of programming. You'll get used to them.

I was thinking about using this project for the JS testing: https://github.com/jfirebaugh/konacha.

MasterSlowPoke
Oct 9, 2005

Our courage will pull us through
I've got the feeling I'm not writing my tests properly:

Ruby code:
RSpec.describe Activity, :type => :model do
  context "on creation" do
    before do 
      @lead = FactoryGirl.create(:lead).reload
      @activity = FactoryGirl.create(:activity, lead_id: @lead.id).reload
      @lead.reload
    end

    it "updates last_activity_at of the parent lead" do
      expect(@lead.last_activity_at).to eq(@activity.created_at)
    end
  end

  context "on deletion" do 
    before do 
      @lead = FactoryGirl.create(:lead)
      @first_activity = FactoryGirl.create(:activity, lead_id: @lead.id, created_at: 5.minutes.ago).reload
      destroyed_activity = FactoryGirl.create(:activity, lead_id: @lead.id, created_at: 2.minutes.ago).reload
      destroyed_activity.destroy
      @lead.reload
      
    end

    it "resets the last_activity_at to the last activity" do
      expect(@lead.last_activity_at).to eq(@first_activity.created_at)
    end
  end
end
Ruby code:
RSpec.describe Lead, :type => :model do
  it "can point you to the previous and next leads" do
    leads = 5.times.collect { FactoryGirl.create(:lead) }

    expect(leads[0].prev_lead).to be nil

    leads.each.with_index do |lead, i|
      expect(lead.prev_lead).to eq(leads[i-1]) unless i == 0
      expect(lead.next_lead).to eq(leads[i+1]) unless i == 4
    end

    expect(leads[4].next_lead).to be nil
  end
From browsing around online I'm thinking that my before blocks there aren't ideal, and that I have way too many expects in the last example. Is there a resource to help me write better tests? Or am I crazy?

EVGA Longoria
Dec 25, 2005

Let's go exploring!

MasterSlowPoke posted:

I've got the feeling I'm not writing my tests properly:

Ruby code:
RSpec.describe Activity, :type => :model do
  context "on creation" do
    before do 
      @lead = FactoryGirl.create(:lead).reload
      @activity = FactoryGirl.create(:activity, lead_id: @lead.id).reload
      @lead.reload
    end

    it "updates last_activity_at of the parent lead" do
      expect(@lead.last_activity_at).to eq(@activity.created_at)
    end
  end

  context "on deletion" do 
    before do 
      @lead = FactoryGirl.create(:lead)
      @first_activity = FactoryGirl.create(:activity, lead_id: @lead.id, created_at: 5.minutes.ago).reload
      destroyed_activity = FactoryGirl.create(:activity, lead_id: @lead.id, created_at: 2.minutes.ago).reload
      destroyed_activity.destroy
      @lead.reload
      
    end

    it "resets the last_activity_at to the last activity" do
      expect(@lead.last_activity_at).to eq(@first_activity.created_at)
    end
  end
end
Ruby code:
RSpec.describe Lead, :type => :model do
  it "can point you to the previous and next leads" do
    leads = 5.times.collect { FactoryGirl.create(:lead) }

    expect(leads[0].prev_lead).to be nil

    leads.each.with_index do |lead, i|
      expect(lead.prev_lead).to eq(leads[i-1]) unless i == 0
      expect(lead.next_lead).to eq(leads[i+1]) unless i == 4
    end

    expect(leads[4].next_lead).to be nil
  end
From browsing around online I'm thinking that my before blocks there aren't ideal, and that I have way too many expects in the last example. Is there a resource to help me write better tests? Or am I crazy?

http://betterspecs.org/ is a great resource, and I try to stick to it whenever it makes sense.

I'm looking at your tests and the relationship between lead and activities makes it a bit weird. I would probably do:

Ruby code:
RSpec.describe Activity, :type => :model do
  context "on creation" do
    let(:lead) { create(:lead)}
    let(:activity) { create(:activity, lead: lead) }
    it "updates last_activity_at of the parent lead" do
      expect(activity.lead.last_activity_at).to eq(activity.created_at)
    end
  end

  context "on deletion" do 
    let(:lead) { create(:lead)}
    let(:activity) { create(:activity)}

    it "resets the last_activity_at to the last activity" do
      destroyed_activity = create(:activity, lead: lead) 
      destroyed_activity.destroy
      expect(lead.last_activity_at).to eq(activity.created_at)
    end
  end
end
Then for your Lead test:

Ruby code:
RSpec.describe Lead, :type => :model do
  
  context 'relationships' do

    let(:leads) { FactoryGirl.create_list(:lead, 3) }

     it "returns nil before the first lead" do
      expect(leads[0].prev_lead).to be nil
    end

    it 'returns nil after the last lead' do
      expect(leads[-1].next_lead).to be nil
    end

    it 'returns the previous lead' do
      expect(leads[1].next_lead).to be leads[0]
    end

    it 'returns the next lead' do
      expect(leads[1].prev_lead).to eq leads[2]
    end
  end 
create_list does what you want without a 5.times. You should strive to have only a single expectation per test, so split the tests out. And don't do clever things like loops with expectations inside -- it wasn't testing any more than this does, but it was more complex and likely to fail.

EVGA Longoria fucked around with this message at 21:01 on Feb 23, 2015

MasterSlowPoke
Oct 9, 2005

Our courage will pull us through
Gotcha, thanks. I've written these tests for my user model using that info, do they look good?

Ruby code:
RSpec.describe User, :type => :model do
  [...]
  context "admin scope" do 
    let(:users) { FactoryGirl.create_list(:user, 2) }
    let(:admin) { FactoryGirl.create(:admin) }

    it "can pick out admin users" do
      expect(User.admin).to eq([admin])
    end

    it "can pick out non-admin users" do
      expect(User.admin(false)).to eq(users)
    end
  end

  context "division scope" do
    let(:division) { FactoryGirl.create(:division) }
    let(:unassigned) { FactoryGirl.create(:user, division: nil) }
    let(:assigned) { FactoryGirl.create_list(:user, 2, division: division) }
    let(:manager) { FactoryGirl.create(:manager, division: division) }

    it "can find people not assigned to a division" do
      expect(User.division(false)).to eq([unassigned])
    end

    it "can find people who belong to a particular division" do
      expect(User.division(division)).to eq([assigned, manager].flatten)
    end
  end
end
I

As an aside, I don't like this pattern on my admin scope:
Ruby code:
  scope :admin, ->(admin = true) { admin ? where(role: 'a') : where.not(role: 'a') }
I can do something like this, but I think it's trading dryness for readability:
Ruby code:
  scope :admin, ->(admin = true) { where("role #{ '!' unless admin}= 'a'") }
There's got to be a better way that I'm not seeing.

Peristalsis
Apr 5, 2004
Move along.
I keep running into the same problem with many-to-many relationships in Rails, and I've never really found a great solution. It deals with storing meaningful data in join tables, and I'm hoping there's something obvious I'm missing, not that it's just a limitation of rails.

Here's a stripped down version of the current iteration:

code:
class ClassA
  has_many => :class_a_class_b
  has_many :class_b, :through => :class_a_class_b
end

class ClassB
  has_many => :class_a_class_b
  has_many :class_a, :through => :class_a_class_b
end

class ClassAClassB
  belongs_to :class_a
  belongs_to :class_b

  # database table class_a_class_b contains the following fields
  # class_a_id
  # class_b_id
  # some_other_attribute 
end

def some_method
  a = classA.new
  b = classB.new

  # If I do this, then there's no classA_classB object to populate with some_other_attribute, at 
  # least without saving first (which really isn't an option)
  a.class_bs << b
  puts a.class_bs.size                                                       # output = 1
  a.class_a_class_bs.size                                                    # output = 0; same 
                                                                             #  for b.class_a_class_b.size
  a.class_a_class_bs.first.some_other_attribute = "abc"                      # throws exception; 
end

def try_different_approach
  a = classA.new
  b = classB.new
  link = ClassAClassB.new
  link.class_a = a
  link.class_b = b
  link.some_other_attribute = "abc"
  a.class_a_class_bs << link
  b.class_a_class_bs << link

  # This works, but now I don't have the direct link between A and B, and doesn't inform
  # the main objects of the links at all.
  puts a.class_bs.size                                                      # output = 0
  puts a.class_a_class_bs.size                                              # output = 0
  # etc.
  # In this case, I'm also concerned about whether the link will even be saved when I save a or b.
end

def third_try
  a = classA.new
  b = classB.new
  link = ClassAClassB.new

  link.class_a = a
  link.class_b = b
  link.other_attribute = "abc"
  a.class_a_class_bs << link
  b.class_a.class_bs << link
  
  # Still doesn't hook up a -> b link, but at least is functional up to that point.
  puts a.class_a_class_bs.size                                              # output = 1
  puts b.class_a_class_bs.size                                              # output = 1
  puts a.class_bs.size                                                      # output = 0
  puts b.class_as.size                                                      # output = 0

  # However, even when I save a, it doesn't get the link to b without reloading.
  a.save
  puts a.class_bs.size                                                      # output = 0
  # Oddly, the other direction works fine.
  puts b.class_as.sizse                                                     # output = 1
  a.reload
  puts a.class_bs.size                                                      # output = 1
end

def desperate_attempt
  # Just hook everything up manually
  a = classA.new
  b = classB.new
  link = ClassAClassB.new
  link.class_a = a
  link.class_b = b
  link.other_attribute = "abc"
  a.class_a_class_bs << link
  b.class_a_class.bs << link
  a.class_bs << b
  b.class_as << a
  
  # That seems to work at first, but the link between a and b is actually separate from the explicit 
  # link object here.  So, when I save, I get this:
  a.save
  puts a.persisted?                                                         # output = true
  puts b.persisted?                                                         # output = true
  puts link.persisted?                                                      # output = true
  puts a.class_a_class_bs.size                                              # output = 2
end

So, is there a good way to do this for new records? I'd like to have confidence that when the clients use the returned objects I create, they can use the rails connections without reservation, but they also need to decide when (and whether) to save them to the database, so I can't do that for them.

Edit: If I could force the link between a and b to use the link object I've created, I think that would solve this. Is there a way to do something like
code:
a.class_b = b, :using => link
???

Peristalsis fucked around with this message at 19:46 on Feb 26, 2015

Chilled Milk
Jun 22, 2003

No one here is alone,
satellites in every home

Peristalsis posted:

I keep running into the same problem with many-to-many relationships in Rails, and I've never really found a great solution. It deals with storing meaningful data in join tables, and I'm hoping there's something obvious I'm missing, not that it's just a limitation of rails.

Here's a stripped down version of the current iteration:

code:
class ClassA
  has_many => :class_a_class_b
  has_many :class_b, :through => :class_a_class_b
end

class ClassB
  has_many => :class_a_class_b
  has_many :class_a, :through => :class_a_class_b
end

class ClassAClassB
  belongs_to :class_a
  belongs_to :class_b

  # database table class_a_class_b contains the following fields
  # class_a_id
  # class_b_id
  # some_other_attribute 
end

def some_method
  a = classA.new
  b = classB.new

  # If I do this, then there's no classA_classB object to populate with some_other_attribute, at 
  # least without saving first (which really isn't an option)
  a.class_bs << b
  puts a.class_bs.size                                                       # output = 1
  a.class_a_class_bs.size                                                    # output = 0; same 
                                                                             #  for b.class_a_class_b.size
  a.class_a_class_bs.first.some_other_attribute = "abc"                      # throws exception; 
end

def try_different_approach
  a = classA.new
  b = classB.new
  link = ClassAClassB.new
  link.class_a = a
  link.class_b = b
  link.some_other_attribute = "abc"
  a.class_a_class_bs << link
  b.class_a_class_bs << link

  # This works, but now I don't have the direct link between A and B, and doesn't inform
  # the main objects of the links at all.
  puts a.class_bs.size                                                      # output = 0
  puts a.class_a_class_bs.size                                              # output = 0
  # etc.
  # In this case, I'm also concerned about whether the link will even be saved when I save a or b.
end

def third_try
  a = classA.new
  b = classB.new
  link = ClassAClassB.new

  link.class_a = a
  link.class_b = b
  link.other_attribute = "abc"
  a.class_a_class_bs << link
  b.class_a.class_bs << link
  
  # Still doesn't hook up a -> b link, but at least is functional up to that point.
  puts a.class_a_class_bs.size                                              # output = 1
  puts b.class_a_class_bs.size                                              # output = 1
  puts a.class_bs.size                                                      # output = 0
  puts b.class_as.size                                                      # output = 0

  # However, even when I save a, it doesn't get the link to b without reloading.
  a.save
  puts a.class_bs.size                                                      # output = 0
  # Oddly, the other direction works fine.
  puts b.class_as.sizse                                                     # output = 1
  a.reload
  puts a.class_bs.size                                                      # output = 1
end

def desperate_attempt
  # Just hook everything up manually
  a = classA.new
  b = classB.new
  link = ClassAClassB.new
  link.class_a = a
  link.class_b = b
  link.other_attribute = "abc"
  a.class_a_class_bs << link
  b.class_a_class.bs << link
  a.class_bs << b
  b.class_as << a
  
  # That seems to work at first, but the link between a and b is actually separate from the explicit 
  # link object here.  So, when I save, I get this:
  a.save
  puts a.persisted?                                                         # output = true
  puts b.persisted?                                                         # output = true
  puts link.persisted?                                                      # output = true
  puts a.class_a_class_bs.size                                              # output = 2
end

So, is there a good way to do this for new records? I'd like to have confidence that when the clients use the returned objects I create, they can use the rails connections without reservation, but they also need to decide when (and whether) to save them to the database, so I can't do that for them.

Edit: If I could force the link between a and b to use the link object I've created, I think that would solve this. Is there a way to do something like
code:
a.class_b = b, :using => link
???

Have you tried futzing with #build? That should set up associations without persisting.
http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html

DONT THREAD ON ME
Oct 1, 2002

by Nyc_Tattoo
Floss Finder
Whenever I want strong guarantees about complex associations, I usually create a "manager" poro to deal with creating, persisting, and validating associated objects.

Peristalsis
Apr 5, 2004
Move along.

The Milkman posted:

Have you tried futzing with #build? That should set up associations without persisting.
http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html

I have not - I'll look into that, thanks.

I sort of got things working well enough for now just by explicitly constructing and populating the link objects, but anyone using that code is going to have to be aware that the top level voodoo (i.e. the a.class_bs as b.class_as links) just won't work until after saving the objects. If these build methods can set this up better in the future, that'd be sweet.

MALE SHOEGAZE posted:

Whenever I want strong guarantees about complex associations, I usually create a "manager" poro to deal with creating, persisting, and validating associated objects.

That's an interesting idea, but I'm not sure how it would work. Do you just have something that replicates the rails functionality that you feel is too complicated or unreliable? It's not something I want to retrofit into a bunch of code right now just to fix a medium-sized bug, but I'd like to hear more about it.

DONT THREAD ON ME
Oct 1, 2002

by Nyc_Tattoo
Floss Finder

Peristalsis posted:


That's an interesting idea, but I'm not sure how it would work. Do you just have something that replicates the rails functionality that you feel is too complicated or unreliable? It's not something I want to retrofit into a bunch of code right now just to fix a medium-sized bug, but I'd like to hear more about it.

Mainly I use it to escape from callback hell (esp after delete callbacks, shudder), but it also works nicely for creating and validating associations.
code:
      class Butt < ActiveRecord::Base
        has_many: :poops
      end 
      
      class Poop < ActiveRecord::Base
        belongs_to: :butt
      end 

      class ButtManager
        attr_reader :butt

        def initialize(butt:)
          @butt = butt
        end

        def go_to_bathroom
          poop = create_poop
          wipe_butt
          flush_toilet
          examine_poop(poop)
        end 
        
        def create_poop
          butt.poops.create
        end

        def flush_toilet
          begin 
            Toilet.flush
          rescue Toilet::ToiletTankNotReady
            # handle error
          end 
        end

        def wipe_butt
          fail "No TP in cache" if TP.get_from_cache.nil?
          # butt whiping code
        end 

        def examine_poop(poop)
          raise if poop.contains_blood? 
          # validates health of poop 
        end
      end
probably a better example here:

http://samuelmullen.com/2013/05/the-problem-with-rails-callbacks/

DONT THREAD ON ME fucked around with this message at 22:18 on Feb 27, 2015

Pardot
Jul 25, 2001




Should probably examine_poop(poop) before flush_toilet

MasterSlowPoke
Oct 9, 2005

Our courage will pull us through
It doesn't say the poop goes in the toilet. The flush is probably just so no one else knows what you're up to in the stall.

DONT THREAD ON ME
Oct 1, 2002

by Nyc_Tattoo
Floss Finder
This is why we have unit testing.

Chilled Milk
Jun 22, 2003

No one here is alone,
satellites in every home
Quick question, as I didn't get enough sleep last night

Is there a way to do this purely in AR/SQL?
code:
    firms.joins(:countries).reject { |firm| firm.countries.map(&:alpha2).include?(country_code) }
Trying to only get records where NONE of the has_many'd records match a condition

In my haze I initially wrote this
code:
    firms.joins(:countries).where.not('countries.alpha2' => country_code)
But obviously that will still grab any record where any of the children don't match. Not a huge deal but it's nice to avoid farting up AR Collections by running enumerable methods on them

xenilk
Apr 17, 2004

ERRYDAY I BE SPLIT-TONING! Honestly, its the only skill I got other than shooting the back of women and calling it "Editorial".
i guess it's not purely AR but couldnt you do

.where("countries.alpha2 NOT IN (?)", @country_exclude_list)

Thalagyrt
Aug 10, 2006

xenilk posted:

i guess it's not purely AR but couldnt you do

.where("countries.alpha2 NOT IN (?)", @country_exclude_list)

That should generate equivalent SQL to .where.not(countries: { alpha2: @country_exclude_list }).

Example:

2.1.3 :003 > puts Accounts::Account.joins(:solus_servers).where.not(solus_servers: { id: [1, 2] }).to_sql
SELECT "accounts_accounts".* FROM "accounts_accounts" INNER JOIN "solus_servers" ON "solus_servers"."account_id" = "accounts_accounts"."id" WHERE ("solus_servers"."id" NOT IN (1, 2))

Pollyanna
Mar 5, 2005

Milk's on them.


I wrote a script that tries to operate on a large subsection of the database, but it's super slow and non-performant and I was looking for a way to speed it up. Without getting into too much detail, I'm trying to get a list of "users" who have at least one of X associated model, and do NOT have any of Y associated model. I got up to something like this:

Ruby code:
# Users with at least one associated model X
User.include(:model_x).where(attribute: true).uniq
# adding .count to the end of that results in about half of all users
What I'm confused on is how to do the same for model Y, but in reverse: something that does NOT include model Y. Is there some sort of "negative" table I can make? I'm not entirely sure how join tables work for ActiveRecord associations, and originally I wanted to make a join table, then join that one with the table for model Y, but it got confusing really quickly.

MasterSlowPoke
Oct 9, 2005

Our courage will pull us through
Maybe go about it backwards? Something like

Ruby code:
ids = ModelY.select('DISTINCT user_id').pluck(:user_id) 
User.where.not(id: ids) 

Two simple queries instead of a join query. On phone so may be typos.

EVGA Longoria
Dec 25, 2005

Let's go exploring!

Pollyanna posted:

I wrote a script that tries to operate on a large subsection of the database, but it's super slow and non-performant and I was looking for a way to speed it up. Without getting into too much detail, I'm trying to get a list of "users" who have at least one of X associated model, and do NOT have any of Y associated model. I got up to something like this:

Ruby code:
# Users with at least one associated model X
User.include(:model_x).where(attribute: true).uniq
# adding .count to the end of that results in about half of all users
What I'm confused on is how to do the same for model Y, but in reverse: something that does NOT include model Y. Is there some sort of "negative" table I can make? I'm not entirely sure how join tables work for ActiveRecord associations, and originally I wanted to make a join table, then join that one with the table for model Y, but it got confusing really quickly.

With SQL, this is accomplished with a left outer join:

SQL code:
select u.* from users u, inner join modelX x on x.user_id = u.id left outer join modelY on y.user_id = u.id where y.id is null
Left outer joins in ActiveRecord suck. Do it in 2 queries.

DONT THREAD ON ME
Oct 1, 2002

by Nyc_Tattoo
Floss Finder
Does anyone have a hard time using refinements in a meaningful way? I'm trying to fix some code. Ages ago, some knucklehead did this:
code:
class RestClient::Request
  def self.execute(args, &block)
     *a bunch of junk specific to this one module, now used anytime something calls RestClient.(post|get|put|etc)*
  end 
end 


The actual implementation of RestClient looks like:

code:
module RestClient
  def self.post(...)
      Request.execute(...)
  end 
  
  def self.get(...)
      Request.execute(...)
  end 

  etc 


I want to do something like:
code:
 
module RestClientExt 
  class RequestExt
    refine RestClient::Request.singleton_class do
      def execute(args, & block)
	 *overridden junk*
      end
    end
  end
  refine RestClient.singleton_class do
    using RequestExt

    def get(url, headers={}, &block)
      raise "Balls"      
      Request.execute(:method => :get, :url => url, :headers => headers, &block)
    end
    ...
  end 
end
This doesn't work, because you can't refine modules. I assume I could do something like
code:
module RestClientExt
   using Request Ext
end


But at that point, I'm back where I started: everything is being overridden globally. I mean, there are other ways to deal with this, but none of them are particularly nice.

kayakyakr
Feb 16, 2004

Kayak is true

EVGA Longoria posted:

With SQL, this is accomplished with a left outer join:

SQL code:
select u.* from users u, inner join modelX x on x.user_id = u.id left outer join modelY on y.user_id = u.id where y.id is null
Left outer joins in ActiveRecord suck. Do it in 2 queries.

They're not that bad. Don't want to pull up a AR console to test this, but you should be able to write inline joins similar to:
Ruby code:
User.joins("LEFT JOIN model_xes on users.id = model_xes.user_id").where("model_xes.id IS NULL")

Smol
Jun 1, 2011

Stat rosa pristina nomine, nomina nuda tenemus.
#eager_join instead of #includes uses left joins where possible.

duck hunt
Dec 22, 2010
I've been a Python developer for a long while, and I'm inheriting and taking on a lot of Ruby projects at work right now. We use Puppet extensively as well as other internal tools written in Ruby. Seems like there is a lot of overlap conceptually between Python and Ruby. Python meet ups have stupid names about snakes and Holy Grail this and that, while all the Ruby meet ups seem to happen on Tuesdays.

Can you guys recommend a book (I need to have pages) to help pick up Ruby? Otherwise I was just going to default to Oreilly.

semicolonsrock
Aug 26, 2009

chugga chugga chugga
I liked rails tutorial -- an ebook. Has links to other works as well.


Related question: I'm on my second Ruby project, and I realized this basically is just a a static site except for the contact form. Is there a good general approach to making heavily html/Css/JavaScript sites back ends in Ruby if you really don't need it to do much?

Of course I could just do it like normal, but wondering if there is a shortcut.

good jovi
Dec 11, 2000

'm pro-dickgirl, and I VOTE!

duck hunt posted:

I've been a Python developer for a long while, and I'm inheriting and taking on a lot of Ruby projects at work right now. We use Puppet extensively as well as other internal tools written in Ruby. Seems like there is a lot of overlap conceptually between Python and Ruby. Python meet ups have stupid names about snakes and Holy Grail this and that, while all the Ruby meet ups seem to happen on Tuesdays.

Can you guys recommend a book (I need to have pages) to help pick up Ruby? Otherwise I was just going to default to Oreilly.

Especially for someone coming from Python, I recommend Metaprogramming Ruby 2. It may sound kind of specific, but I'm assuming you don't need to know how if statements work or whatever. The metaprogramming bits are most of what distinguishes Ruby from Python anyway.

xenilk
Apr 17, 2004

ERRYDAY I BE SPLIT-TONING! Honestly, its the only skill I got other than shooting the back of women and calling it "Editorial".

duck hunt posted:

I've been a Python developer for a long while, and I'm inheriting and taking on a lot of Ruby projects at work right now. We use Puppet extensively as well as other internal tools written in Ruby. Seems like there is a lot of overlap conceptually between Python and Ruby. Python meet ups have stupid names about snakes and Holy Grail this and that, while all the Ruby meet ups seem to happen on Tuesdays.

Can you guys recommend a book (I need to have pages) to help pick up Ruby? Otherwise I was just going to default to Oreilly.

Practical Object-Oriented Design in Ruby: An Agile Primer


Has a lot of praise....i also liked eloquent ruby

duck hunt
Dec 22, 2010

xenilk posted:

Practical Object-Oriented Design in Ruby: An Agile Primer


Has a lot of praise....i also liked eloquent ruby

Can I assume that by Eloquent Ruby, it is like the Eloquent Javascript book?

aunt jenkins
Jan 12, 2001

semicolonsrock posted:

Is there a good general approach to making heavily html/Css/JavaScript sites back ends in Ruby if you really don't need it to do much?

Methinks you're looking for Middleman.

KoRMaK
Jul 31, 2012



My code has two versions, a base branch and then a customized branch.

Currently, the customized one is just a superset of the base. I merge my master branch into the customized one periodically.

I'm trying to think of the right implemenation so that the customization code doesn't exist in any file in the base. Right now, if I make changes to customization branch I make them in the relevant file. This results in periodic conflicts and other weirdness that I want to eliminate.

A first iteration improvement to this could be to create a second file that corresponds to each existing file requiring additions, and put the customization code in there.

That's kind of lame though, so maybe I should make it as a gem or something. I think I need to look into packaging an app as a gem, and including it without using ruby gems.

semicolonsrock
Aug 26, 2009

chugga chugga chugga

aunt jemima posted:

Methinks you're looking for Middleman.

This is exactly what I was hoping for, thank you!

Adbot
ADBOT LOVES YOU

EVGA Longoria
Dec 25, 2005

Let's go exploring!

duck hunt posted:

I've been a Python developer for a long while, and I'm inheriting and taking on a lot of Ruby projects at work right now. We use Puppet extensively as well as other internal tools written in Ruby. Seems like there is a lot of overlap conceptually between Python and Ruby. Python meet ups have stupid names about snakes and Holy Grail this and that, while all the Ruby meet ups seem to happen on Tuesdays.

Can you guys recommend a book (I need to have pages) to help pick up Ruby? Otherwise I was just going to default to Oreilly.

The Ruby language itself is really easy. I'd recommend The Well-Grounded Rubyist for picking it up.

The Ruby community tends to embrace a lot of OO patterns and focus on a lot of "code smells". Check out https://github.com/bbatsov/ruby-style-guide for guidance on the stylistic things. It's almost universally adhered to in my experience, so it's good to know and it makes a lot of Ruby code feel very familiar even if you've never seen it before.

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