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
Anveo
Mar 23, 2002

prom candy posted:

I found installing postgres with homebrew to be a breeze.

Does anyone know if there's a way to get Heroku to skip asset compilation if you haven't actually changed any assets? Or does it not matter because each push spins up a fresh dyno with no memory of past dynos?

Although this wouldn't work on Heroku, this might be useful to anyone else who wants to skip asset pre-compilation. Helpful since our compilation process takes 10-15 minutes :eng99:

code:
namespace :deploy do
  namespace :assets do
    task :precompile, :roles => :web, :except => { :no_release => true } do
      # If a REVISION file doesn't yet exist, trigger the asset build
      if capture("test -f #{deploy_to}/current/REVISION; echo $?").to_i > 0
        run %Q{cd #{latest_release} && #{rake} RAILS_ENV=#{rails_env} #{asset_env} assets:precompile}
      else
        from = source.next_revision(current_revision)
        if capture("cd #{latest_release} && #{source.local.log(from)} -- vendor/assets/ app/assets/ lib/assets/ | wc -l").to_i > 0
          run %Q{cd #{latest_release} && #{rake} RAILS_ENV=#{rails_env} #{asset_env} assets:precompile}
        else
          logger.info "Skipping asset pre-compilation because there were no asset changes"
        end
      end
    end
  end
end
This also won't work if you have changed the location of your manifests.yml path. We do something like:

code:
config.assets.manifest = Rails.root
The reason you might do that is so you can rollback and have the manifest.yml that was associated with the deploy you are reverting to... which means you need to build a manifest each deploy and not have it in a shared location. Go asset pipline! :suicide:

Adbot
ADBOT LOVES YOU

Sharrow
Aug 20, 2007

So... mediocre.
I'm writing an app that's basically a debugging proxy for a third-party web service. You change your endpoint to my app, it forwards the API request and returns the response, logs traffic, and allows you to fiddle with the data.

One thing I'd like to add though, is a user-definable set of rules or assertions that each request is checked against. For instance, you might create a new rule of request[:version] > 4 and it would flag any requests using an old API version.

Or if request[:method] == "foo" then request[:bar] == "baz" to highlight that you've not included recommended parameters.

There'd be a web interface that you could define these, and they'd be loaded and run against each request that came through.

Is there some sort of DSL and instance_eval trickery I can do here (I've never really looked at DSLs before), or is this more parser territory?

Physical
Sep 26, 2007

by T. Finninho
Is there a way to do a scope that uses a related model in the search?

I have
Ruby code:
class ModelA
	belongs_to :ModelB

	scope :search_item, lambda {|q| where(["#{self.ModelB.title} LIKE (?)", "%#{q}%"])}
end
ModelB has a title that I want to search by. That self.ModelB.title line doesn't work obviously. Is there a way to do it?

manero
Jan 30, 2006

Physical posted:

Is there a way to do a scope that uses a related model in the search?

I have
Ruby code:
class ModelA
	belongs_to :ModelB

	scope :search_item, lambda {|q| where(["#{self.ModelB.title} LIKE (?)", "%#{q}%"])}
end
ModelB has a title that I want to search by. That self.ModelB.title line doesn't work obviously. Is there a way to do it?

Yeah, actually first do something like this:

Ruby code:
class ModelB
  def self.search_by_title(title)
    where("title LIKE ?", "%#{title}%")
  end
end
Then chain it off a merged scope with the associated model:

Ruby code:
class ModelA
  belongs_to :model_b

  def self.search_item(item)
    includes(:model_b).merge(model_b.search_by_title(item))
  end
end
Edit: I think the includes() and merge() call are actually not needed, you might even be able to just do:

Ruby code:
model_b.search_by_title(item)

manero fucked around with this message at 16:23 on Jul 30, 2012

Physical
Sep 26, 2007

by T. Finninho
Thank you very much! That's close but I need the ModelA object returned, not the ModelB one. I need to find out which ModelA is linked to ModelB. Seems pretty simple using methods in the model, but I was hoping there was some super slick way to do it using a scope.

prom candy
Dec 16, 2005

Only I may dance
code:
class ModelA
  belongs_to :model_b
  scope :search_title, lambda { |query| joins(:model_b).where("model_bs.title LIKE (?)", "%#{query}%") }
end
Does that do what you want?

Physical
Sep 26, 2007

by T. Finninho

prom candy posted:

Ruby code:
class ModelA
  belongs_to :model_b
  scope :search_title, lambda { |query| joins(:model_b).where("model_bs.title LIKE (?)", "%#{query}%") }
end
Does that do what you want?
:tviv: Yep thank you! That little line taught me a couple things too, that I can use the other model in the search clause, but I have to pluralize it (probably because that is what the actual SQL table is called) and that joining the table can use the :identifier. And it's pretty painless. I was pretty close, headed in the right direction, thanks for bringing me across the finish line.

Pardot
Jul 25, 2001




Physical posted:

:tviv: Yep thank you! That little line taught me a couple things too, that I can use the other model in the search clause, but I have to pluralize it (probably because that is what the actual SQL table is called) and that joining the table can use the :identifier. And it's pretty painless. I was pretty close, headed in the right direction, thanks for bringing me across the finish line.

If you want to step it up a bunch, go from using LIKE to great built-in fulltext search. Pivotal released a gem that makes using the tsvector stuff easy with rails: https://github.com/casecommons/pg_search

Oh My Science
Dec 29, 2008

Pardot posted:

If you want to step it up a bunch, go from using LIKE to great built-in fulltext search. Pivotal released a gem that makes using the tsvector stuff easy with rails: https://github.com/casecommons/pg_search

This is awesome.

prom candy
Dec 16, 2005

Only I may dance
So using the pg_search gem what would be the best way to also include my permissions? For example, say I have two models that I want to search, a page model with a secured flag and a post model that has active/inactive scopes:

code:
class Page < ActiveRecord::Base
  def self.viewable_by(user)
    user ? self : where("secured = ?", false)
  end
end

class Post < ActiveRecord::Base
  def self.active
    now = lambda { Time.now }.call
    where("published = :true AND post_at >= :now", {:true => true, :now => now})
  end
end
If I'm running pg_search on these models for a multisearch is there a way that I can selectively apply these scopes before the sql is run? If not, is there another way to do this, or am I going to have to check visibility/permissions on each individual record that's returned?

Abrahamsen
Jul 1, 2009
Hello thread, forgive me if I missed the answer to my question on an earlier page.

I am a complete newbie, I am on windows 7 I have used the http://railsinstaller.org/ to install rails. Where do I go from here? I tried watching Michael Hartl's tutorial (and reading it) series but I keep getting into what I assume is dependency/gem version problems around chapter 3 so I have given that up for now.

How do I gain the knowledge to actually start developing cool web applications?

prom candy
Dec 16, 2005

Only I may dance
This isn't what you want to hear but developing on Windows is going to be a constant uphill battle for you. I would almost go so far as installing a Ubuntu VM for your web dev work, the Rails/Ruby dev community just does not seem to care as much about Windows/Windows users.

Abrahamsen
Jul 1, 2009

prom candy posted:

This isn't what you want to hear but developing on Windows is going to be a constant uphill battle for you. I would almost go so far as installing a Ubuntu VM for your web dev work, the Rails/Ruby dev community just does not seem to care as much about Windows/Windows users.

I was afraid this would be the answer but I expected it. Now to decide I'd it its worth the trouble (going Ubuntu)

prom candy
Dec 16, 2005

Only I may dance
Getting Ubuntu set up is a snap these days. If you're getting into web development being familiar with a non-Windows platform is going to be a huge boon to you, unless you want to go the full MS route (C#, IIS, cell phone clipped to your belt)

Jam2
Jan 15, 2008

With Energy For Mayhem
code:
def self.viewable_by(user)
    user ? self : where("secured = ?", false)
  end
what does this do?

Abrahamsen
Jul 1, 2009

prom candy posted:

Getting Ubuntu set up is a snap these days. If you're getting into web development being familiar with a non-Windows platform is going to be a huge boon to you, unless you want to go the full MS route (C#, IIS, cell phone clipped to your belt)

Is running a VM with Ubuntu similar enough to the real deal?

Cock Democracy
Jan 1, 2003

Now that is the finest piece of chilean sea bass I have ever smelled

Abrahamsen posted:

Is running a VM with Ubuntu similar enough to the real deal?
Yep.

A MIRACLE
Sep 17, 2007

All right. It's Saturday night; I have no date, a two-liter bottle of Shasta and my all-Rush mix-tape... Let's rock.

Jam2 posted:

code:
def self.viewable_by(user)
  user ? self : where("secured = ?", false)
end
what does this do?

returns self unless user evaluates falsy, otherwise returns all records of self's class that have a secured value of false in the database

prom candy
Dec 16, 2005

Only I may dance
The idea is to return a chainable relation. I don't think what I'm trying to do is possible though.

Jam2
Jan 15, 2008

With Energy For Mayhem
But it doesn't actually check the user against anything?

prom candy
Dec 16, 2005

Only I may dance
It's checking it against nil, it's basically a really quick way to check if someone is logged in.

A MIRACLE
Sep 17, 2007

All right. It's Saturday night; I have no date, a two-liter bottle of Shasta and my all-Rush mix-tape... Let's rock.

prom candy posted:

It's checking it against nil, it's basically a really quick way to check if someone is logged in.

Just a thought, couldn't you skip this step by integrating CanCan or the like?

prom candy
Dec 16, 2005

Only I may dance
I have CanCan integrated already, I'm not really clear on how it would integrate with pg search though, except maybe by checking can?(:read) on each. If you had another idea I'm definitely interested.

Physical
Sep 26, 2007

by T. Finninho
I have a model that is to have a "related_items" relationship so I can do @mymodel.related_items

And also, I'd like to go the other way, so that I can take an object that has been identified as a related_item for other objects and do @myitem.objects_that_relate_to_me

The related item can be of multiple types, so I have a table setup with: related_item_id, related_item_type

I have the second part, but not the first part. I thought the :through directive would do it for me but I couldn't quite understand how I could set the related_item_type field or even read it later.

Is this possible using a :through model and I just gave up too soon?

Physical fucked around with this message at 14:13 on Aug 6, 2012

prom candy
Dec 16, 2005

Only I may dance
Does this answer your question? http://stackoverflow.com/questions/1683265/activerecord-has-many-through-and-polymorphic-associations

Physical
Sep 26, 2007

by T. Finninho
At a glance it looks like it might. The source_type field is helpful. Now lets say I want to store some arbitrary data in along with it in another field, how do I do that without having to do a create()?

prom candy
Dec 16, 2005

Only I may dance
Check out the guide on has_many :through relationships http://guides.rubyonrails.org/association_basics.html#the-has_many-through-association

Physical
Sep 26, 2007

by T. Finninho
Been reading it the last couple days, doesn't really tell me how to store extra data at creation time. Like the "appointment_date" field. They don't give an example on how to populate it.

prom candy
Dec 16, 2005

Only I may dance
You can just deal with the join table like any other model. Can you post some of your actual code, it might make it easier for us to help you.

Cocoa Crispies
Jul 20, 2001

Vehicular Manslaughter!

Pillbug

Physical posted:

Been reading it the last couple days, doesn't really tell me how to store extra data at creation time. Like the "appointment_date" field. They don't give an example on how to populate it.

Ruby code:
@appointment = current_patient.appointments.create physician: @selected_physician,
                                                   appointment_date: Date.parse('Apr. 20, 2069')

kitten smoothie
Dec 29, 2001

Anyone use Tire/ElasticSearch? I'm having some trouble doing pagination with multiple models.

Suppose I have models Client and Contract.

in my search controller method:
Ruby code:
query = params[:q]
search = Tire.search ['clients','contracts'], :load=>true, :page=> params[:page], :per_page=> 10 do
      query {string query}
    end
    
@results = search.results
and in the view
code:
<% @results.each do |r| %>
	<div class="row-fluid">
	<%= render r %>
	</div>
<% end %>

<%= paginate @results %>
Kaminari's pagination widget seems to work correctly, and displays the pager control as though things were pagianted properly. But the result set has all the results and is not just limited to the particular page, so the pager is usless and I get all the results on one page.

If I were to do something like this, though, and only focus on the one model, it works fine.
Ruby code:
@results = Client.search query, :load=>true, :page=> params[:page], :per_page=> 10
Am I doing something wrong or am I looking at a bug in Tire?

Physical
Sep 26, 2007

by T. Finninho

Cocoa Crispies posted:

Ruby code:
@appointment = current_patient.appointments.create physician: @selected_physician,
                                                   appointment_date: Date.parse('Apr. 20, 2069')
I was hoping to avoid using the create method but I guess it doesn't matter because it's not that much more than using "<<". Thank you very much. Was this suggested to you by any reading materials? If so can you link me? If you just kind of picked up on it on your own then congratulations, as obvious as these things seem after they have been pointed out I find myself unable to get there on my own.

New question related to polymorphic relationships, I have (made the mistakeof putting) the source_id and source_type fields in the same model of ModelC. Can the source and source_type be in the same table?
Ruby code:
class ModelC < ActiveRecord::Base
  has_one :item, :source => :source_id, :source_type => :source_type
end
edit: It seems it is possible http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html I think the code would as follows. The field name is "source" so it might get a little confusing to differential between source column and the :source and :source_type directives.

Ruby code:
class ModelC < ActiveRecord::Base
  has_one :source, :polymorphic => true
end

class ModelD < ActiveRecord::Base
  has_one :model_c, :as => :source
end
What if the field in the model definition didn't match up to the names of the columns in the table? Lets says I wanted to do something like this

Ruby code:
class ModelC < ActiveRecord::Base
  has_one :origin, :polymorphic => true
end
How would I tell it that the origin id and type is in source_id and source_type?

Physical fucked around with this message at 15:42 on Aug 7, 2012

prom candy
Dec 16, 2005

Only I may dance
You're probably going to run into problems if you actually name your field "source."

Does anyone know how to do an initial data insert for pg_search? I've added it to my project but my project has a ton of content already. Do I just need to loop over everything and save?

Jam2
Jan 15, 2008

With Energy For Mayhem
I've run into an architectural challenge. I'm hoping some second opinions will help me organize this logic.

My sites naked and www domains serve as entrypoints to numerous subdomains through which users interact with the site.

models/region.rb
Ruby code:
class Region < ActiveRecord::Base
  ...
end
lib/subdomain.rb
Ruby code:
class Subdomain
  def self.matches?(request)
    request.subdomain.present? && request.subdomain != 'www' &&
      Region.active_subdomain?(request.subdomain)
  end
end
I've placed logic about which subdomain a user has visited in a class called Locale.

lib/locale.rb
Ruby code:
class Locale

  # must provide session and request options
  def initialize(options = {})

    raise ArgumentError, 'No session provided' if options[:session].nil?
    raise ArgumentError, 'No request provided' if options[:request].nil?

    @region = case
    when Subdomain.matches?(options[:request])
      region = Region.find_by_subdomain(options[:request].subdomain)
      options[:session][:region_id] = region.id
      region # @region = region
    else
      Region.find_by_id(options[:session][:region_id]) || Region.new
    end

  end

  # return the region object associated with this Locale
  def region
    @region
  end

  def valid?
    @region.present?
  end

end
Then I place a before_filter in Application controller so Locale gets set up for every request.

Ruby code:
class ApplicationController < ActionController::Base
  include LocaleHelper
  protect_from_forgery

  prepend_before_filter :set_locale

  helper_method :within_region?
  helper_method :initialize_data_for_listings_form

  def set_locale
    @locale = Locale.new(request: request, session: session)
  end

  def within_region?
    Subdomain.matches?(request)
  end

  # send return visitors on their way
  def redirect_return_visitors
    return if @locale.nil? || @locale.valid? == false
    r = Region.find_by_id(@locale.region.id)
    saved_region = url_for subdomain: r.subdomain,
      controller: 'listings', action: 'index'

    redirect_to saved_region if return_visitor?
  end

  def render_404(message = "page not found")
    raise ActionController::RoutingError.new(message)
  end

  def reject_unless_current_user_is_admin
    render_404 unless current_user.is_admin?
  end

  def reject_unless_current_region_set
    # TODO to root
    redirect_to '/' if @locale.region == nil
  end

  def initialize_data_for_listings_form(controller)
    models = Category.major.sort_by! { |c| c.name }
    cvar = :@major_categories
    controller.instance_variable_set(cvar, models)

    regions = Region.find(@locale.region.id).leaves
    regions.sort_by! { |r| r.name }
    rvar = :@regions
    controller.instance_variable_set(rvar, regions)
  end

end
Here is the locale functionality in use.

locale in use dot rbs (some html.hamls)
Ruby code:
        - if within_region?
          = @locale.region.name
Ruby code:
    %title= "sitename #{@locale.region.name}"
Ruby code:
    #region-step.step
      %h1 Where in #{@locale.region.name}?
      %hr
      = f.association :region, as: :select, label: false,
        input_html: { id: 'select-region'},
        collection: @regions
      %hr
Ruby code:
  def initialize_data_for_listings_form(controller)
    models = Category.major.sort_by! { |c| c.name }
    cvar = :@major_categories
    controller.instance_variable_set(cvar, models)

    regions = Region.find(@locale.region.id).leaves
    regions.sort_by! { |r| r.name }
    rvar = :@regions
    controller.instance_variable_set(rvar, regions)
  end
the problem is, the first time someone visits the site, they haven't yet visited a particualr region, so @locale.region is nil. This causes application errors.

I've considered extending application_controller with a module called LocaleHelper to address this.

lib/locale_helper.rb
Ruby code:

def current_region_name
  if @locale.present? && @locale.region.present?
    @locale.region.name
  else
    ''
  end
end

def current_region_id
  if @locale.present? && @locale.region.present?
    @locale.region.id
  else
    ''
  end
end
I'm sure there's a better way to accomplish this. Any ideas?

manero
Jan 30, 2006

Jam2 posted:

the problem is, the first time someone visits the site, they haven't yet visited a particualr region, so @locale.region is nil. This causes application errors.

code:
snip
I'm sure there's a better way to accomplish this. Any ideas?


You should use the Null Object pattern here -- always initialize a locale, even if they haven't chosen one. You could have a NullLocale class that you can ask for its name:

Ruby code:
class NullLocale < Locale
  def region_name
    ""
  end

  def region_id
    ""
  end
end
Now you don't even have to check to see if it's there. Use the one you load from the request, or just return an instance of NullLocale. Implement the same interface in the Locale class. You could even have a "current_locale" method do the work of choosing which one to use.

That saves you from digging too deeply into the object itself.

Physical
Sep 26, 2007

by T. Finninho
Ugh finally. After like 40 minutes of toying around I finally understand how to get this setup. the "as" keyword goes on the item side and on the association declaration to the join table. To put it in human, english thoughts "[current model] has_many related_items. related_items knows [current model] :as [related_item]"

Then on the through table when you say

Ruby code:
belongs_to :related_item, polymorphic => true
You are setting up an alias or handle for other things to communicate in as. The polymorphic part also informs the model that there is a *_id and *_type column. This is where the alias referred to by the afore mentioned :as statement is declared.

On one side of the relationship you must declare the :source => :alias_from_through_model and the :source_type => "String that you want in the item_type column"

prom candy posted:

You're probably going to run into problems if you actually name your field "source."

Does anyone know how to do an initial data insert for pg_search? I've added it to my project but my project has a ton of content already. Do I just need to loop over everything and save?
Sorry I can't help you, I'm not familiar with that gem. In regards to my question just change "source" to "item" to avoid conflicts. Would it work then? I think it might if I understand what the :as keyword and :polymorphic are doing.

e: Ooooooh! This one is even easier. You don't even have to put a relationship on the other models. The only one that needs it is the one with the polymorphic columns (*_id, *_type). And I did it with the column name as source too and there are no conflicts. Neat!

Ruby code:
class ModelA < ActiveRecord::Base
	belongs_to :source, :polymorphic => true
end
The :polymorphic keyword essentially informs the model that the table for it will have an id and type column. This concept is really clicking for me. Too bad I programmed most of this stuff with the :through infrastructure set up but used them inefficiently with things like "thing = item.related_item_type.constantize.find(item.related_item_id)"

What if I want to change the names of the columns used? Let's say the column names are item_id and thing_type. It's stupid, but its just a hypothetical that I'm curious if there is an answer.

Physical fucked around with this message at 20:40 on Aug 7, 2012

Jam2
Jan 15, 2008

With Energy For Mayhem

manero posted:

You should use the Null Object pattern here -- always initialize a locale, even if they haven't chosen one. You could have a NullLocale class that you can ask for its name:

Ruby code:
class NullLocale < Locale
  def region_name
    ""
  end

  def region_id
    ""
  end
end
Now you don't even have to check to see if it's there. Use the one you load from the request, or just return an instance of NullLocale. Implement the same interface in the Locale class. You could even have a "current_locale" method do the work of choosing which one to use.

That saves you from digging too deeply into the object itself.

So my before_filter should look something like this then?
Ruby code:
  def set_locale
    locale = Locale.new(request: request, session: session)
    @locale = case
              when locale.valid?
                locale
              else
                NullLocale.new
              end
  end
Or should this be abstracted away somewhere deeper?

manero
Jan 30, 2006

Jam2 posted:

So my before_filter should look something like this then?
Ruby code:
  def set_locale
    locale = Locale.new(request: request, session: session)
    @locale = case
              when locale.valid?
                locale
              else
                NullLocale.new
              end
  end
Or should this be abstracted away somewhere deeper?

I'd say make a specific constructor in Locale (or just override initialize). Have it return either a legit Locale, or an instance of a NullLocale. Push it all down into the model. The controller/helper code should be clueless.

Jam2
Jan 15, 2008

With Energy For Mayhem

manero posted:

I'd say make a specific constructor in Locale (or just override initialize). Have it return either a legit Locale, or an instance of a NullLocale. Push it all down into the model. The controller/helper code should be clueless.

I don't full understand. Is this the idea?

Ruby code:
class Locale

  # must provide session and request options
  def self.new(options = {})
    initialize_region(options) || NullLocale.new
  end

  # return the region object associated with this Locale
  def region_name
    @region.name
  end

  def region_id
    @region.id
  end

  def valid?
    true
  end

  private
  def initialize_region(options = {})
    raise ArgumentError, 'No session provided' if options[:session].nil?
    raise ArgumentError, 'No request provided' if options[:request].nil?

    @region = case
              when Subdomain.matches?(options[:request])
                region = Region.find_by_subdomain(options[:request].subdomain)
                options[:session][:region_id] = region.id
                region # @region = region
              else
                Region.find_by_id(options[:session][:region_id]) || Region.new
              end
  end

end

class NullLocale < Locale

  def region_name
    ''
  end

  def region_id
    ''
  end

  def valid
    false
  end

end

Jam2 fucked around with this message at 21:07 on Aug 7, 2012

Adbot
ADBOT LOVES YOU

manero
Jan 30, 2006

Jam2 posted:

I don't full understand. Is this the idea?

Yeah, that's the basic idea. You'll want initialize_region() to return nil in the case that you couldn't initialize the region properly (so your || NullLocale.new falls through properly), but that's the general idea.

Write tests! :science:

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