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

Nolgthorn posted:

You could do it like this but you're not supposed to
Well, if we're going to throw MVC to the wind...
code:
class Person < ActiveRecord::Base
  Builder::XmlMarkup.new.table do |table|
    find(:all, :order => 'lastname').each do |person|
      table.tr do
        table.td person.firstname
        table.td person.lastname
        table.td person.age
      end
    end
  end
end
Also, the SVN RSS feed (http://dev.rubyonrails.org/log/?limit=100&mode=stop_on_copy&format=rss) is a beautiful thing for keeping up with what is changing. No Rails developer should be without it.

skidooer fucked around with this message at 05:59 on Aug 9, 2007

Adbot
ADBOT LOVES YOU

skidooer
Aug 6, 2001

legalcondom posted:

This is exactly why I don't understand what the big deal about ruby is.
In most popular web development languages you write a program. In Ruby you write programs that write programs. The latter lends itself very well to web development. The only problem I see is that these Ruby idioms usually are not apparent to the Ruby novice, so they end up writing PHP-like code, only with Ruby syntax, and fail to see what the big deal really is.

skidooer
Aug 6, 2001

Scarboy posted:

If I get no result how do I call ActiveRecords base method_missing to do whatever it has to do or raise exceptions?
Call super to pass it up to the superclass. For example:
code:
def method_missing(symbol, *args, &block)
  whatever_you_need_to_do(symbol, *args, &block) || super
end

skidooer
Aug 6, 2001

Jackdonkey posted:

Whatever I'll get it someday.
code:
find(:all, :select => 'items.*',
     :joins => 'INNER JOIN users ON items.qc_user_id = users.id',
     :order => 'users.name')

skidooer
Aug 6, 2001

vg8000 posted:

Yeah but when you try to re-migrate from scratch, you're using [latest model] versus [older database migration] that may not be compatible anymore. He said this himself in his post.
You can redefine the model within the migration to solve that problem. Not exactly DRY, but a lot better than trying to manage versioned models in an automated fashion.
code:
class MigrationName < ActiveRecord::Migration
  class User < ActiveRecord::Base; end
end
Although I have to agree with Scarboy. If you're starting a fresh database use db:schema:load instead of starting from migration version 1.

Mr. Wynand posted:

sooner or later an if RAILS_ENV=="development" is going to slip in your code somewhere...
Why not just use a mock object?

skidooer fucked around with this message at 22:06 on Aug 10, 2007

skidooer
Aug 6, 2001

nebby posted:

Rails is a great webapp framework ruined by a lovely O/R framework.
I fail to see how one library can ruin another. ActiveRecord is not a required dependency. You can use whatever persistence layer you want.

skidooer
Aug 6, 2001

vg8000 posted:

Are there any other ORMs for Ruby besides those two?
There is also ruby-sequel. I don't really see what's so terrible about ActiveRecord though.

skidooer
Aug 6, 2001

MrSaturn posted:

well the problem with that call is that I'm in a room, and I have a valid reference to a house, but not to a user. so the :include => :user part wouldn't work, right?
Is this what you're trying to do?
code:
@user = Room.find(1).user
@user = House.find(1).user
@house = User.find(1).houses.create(params[:house])
@house.rooms.create(params[:room])
...etc...
code:
class Room
  belongs_to :house
  delegate :user, :to => :house
end

class House
  belongs_to :user
  has_many :rooms
end

class User
  has_many :houses
end

skidooer
Aug 6, 2001

MrSaturn posted:

yeah, that's kinda like it, though the syntax is a bit different because of hobo. it turns out my problem was a mound of different things, but the eventual syntax is this:

House.find(:first,:conditions=>[ "user_id = ?", user['user_id']])
In that case, I think you'll find this syntax is preferable:
code:
user.houses.find(:first)
 

quote:

out of curiosity, would I be better of replacing my belongs_to :user to a delegate? I've never used delegate.
Delegate just passes the message along. Essentially the same as writing:
code:
def user
  house.user
end
You probably don't want to replace a belongs_to with a delegate, but it's hard to say for sure without seeing it in context.

skidooer
Aug 6, 2001

MrSaturn posted:

It looks like I have to set some keyword for my cookie? Where and how do I do that?
A secret is required to generate an integrity hash for cookie session data. Use config.action_controller.session = { :session_key => "_myapp_session", :secret => "some secret phrase" } in config/environment.rb ;)

