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
skidooer
Aug 6, 2001

Hop Pocket posted:

Is there a good best practice for this?
Write it in the public directory, under the same directory structure that your route implements.

So, if your application responds to, for example, /photos/2 -> write the file to RAILS_ROOT/public/photos/2.jpg. Apache will try to serve the file first. Only when it does not exist will it send the request up to the application.

Adbot
ADBOT LOVES YOU

skidooer
Aug 6, 2001
Is anyone here using a document-oriented database (such as CouchDB or ThruDB) with Rails? I've got some projects where SQL isn't the right tool for the job. There are several ActiveRecord-like abstractions (which I'd like to use) on the go, but they all seem to be in the early stages. So I'm also wondering which of those projects I should be focusing my attention on, if any.

skidooer
Aug 6, 2001

Pardot posted:

There was mention of Active Couch
That's for the link. That's definitely one of the more mature ones I have seen. But I'm not too keen on their API. And it doesn't look like it will even let me store hashes or arrays. Might be a good starting point for rolling my own, however.

skidooer
Aug 6, 2001
Well I went ahead and started creating yet another CouchDB library named ActiveCushion. I couldn't find one that worked the way I envisioned it, sticking to AR conventions as much as possible, so here we are. There's more work to do before it's ready for any kind of release, but I'm quite happy with the way it's shaping up.

Creating documents is not unlike doing so with ActiveRecord. There is, however, no schema. You're free to add whatever attributes you want. Validations will ensure input is sane.
code:
Person.create(:name => 'David Heinemeier Hansson', :age => 28, :aliases => %w(DHH Dave))
=> #<Person:0x2661d20 @attributes={"name"=>"David Heinemeier Hansson",
       "_rev"=>"724093250", "_id"=>"85A2D0B5E67FF94B284B3EEAA9D285D3", "type"=>"person",
       "aliases"=>["DHH", "Dave"], "age"=>28}>
CouchDB uses the concept of views for record retrieval. Javascript is the default language for creating views, and I've created a few examples in that language:
code:
all:
function(doc) {
	if (doc.type == "person") {
		map(null, doc);
	}
}

by_name:
function(doc) {
	if (doc.type == "person") {
		map(doc.name, doc);
	}
}

by_alias:
function(doc) {
	if (doc.type == "person") {
		for (var i = 0; i < doc.aliases.length; i++) {
			map(doc.aliases[i], doc);
		}
	}
}

by_age:
function(doc) {
	if (doc.type == "person") {
		map(doc.age, doc);
	}
}
To query one of those views in ActiveCushion we use the familiar find_XXX-like methods.
code:
Person.find_all # Find all records
Person.find_by_name('David Heinemeier Hansson') # Find David Heinemeier Hanssons 
Person.find_by_alias('DHH') # Finds DHH aliases
Person.find_by_age(:startkey => 30, :endkey => 50) # Find people betwen the ages of 30 and 50
And just like ActiveRecord, one can reference a document by ID. Retrieving and manipulating values in the document also share the same behaviour as ActiveRecord.
code:
person = Person.find('85A2D0B5E67FF94B284B3EEAA9D285D3')
=> #<Person:0x265a840 @attributes={"name"=>"David Heinemeier Hansson", 
       "_id"=>"85A2D0B5E67FF94B284B3EEAA9D285D3", "_rev"=>"724093250",
       "type"=>"person", "aliases"=>["DHH", "Dave"], "age"=>28}>
person.name
=> "David Heinemeier Hansson"
person.aliases 
=> ["DHH", "Dave"]
person.company = '37signals'
=> "37signals"
person.save
=> true
Because CouchDB saves each revision of the document, we can also go back in time:
code:
Person.revisions('85A2D0B5E67FF94B284B3EEAA9D285D3').map do |r|
  Person.find('85A2D0B5E67FF94B284B3EEAA9D285D3', :rev => r).company
end
=> ["37signals", nil]

skidooer fucked around with this message at 23:15 on Feb 1, 2008

skidooer
Aug 6, 2001

drjrock_obgyn posted:

If it were me, I'd read up on the following:
You forgot the most important one of them all: Unit/functional/integration tests.

skidooer
Aug 6, 2001

Hop Pocket posted:

In your controller:

code:
def create_something
  if request.xhr?
    # the request was made using some sort of ajax black magic.
  end
end
Depending on what he is trying to do, respond_to is probably better suited for this job.
code:
def new
  @object = Object.new

  respond_to do |type|
    type.html do
      # Do your regular request specific stuff here
    end

    type.js do
      # Do your AJAX specific stuff here
    end

    type.xml { render :xml => @object.to_xml } # We'll do some XML for fun as well
  end
end

skidooer
Aug 6, 2001
Is anyone an expert with Ferret/acts_as_ferret?

I'm confused why
code:
Model.find_by_contents('field:"Some Value"')
returns no results.

However,
code:
query = Ferret::Search::PhraseQuery.new(:field)
query << "Some Value"
Model.find_by_contents(query)
returns the expected results. Note that "field" is an untokenized field.

I've gone through the source and Ferret's query parser builds, as far as I can tell, the exact same PhraseQuery object before it goes searching so I'm not seeing why there is a discrepancy.

Edit: Found it. The query parser builds the phrase query like this:
code:
query = Ferret::Search::PhraseQuery.new(:field)
query << "Some" << "Value"

skidooer fucked around with this message at 05:50 on Mar 7, 2008

skidooer
Aug 6, 2001

brae posted:

Also, what is wrong with a mongrel cluster and mod_proxy?
It requires administration. Passenger just works. Upload your application and you're done. At least that's what they claim.

skidooer
Aug 6, 2001
Another take:
code:
begin
  require 'fastercsv'
rescue LoadError
  require 'rubygems'
  require 'fastercsv'
end

class Person
  attr_accessor :id, :first_name, :last_name
  
  def initialize(id = nil, first_name = nil, last_name = nil)
    @id, @first_name, @last_name = id.to_i, first_name, last_name
  end
  
  def name
    "#{first_name} #{last_name}"
  end

  def username
    "#{first_name[0..0]}#{last_name}"
  end
  
  def email
    "#{username}@contoso.com"
  end
  
  def dn
    "CN=#{name},OU=Test OU,DC=contoso,DC=com"
  end
  
  def to_a
    [ dn, username, email, 512, 'user' ]
  end
  
  def map(&block)
    to_a.map(&block)
  end
end

FasterCSV.open('names.csv', 'w') do |csv|
  csv << %w(dn sAMAccountName userPrincipalName userAccountControl objectClass)
  File.open('names.txt').each do |record|
    csv << Person.new(*record.strip.split(/\s+/))
  end
end

skidooer
Aug 6, 2001

bag of a bee posted:

The form builder seems to only like dealing with a single object (just quotes, or just people, but not both).
You can use fields_for to specify an additional object.
code:
<% form_for @quote do |f| %>
	<%= f.text_field :quote %>
	
	<% f.fields_for :people do |n| %>
		<%= n.text_field :name, :index => 0 %>
		<%= n.text_field :name, :index => 1 %>
	<% end %>
	
	<%= submit_tag 'Add quote' %>
<% end %>
code:
class QuotesController < ApplicationController
  def new
    @quote = Quote.new
  end

  def create
    @quote = Quote.create(params[:quote])
  end
end
code:
class Quote < ActiveRecord::Base
  has_many :people
  
  def people_with_form_initialization=(people)
    people = people.values.map { |attributes| Person.new(attributes) } if people.is_a?(Hash)
    self.people_without_form_initialization = people
  end
  alias_method :people_without_form_initialization=, :people=
  alias_method :people=, :people_with_form_initialization=
end

skidooer
Aug 6, 2001

Rocko Bonaparte posted:

2. The server's understanding of the list removes that row. ... Really the server doesn't need to know that stuff.
If the server needs to know:
code:
<% content_tag_for(:tr, task) do %>
  <td>
    <%=h task.name %>
  </td>
  <td>
    <%= link_to_remote 'remove', :url => task_path(task), :method => :delete %>
  </td>
<% end %>
code:
class TasksController < ApplicationController
  def destroy
    @task = Task.find(params[:id])
    
    if @task.destroy
      render :update do |page|
        page.remove dom_id(@task)
      end
    end
  end