In other words, stick that line in the config section of your environment file. And change the key and secret values.

skidooer
Aug 6, 2001

roop posted:

Should I be combining the two above into one Model?
Kind of.

code:
class Team < ActiveRecord::Base
  has_many :participants
  attr_accessor :participant
  after_create :create_participants

  protected
    def create_participants
      participants.create(participant)
    end
end
code:
class TeamController < ApplicationController
  def create
    @team = Team.create(params[:team])
  end
end
code:
<% form_for :team, :url => teams_path do |f| %>
  <%= f.text_field :name %>
  <% f.fields_for :participant, Participant.new do |p| %>
    <%= p.text_field :name %>
  <% end %>
<% end %>
You'll probably want to write a much more robust model than that, but that's the basics. Note that the FormBuilder::fields_for method doesn't exist in 1.2, so you'll have to either add it yourself or move to edge.

skidooer fucked around with this message at 15:16 on Sep 11, 2007

skidooer
Aug 6, 2001

shopvac4christ posted:

What I'm trying to say is, why can't we have something along the lines of a deployments directory, that has deploy.rb's and subdirectories for all the applications we can deploy, which is completely unrelated to any local checked out copies of the source?
There's no reason why you couldn't do that. But considering that you're most likely going to want to keep the deploy file in version control, and you're going to want to check out the latest version of the source to run your test suite before deployment, keeping it as part of the application seems much more convenient to me.

skidooer
Aug 6, 2001

Hop Pocket posted:

What is the rails equivalent of a Quartz scheduler? I want something that will execute periodic jobs on the development/production servers.
Backgroundrb should fit the bill.

skidooer
Aug 6, 2001

atastypie posted:

I've always used

if @posts.nil? || if @posts.blank?
Your nil? check is redundant considering that blank? will return false if @posts is nil.

skidooer
Aug 6, 2001

Nolgthorn posted:

Is "blank?" what I am looking for?

I've always wanted something similar to @posts.title.empty_or_nil? In case the value being returned in the database is blank instead of nil for whatever reason, as nil.empty? would return an error.

Or.. does it? I'm getting confused.
Yes, object.blank? is equivalent to object.nil? || object.empty? Note that it's provided by ActiveSupport should you find yourself trying to use it outside of Rails.

skidooer
Aug 6, 2001

zigb posted:

Documentation. For gently caress's sake people, at least pretend like you're trying.
I suppose it might be a little daunting for the first time user. Honestly, I prefer to just read the source code anyway. Why bother with someone's english interpretation when you've got perfectly good source code to go by?

quote:

Server restarts. Our dev server is also, unfortunately, a production server for different apps in other languages. (don't blame me, I didn't do it :().
Is there any reason why you aren't developing on your local system? That is the Rails way.

quote:

Added/Edited something in the /lib path? Restart Apache. This makes any sort of iterative development of libs/mixins a huge pain in the rear end.
Unless you were using an ancient version of Rails, or running in production mode, that isn't true.

quote:

SQL Logging. Didn't work, even when I triple checked that the /tmp and /log dirs had proper permissions and that logging wasn't disabled in the environment files.
SQL logging doesn't happen in production unless you increase the log level. I've never seen it not work in development mode.

quote:

Not that I mind writing SQL, but I prefer to write it in one large understandable chunk instead of splitting it up into mini-clauses, like :conditions => "[some sql]", :order => "[some sql]", etc.
They're split up so things like scopes can be applied. I suppose AR could implement an SQL parser so that you can write whole SQL statements, but that seems like a lot of effort for little benefit.

Although it's rare that I find myself writing any SQL at all. I'll assume it's your use of a schema that wasn't designed for ActiveRecord that you had to write a lot of SQL to work around those limitations.

quote:

Most find queries that required a JOIN or two had to be written using find_by_sql.
find(:all, :joins => 'INNER JOIN bar ON bar.foo_id = foo.id')

quote:

Controller initialize function. It causes "Internal Server Error" when I put simple logic in there. Example (this kills rails): "if null != params[:a_param]; end". Same thing when I put the logic in question into a method and call it from initialize. No problems when I call that same method from one of the actions instead.
params is your problem here. It's nil. There is no [] method defined for NilClass. If you're doing what I think you are, you want to use a before_filter instead.

quote:

Different expectations for overriding ActionController::initialize and ActiveRecord::initialize.
The odds that you'd ever want to overwrite initialize in either class are extremely low. I can't think of any reason why you'd ever want to, really.

quote:

While the above issues were all annoyances, the need to restart Apache after making code, not configuration, changes is the kicker.
Run your application as a CGI process and it will work just as you desire. But I'm sure you'd rather have the performance benefits of not reloading your code every time in production.

skidooer fucked around with this message at 17:50 on Nov 20, 2007

skidooer
Aug 6, 2001

wunderbread384 posted:

Why read source code when you have a perfectly good English explanation to go by?
I find the code much easier to read and understand. I almost always ignore the documentation and dive right into the code. I guess I'm just weird. :unsmith: I will resort to the documentation if the code is poorly written, but I wouldn't lump Rails into that category.

skidooer fucked around with this message at 20:08 on Nov 20, 2007

skidooer
Aug 6, 2001

spacepirate posted:

Fantastic, self explaining code right there, especially since create_or_update is not listed in the Rails API.
From that snippet I know that saving the object will create a new database record or update an existing record if one already exists. What more can be said about it?

skidooer
Aug 6, 2001

zigb posted:

Rails 1.2.3 on Ruby 1.8.5. We're currently supporting another RoR app written by a different dev on this same box, so neither of those are subject to change. Also, I'm running in development mode.
It should load them then. Let the app automatically include the files if you aren't already. Manually loading them may cause problems.

zigb posted:

If there's some way AR would make this statement go away, I want to know about it!
Without knowing more about the problem at hand, I'd probably do something along these lines:
code:
class Payment < ActiveRecord::Base
  def self.find_subscriptions(start_date, end_date, options = {})
    options.reverse_merge!(
      :select     => 'payments.*',
      :joins      => construct_subscription_joins
      :conditions => construct_subscription_conditions(start_date, end_date)
    )
    
    find(:all, options)
  end
  
  def self.contruct_subscription_joins
    %(
      LEFT JOIN schools ON payments.school_id = schools.id
      LEFT JOIN costs ON payments.cost_id = costs.id
      LEFT JOIN database_informations ON costs.database_information_id 
         = database_informations.id
    )
  end
  
  def self.construct_subscription_conditions(start_date, end_date)
    statement = %(
      schools.school_name LIKE '% school redacted' AND
      library NOT LIKE '%library also redacted%' AND
      costs.subscription_start >= ? AND costs.subscription_end <= ?
    )
                  
    [ statement, range.first, range.last ]
  end
end

@payments = Payment.find_subscriptions(@start_date, @end_date,
      :order => 'school_name, library, database_name')
Not exactly beautiful yet, but it's a start. You can easily get rid of the SQL in construct_subscription_joins method, but I'll leave that as an exercise for the reader.

At very least take the SQL out of your controllers. The only place that belongs is in the model.

zigb posted:

Taking your second statement first, is a controller's initialize method not the best place to put code that I want executed for each action?
You want to use a before_filter for that.
code:
class MyController < ApplicationController
  before_filter :require_admin
  before_filter :initialize_some_object, :only => [ :index, :show ]

  private
    def require_admin
      redirect_to login_url unless current_user.admin?
    end

    def initialize_some_object
      @some_object = SomeObject.find(params[:some_object_id]
    end
end
And there are similar filters in ActiveRecord.

zigb posted:

You're saying that params is unavailable/nil in a controller's initialize method? Any specific reason why?
Yes. I'm guessing that it initializes the controller object before it sets the params, but I haven't read the code (or read the documentation :cool: ) to verify that suspicion.

skidooer fucked around with this message at 23:35 on Nov 20, 2007

skidooer
Aug 6, 2001
You can assign the category_id field instead:
code:
<%= f.collection_select [b]:category_id[/b], @categories, :id, :name %>
Or if you're feeling real adventurous, you could change the model to do what you want.
code:
class Event < ActiveRecord::Base
  belongs_to :category
  
  def category_with_id_assignment=(category_id)
    category = case category_id
    when String, Fixnum
      Category.find(category_id)
    else
      category_id
    end
    
    self.category_without_id_assignment = category
  end
  alias_method :category_without_id_assignment=, :category=
  alias_method :category=, :category_with_id_assignment=
end
Remember that the user can enter any value they want for the category ID. It doesn't have to be a valid ID. So if you do directly assign the category_id into the database you run the risk of not having a valid association. By the same token, if the users are only allowed to select from a subset of categories, they can still pick from all of the categories without other checks and balances. So these are things that you must take into consideration when deciding how you're going to implement it.

skidooer fucked around with this message at 19:20 on Nov 21, 2007

skidooer
Aug 6, 2001

Hop Pocket posted:

I have one more question. I'm writing my own form builder, and I want all of my form fields to go inside of a <table>.
code:
class EventFormBuilder < ActionView::Helpers::FormBuilder
  def inside_table(&block)
    @template.concat('<table>', block.binding)
    block.call
    @template.concat('</table>', block.binding)
  end
end

skidooer
Aug 6, 2001

MrSaturn posted:

ah I got it working now, I just set it up under a new controller
Any reason why you didn't just include it in your index method?

code:
class BlogpostsController < ActionController::Base
  def index
    @blogposts = Blogpost.find(:all, :order=> "id DESC")

    respond_to do |type|
      type.html
      type.rss do
        render_without_layout
        headers["Content=Type"] = "application/xml; charset utf-8"
      end
    end
  end
end
Which, assuming you're using RESTful routes on that resource, will give you the URL http://host/blogposts.rss

skidooer
Aug 6, 2001
The discussion in the PHP thread about not putting any logic in the templates got me thinking. Would the template be better off separated from the view in Rails? I can imagine a RJS-like DSL for implementing the views. Something like the following:

View:
code:
unless @results.empty?
  @results.each do |result|
    page.insert :bottom, :results, page['/results/result'].yield(result)
  end

  page.hide :no_results
else
  page.hide :results
end
Template:
code:
<div id="no_results">
  <p>You have no results</p>
</div>

<div id="results">
  <div class="result">
    <p><%= result.name %></p>
  </div>
</div>
I'm not convinced it's better, but I do like some of the aspects of it. Thoughts?

skidooer
Aug 6, 2001

poemdexter posted:

I want the group table to have a 'creator' attribute that holds the user id from a session.
code:
class GroupsController < ApplicationController
  def create
    @group = current_user.groups.build(params[:group])    
    redirect_to groups_url if @group.save
  end
  
  private
    def current_user
      @current_user ||= User.find(session[:user_id])
    end
end

MonkeyMaker posted:

Anyone know of a quick/easy way to provide 'validates_X'-style validation on non-model checks? Like if a .find comes up blank, show an error/alert, instead of having to code that exception explicitly every time?
I guess you could do something along the lines of the following. I don't find it all that appealing, personally.
code:
class GroupsController < ApplicationController
  def index
    @groups = Group.find(:all)  
    validates_presence_of @groups
  end
  
  private
    def validates_presence_of(collection)
      # Handle the failure however you see fit
      raise ActiveRecord::RecordNotFound if collection.blank?
    end
end

skidooer fucked around with this message at 09:04 on Dec 4, 2007

skidooer
Aug 6, 2001

poemdexter posted:

This was the simplest way to go about it. Thanks. I have no idea what everyone else's code does, but I'm still new to both Ruby and the Rails gem.
I would still recommend going with the association proxy. It's the Rails way.

Based on the information you have given, I'm assuming your models look something like this:
code:
class User < ActiveRecord::Base
  has_many :groups, :foreign_key => :creator
end

class Group < ActiveRecord::Base
  belongs_to :user, :foreign_key => :creator
end
Now, in your controller you'd write something like:
code:
@group = logged_in_user.groups.build(params[:group])
which will give you the same result as this:
code:
@group = Group.new(params[:group])
@group.creator = logged_in_user.id
without putting database specific details (i.e. the id method) into your controller.

skidooer
Aug 6, 2001

Lamont Cranston posted:

I can't figure out how to do this in REST with map.resource.
:id doesn't necessarily have to be the ID of the record. You can do something like this:
code:
map.resources :users

def show
  @user = User.find_by_permalink(params[:id]) || User.find(params[:id])
end

<%= link_to h(user.name), user_path(user.permalink) %>
If you're dead set on using :user instead of :id, just define an additional route.
code:
map.resources :users
map.named_user 'user/:user', :controller => 'users', :action => 'show'

<%= link_to h(user.name), named_user_path(user.permalink) %>

skidooer
Aug 6, 2001

Hop Pocket posted:

You can also use content_for to supply extra information to your layout.
I like this method. Except I'd add a helper method for setting the title so that the templates aren't so cluttered with huge content_for blocks.

Something like:
code:
def title(title)
  content_for(:title) { title }
end

SeventySeven posted:

What would be the sanest way to add a "global" variable accessible by all controllers/views in an app?
Global as in a constant, or something you want to set on each load, like so?
code:
class ApplicationController < ActionController::Base
  before_filter :set_some_variable

  private
    def set_some_variable
      @variable_accessible_to_controllers_and_views = Model.find(:first)
    end
end

skidooer fucked around with this message at 17:37 on Dec 5, 2007

skidooer
Aug 6, 2001

Nolgthorn posted:

I'm at a loss as to how to put code safely after calling permission_required in my controller, without worrying about it getting executed anyway after the user is redirected.
If you're dead set on that API, you could raise a permission denied exception in your permission_required function and rescue it outside of the controller method. Although I'm wondering about how clear it will be to anyone else who may be working on your code in the future, although I guess it's no worse than the magic that happens when ActiveRecord::RecordNotFound is raised.
code:
class ActionController::Base
  class PermissionDenied < ActionControllerError; end
  
  def perform_action_with_permission_exceptions
    perform_action_without_permission_exceptions
  rescue PermissionDenied
  end
  
  alias_method_chain :perform_action, :permission_exceptions
end

skidooer fucked around with this message at 19:47 on Dec 6, 2007

skidooer
Aug 6, 2001

Hop Pocket posted:

Any ideas?
If I'm understanding you correctly, you want to specify the select statement as well.
code:
:select => 'events.*'
Also, as a style note, you should move most of those details into the model. That stuff doesn't belong in the controller.

skidooer
Aug 6, 2001

asveepay posted:

Soooo...how many other people are really unhappy with the complete lack of documentation/guidance with 2.0?
There's really nothing in 2.0 that's groundbreaking for someone who has already been using Rails. Most of the new features were already being used by most people through their respective plugins in 1.2. 2.0 just brings them into core. If you've been following Ryan's Scraps and/or the development feed you'll already be well versed in the changes.

But I believe that people who are just trying to learn Rails now are probably suffering from the problems you mentioned. For whatever reason, the whole community Rails once had that would help in this area seemed to die out around the 1.1 release. But I guess as a community project, anyone can step in and provide what is missing if they feel it's a problem.

skidooer
Aug 6, 2001

Al Azif posted:

Are there any guides for moving an application from 1.2 to 2.0 yet?
Run your test suite and fix anything that fails. Unless you've been monkeying with the Rails internals, or using deprecated methods (which you would have seen warnings for in the logs), you probably won't have to do anything.

skidooer
Aug 6, 2001

Grob posted:

And I was saying I'm not aware of a way to do:
How about something like this?
code:
def visual_effect_with_callback_generation(name, id = nil, options = {})
  options.each do |name,value|
    options[name] = "function() { #{JavaScriptGenerator(@context, &value)} }" if value.is_a?(Proc)
  end

  visual_effect_without_callback_generation(name, id, options)
end
alias_method_chain :visual_effect, :callback_generation

page.visual_effect :blind_down, 'id', :afterFinish => lambda { |after|
  after.visual_effect :blind_up
  after.hide :element
}
It's untested, but you get the idea.

skidooer fucked around with this message at 04:53 on Dec 17, 2007

skidooer
Aug 6, 2001

Trabisnikof posted:

mongrel_rails start -d will start it in the background, then mongrel_rails stop will stop the server. Or mongrel_rails restart will reload it. This is of course with mongrel_rails, but that's cause its awesome.
Or you can use the old fashioned & operator.
code:
$ script/server &
$ fg
^C
code:
$ mongrel_rails start &
$ fg
^C

skidooer
Aug 6, 2001

Hop Pocket posted:

Does anyone know how to get the current session id?
code:
session.session_id

skidooer
Aug 6, 2001

blargle posted:

I may have missed it in this thread, but does anyone know if Ruby 2.0 has addressed the performance issues?
Don't quote me because I can no longer find the source, but I seem to recall looking at some benchmarks where YARV blew PHP away.

Edit: YARV is in Ruby 1.9 by the way, whose release just happens to have been announced today.

skidooer fucked around with this message at 05:38 on Dec 26, 2007

skidooer
Aug 6, 2001

Heffer posted:

Is there an api for the map object and what functions I can call on it?
You can call whatever you want. Whatever method name you chose will be used to generate the named route methods. For example: map.foo 'a/long/path/to/foo/:id' will create foo_path, foo_url, etc. that you can then use in your app like: <%= link_to 'Foo', foo_path(@foo) %> or redirect_to foo_url(@foo).

The special cases are map.resources, which is explained here, and map.connect which works the same as the named routes above, but doesn't define the helper methods.

Heffer posted:

Ruby has terrible API docs.
routes.rb itself should tell you everything you need to know. But yeah, I find it's easier to just jump into the source. It's a pretty easy read.

skidooer fucked around with this message at 22:46 on Dec 28, 2007

skidooer
Aug 6, 2001

Heffer posted:

It doesnt seem to be spelled out what actions it looks for or what paths it creates.
Actually it does, in the API docs, at the aforementioned link. It's quite detailed and seems to answer all of your questions.

skidooer
Aug 6, 2001

SeventySeven posted:

What's the quickest way I can get tagging support back without loving with my app too much?
Probably switching to a join model, or re-implementing push_with_attributes yourself. Neither method should be all that difficult to make happen.

skidooer
Aug 6, 2001

SeventySeven posted:

But what happens when you want to, say, roll the app out and freeze the schema? Is there a way you can roll all your migrations in to one and then start writing new migrations?
The migrations are rolled into schema.rb. You'll use that (via: rake db:schema:load) to deploy your cold database. From that point forward you'll rely on the migrations to make incremental changes. So yes, if you are undoing a previous change, you still want to write a new migration.

SeventySeven posted:

Or what if you need to make large scale changes like I do?
How often do you really need to make large changes to the schema? :psyduck:

SeventySeven posted:

I guess how I can see it would make an environment with several devs easier.
Migrations work better with just one developer, actually. Although there are some plugins that aim to improve them for multiple developers.

Adbot
ADBOT LOVES YOU

skidooer
Aug 6, 2001

SeventySeven posted:

Is there an easy way to test ActionMailer or am I going to have to wait until this hits the production server?
http://manuals.rubyonrails.com/read/chapter/64

If you want to actually deliver the message:
code:
config.action_mailer.perform_deliveries = true
But personally, for the number of times I want to send the message, I find it's easier to just copy the output from the logs straight into an SMTP session.

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