end
If it doesn't:
code:
<% content_tag_for(:tr, task) do %>
  <td>
    <%=h task.name %>
  </td>
  <td>
    <%= link_to_function('remove') { |link| link.remove(dom_id(task)) } %>
  </td>
<% end %>

skidooer
Aug 6, 2001

Rocko Bonaparte posted:

Edit: Just to get back to the core problem, I need the system--be it client or server--to not remove elements from the array when the page is first loaded. It should only happen when when the link is clicked.
I think we need to see some more code. What exactly is in this array?

skidooer
Aug 6, 2001

Rocko Bonaparte posted:

Right now the array is created in the controller:
The web is stateless. That array will be recreated on every page load, even if an element has been removed. I'm thinking that's not what you want at all. You will probably want to rethink your application design, but without changing what you have too much:

fermentables_controller.rb
code:
class FermentablesController < ApplicationController
  before_filter :set_fermentables
  
  def destroy
    fermentable = @fermentables[params[:id].to_i]
    @fermentables.delete(fermentable)
    
    render :update do |page|
      page.remove(fermentable.get_tag)
    end
  end
  
  private
    def set_fermentables
      @fermentables = session[:fermentables] ||= [
        Fermentable.new("6-row", 5, 2, 44, 1.50),
        Fermentable.new("Crystal 40L", 1, 40, 38, 2.25),
        Fermentable.new("Black Patent", 0.25, 400, 4, 2.33)
      ]
    end
end
index.html.erb
code:
<table>
  <%= render :partial => @fermentables %>
</table>
_fermentable.html.erb
code:
<tr id=<%= fermentable.get_tag %>>
  <td><!-- Not sure what prepend does --></td>

  <td><%= fermentable.substance %></td>
  <td><%= fermentable.quantity %></td>
  <td>lb</td>        
  <td><%= fermentable.lovlb %></td>
  <td><%= fermentable.SGlb %></td>
  <td><%= fermentable.costlb %></td>
	
  <td><%= link_to_remote 'Remove',
	          :url => fermentable_path(fermentable_counter),
	          :method => :delete %>
</tr>

skidooer
Aug 6, 2001

Cylon Dinner Party posted:

Can I inherit from a class defined in a module? ...
class Smsg < Message
class Smsg < ModuleName::Message ...

skidooer
Aug 6, 2001

Opius posted:

If it's not possible to break multiple levels, how should I go about dealing with nested loops and flow control?
The best way is to not introduce it in the first place.

From what you posted, this comes to mind:
code:
dirs.each do |dir|
  dir.reject { |d| d.something? }.each do |dir|
    ...
  end
  ...
end
Depending on what you are trying to do, it may or may not be the best structure to begin with.

skidooer
Aug 6, 2001

Carabus posted:

What is the best way to convert table attributes to a hash?
Depending on your table structure and what you are trying to do exactly, something like this might work:
code:
class Rating < ActiveRecord::Base
  belongs_to :user
  belongs_to :film
  
  def self.grouped_ratings
    find(:all, :include => [ :user, :film ]).inject({}) do |grouped_ratings,rating|
      (grouped_ratings[rating.user.name] ||= {}).merge!(rating.film.name => score)
    end
  end
end

skidooer
Aug 6, 2001

Strong Sauce posted:

Is there a site that discusses the changes between previous version of Rails and what Rails is at the moment?
http://ryandaigle.com/ is probably your best bet.

skidooer
Aug 6, 2001

Mr. Wynand posted:

hire a core guy
I don't think you need a core guy for something so simple. ;)

code:
class Foo < ActiveRecord::Base
  before_create :set_id
  
  def set_id
    self.id = rand(9999)
  end
end

skidooer
Aug 6, 2001

Plastic Jesus posted:

I found out that my ugly-looking current approaches are actually the fastest by a long shot:
It looks like you forgot to run the operation several times. You'll want to do that when benchmarking.

skidooer fucked around with this message at 16:58 on Jul 20, 2008

skidooer
Aug 6, 2001

GT_Onizuka posted:

Poking through the examples/API, I couldn't find a quick way to do something like document_body.gsub(blah, blah2), or even a way to get at the returned document.
code:
require 'webrick/httpproxy'

proxy = WEBrick::HTTPProxyServer.new(
    :Port => 8080,
    :ProxyContentHandler => lambda { |request,response|
      response.body.gsub!(%r{<a href=".*?">(.*?)</a>},
        '<a href="http://goatse">\1</a>')
    }
)

trap('INT') { proxy.shutdown }
proxy.start
Watch out for compressed content.

skidooer
Aug 6, 2001

Carabus posted:

I'd like to know if the method I have been using for constructing hashes from queries is particularly bad.
Perhaps it is because it is only an example, but there is just something about that method that is telling me that you are thinking about it the wrong way. As far as I can tell your example would be better described as:
code:
Profile.find(:all, :include => :fans)
I'm assuming your models look something like so:
code:
class Profile < ActiveRecord::Base
  has_many :favorites
  has_many :fans, :through => :favorites
end

class Favorite < ActiveRecord::Base
  belongs_to :profile
  belongs_to :fan
end

class Fan < ActiveRecord::Base
  has_many :favorites
  has_many :profiles, :through => :favorites
end

wunderbread384 posted:

The Rails folks don't believe in foreign keys
That's not surprising. Foreign keys don't really make any sense in ActiveRecord.

I'm actually having a hard time figuring out why you would want to use foreign keys if you are using ActiveRecord as intended. If you are not using ActiveRecord as intended, surely one of the other ORM libraries would be better suited for your needs?

skidooer
Aug 6, 2001

luminalflux posted:

Is it just me or is there a huge "don't trust the database" vibe coming from the Rails camp?
It's not a matter of trust. It basically boils down to the fact that SQL is the wrong tool for the job. The right tools, unfortunately, are still too immature for real-world use.

Things will get better. As those projects mature you'll see Rails move away from SQL. Those who wrote their applications properly will be able to migrate with ease. Those who decided to put all their faith in the database will be in for a world of hurt or stuck with SQL forever.

Using SQL to it's full potential has it's place; just not when using ActiveRecord.

skidooer
Aug 6, 2001

functional posted:

Either Array or Marshal should have a built in function that autodetects all of this and writes it out in a very compact form.
If size is your main concern, wouldn't you be better off writing your own file format? The flexibility of Marshal will require that it always contains more information than necessary for what you are trying to do.

However:
code:
class Float
  def self._load(value)
    value.unpack("G").first
  end
  
  def _dump(*args)
    [self].pack("G")
  end
end

skidooer
Aug 6, 2001

functional posted:

Ah, so this is how you would do it.
No, I would still go with a custom format. :)
code:
module FloatMarshal
  def self.dump(array)    
    header = array.map { |element| element.size }
    header.unshift(header.size)
        
    header.pack("NC*") + array.flatten.pack("G*")
  end
end
I'll leave the load method as an exercise for you.

skidooer
Aug 6, 2001

Freakus posted:

Is rails going to be fighting me a lot on this?
Rails, no. ActiveRecord, maybe.

What does your schema look like? If it's close to what ActiveRecord expects, you just have to apply additional configuration options to specify what is different. If your database is doing something completely different you might consider evaluating other ORM options (DataMapper, ruby-sequel, etc.) or writing your own database layer.

skidooer fucked around with this message at 21:53 on Oct 17, 2008

skidooer
Aug 6, 2001

Hop Pocket posted:

Confirming that GeoKit is a pretty good solution. Have used it on a couple of projects.
The API is pretty ugly, especially with the changes to AR in 2.1, but it seems to be the best pre-made solution going.

skidooer
Aug 6, 2001

jonnii posted:

I don't seem to get any response body back when I post with the format being xml.
That's because you're not responding to the format :xml in your controller. Change the format to 'xml' (string, not symbol) in your test and it should work.

skidooer
Aug 6, 2001

dustgun posted:

but I can't figure out the right incantation for has_many :through and whatnot to get back a list of the Nodes themselves.
If I understand your problem correctly, you are looking for something like this:
code:
class Node < ActiveRecord::Base
  has_many :up_links, :class_name => 'Link', :foreign_key => 'up'
  has_many :up_nodes, :through => :up_links, :source => :down_node
end

class Link < ActiveRecord::Base
  belongs_to :up_node, :class_name => 'Node', :foreign_key => 'up'
  belongs_to :down_node, :class_name => 'Node', :foreign_key => 'down'
end

skidooer
Aug 6, 2001

walnutz posted:

I don't know what I'm doing wrong. :(
Do you have at least the default route in your routes.rb file?

Also, that tutorial doesn't seem to follow any of the newer Rails 2.1 conventions. It looks like it was written for 1.0. I would be weary of picking up bad habits from it. Unfortunately, I cannot suggest a better one for you to follow.

skidooer
Aug 6, 2001

Nolgthorn posted:

That is false
Not exactly. There was a certain version of Rails that had a route reloading problem. But, if I recall correctly, that revision also contained a security problem, so nobody should be using it now anyway.

skidooer
Aug 6, 2001

Hammertime posted:

You also have to restart if you make any modification to files in lib.
No you don't, unless you explicitly require the file that is. But apparently 2.2 really does have a problem with routing to new controllers without a restart. I just encountered it.

skidooer
Aug 6, 2001

Hammertime posted:

Well, yes, but what's the point in having lib files if you don't require any of them?
Rails will load them automatically. You may have to specify additional load paths if your lib files are in a directory hierarchy.

skidooer
Aug 6, 2001
How do you guys do "admin sections" of an application? All of the solutions I have come up with / have seen leave a lot to be desired; either by way of duplication of efforts, ugly code, or what have you. There much be a better way.

skidooer
Aug 6, 2001

Hop Pocket posted:

That will take care of most of the duplication right off the bat.
The duplication I was referring to was how the admin and main site controllers end up being almost exactly the same, only different. Different enough that using one controller to serve both views doesn't work well either. Writing the application twice, so to speak, gets old. Maintaining the site twice is even worse.

mynameisntneo posted:

Is there a best way to do what I'm looking for?
You will want to use a before_filter.
code:
class MenuMemberController < ApplicationControllerr
  before_filter :set_menu
  
  def index
    @menu_members = @menu.menu_members.find(:all, :limit => 10)
  end
  
  private
    def set_menu
      @menu = Menu.find(params[:menu_id])
    end
end

skidooer fucked around with this message at 05:22 on Dec 4, 2008

skidooer
Aug 6, 2001

phazer posted:

I did have a working application before I deployed. In fact, it was working AFTER deployment until this restart issue.
Have you diffed the source on the server with the deployed revision? Perhaps a colon accidentally disappeared from a symbol, for example. Then, when you restarted your application the new code was loaded into memory and boom, your code was then broken.

skidooer fucked around with this message at 22:56 on Dec 10, 2008

skidooer
Aug 6, 2001

phazer posted:

I went to restart my app, and the mongrel.pid issue happened.
Run this:
code:
ps -A | awk '/mongrel/ {print $1}' | xargs kill
Start your Rails application(s) again.

skidooer
Aug 6, 2001
And what did you get when you started your application?

skidooer
Aug 6, 2001

phazer posted:

When I grep for a mongrel process, I get no results.
Try:
code:
gem pristine mongrel
And then start your application again.

skidooer
Aug 6, 2001

dustgun posted:

What I want is /person/:last_name/:first_name as a route, giving me person/schmoe/joe. Doing that requires url_for et al to look at the object I passed in beyond just taking the result from a to_param call.
You would have to make some pretty large changes to the current routing code to have it behave like you want. But you could always take a shortcut, like so:
code:
def url_for(options = {})
  if options.is_a?(Person) && !options.new_record?
    person_url(options.last_name, options.first_name)
  else
    super
  end
end

Adbot
ADBOT LOVES YOU

skidooer
Aug 6, 2001

phazer posted:

So can I make my application call that command?
code:
%x{convert x.psd x.jpg}
exec('convert', 'x.psd', 'x.jpg')
system('convert x.psd x.jpg')
`convert x.psd x.jpg`
To name a few.

skidooer fucked around with this message at 19:25 on Dec 17, 2008

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