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
Physical
Sep 26, 2007

by T. Finninho
What is the difference between the model version of changes? and the ActiveRecord version?

I have found very little on this one http://ar.rubyonrails.org/classes/ActiveRecord/Dirty.html#M000291

But have found pretty thorough documentation on this one
http://api.rubyonrails.org/classes/ActiveModel/Dirty.html


Oh wtf I am stupid, they are the same thing. What is the deal with that first URL though? Its like a derelict help site. Was it for an older version of RoR? What does that AR mean?

e2: If you go to the root page http://ar.rubyonrails.org/ it seems pretty dedicated to ActiveRecord. So ar = ActiveRecord? I tried replacing "ar." with "ac." for ActionController but it doesn't give me a page. Meh oh well.

derp3: The first page says "last updated 2008." Welp...

Physical fucked around with this message at 19:31 on Apr 16, 2012

Adbot
ADBOT LOVES YOU

asveepay
Jul 7, 2005
internobody
Try: http://api.rubyonrails.org/

prom candy
Dec 16, 2005

Only I may dance
Look for dates on everything you read about Rails. If something is from earlier than 2010 I would be wary of it because Rails 3 changed a lot. It's a good idea to google "<my search terms> Rails 3" or "<my search terms> 2011..2012"

Another mistake I frequently made as a Ruby/Rails newbie was Googling for how to do something in Rails when I really should have been looking for how to do it in Ruby.

Physical
Sep 26, 2007

by T. Finninho
I have a before_save callback running on a model. How do I access what normally is contained in "params" from inside this before_save method?

prom candy
Dec 16, 2005

Only I may dance
You don't, your model doesn't and shouldn't know what's going on in a GET or POST request. What are you trying to do?

Physical
Sep 26, 2007

by T. Finninho
I am trying to write down who the current user is (via the current_user variable in controllers). I am making a changes model/controller that creates a record in the changes table for every item that gets changed.

Geez that doesn't really sound helpful maybe the code will be more explanatory
code:
class Exercise < ActiveRecord::Base
before_save :mark_changes

def mark_changes
    #create a new entry for each hash
    @changes = self.changes
    @changes.each do |k, v|
      Change.create({ :item_type => self.class.to_s,
                      :item_id => self.id,
                      #:version
                      :field_name => k,
                      #:change_by => self.user_id, #<!!!!!!==== I want to store current_user here
                      :change_date => Time.now.to_datetime,
                      #:section
                      #:subsection
                      :action => "Edit",
                      :old_value => v[0],
                      :new_value => v[1]
                       })
    end
        
  end
end
The only path I see as of now, and it is one I don't want to take, is to create a new field on the exercise table/model and save the user id "change_by" in the actual Exercise model whenever there is an update, just to pass it to the changes model.

enki42
Jun 11, 2001
#ATMLIVESMATTER

Put this Nazi-lover on ignore immediately!
Personally, I think the best way to solve stuff like that is add an updated_by to the model in question. It's useful to know who the last person that changed something was without needing to consult a history table, and it makes grabbing the user who changed something in a before_save easy.

If you really don't want to add that column to the database, it's still totally possible to add a plain old attr_accessor to a model in Rails and use that for the before_save. Then you'll have the value available in the model but it won't be saved to the DB.

Also, I'd probably set up those changes as an association and build them rather than create them in the before_save. Right now that wouldn't work for a new record.

Physical
Sep 26, 2007

by T. Finninho
Thanks I'll try that attr_accessor method and see how it goes.

enki42 posted:

Also, I'd probably set up those changes as an association and build them
http://guides.rubyonrails.org/association_basics.html is what you are talking about right?

Can you elaborate by what you mean by "build them"? Is "build them" a RoR term or something that means other than "to write the code for"?

enki42 posted:

Right now that wouldn't work for a new record.

gently caress da' new records.
But no really, we don't care about new records on this object so its fine for now.

Cocoa Crispies
Jul 20, 2001

Vehicular Manslaughter!

Pillbug

enki42 posted:

Also, I'd probably set up those changes as an association and build them rather than create them in the before_save. Right now that wouldn't work for a new record.

I'd be tempted to invert it and have an ExerciseChange model that then updates the Exercise model as appropriate.

prom candy
Dec 16, 2005

Only I may dance

Physical posted:

Can you elaborate by what you mean by "build them"? Is "build them" a RoR term or something that means other than "to write the code for"?

In think in this case he means create a new object. In Rails build is used to initialize (but not save) a child record.

code:
  class Person < ActiveRecord::Base
    has_many :cats
  end

  class Cat < ActiveRecord::Base
    belongs_to :person
  end

  person = Person.find(20)
  cat = person.cats.build(:fluffy => true)
  cat.person_id   # Will return 20
  cat.id               # Will return nil as the cat has not been saved
If you want to initialize the record and save it immediately you can use .create instead of .build

code:
  person = Person.find(20)
  cat = person.cats.create(:fluffy => true)
  cat.person_id   # Will return 20
  cat.id               # Will return an integer assuming the cat record is valid and it saved

enki42
Jun 11, 2001
#ATMLIVESMATTER

Put this Nazi-lover on ignore immediately!
I'm saying use changes.build. You're doing it in a before_save filter anyway, so you might as well let Rails handle saving the change models for you. Plus if there was ever a case in the future where a change might be invalid, you could move your change building to a before_validate and let the change validation be dealt with by the parent model.

Plus if an excercise model doesn't save for whatever reason (either a bug or an honest-to-god business rule that your change code isn't aware of), you don't have any ghosted change models around that don't represent an actual change. I could be wrong on this, but I think that it might even be transactional if everything is contained within one save.

enki42 fucked around with this message at 13:21 on Apr 19, 2012

enki42
Jun 11, 2001
#ATMLIVESMATTER

Put this Nazi-lover on ignore immediately!

BonzoESC posted:

I'd be tempted to invert it and have an ExerciseChange model that then updates the Exercise model as appropriate.

From the looks of it it's a polymorphic relationship between changes and whatever, and figuring out a way to represent that RESTfully in controllers that doesn't seem completely crazy is making my head hurt.

Cocoa Crispies
Jul 20, 2001

Vehicular Manslaughter!

Pillbug

enki42 posted:

From the looks of it it's a polymorphic relationship between changes and whatever, and figuring out a way to represent that RESTfully in controllers that doesn't seem completely crazy is making my head hurt.

The ExerciseChange model doesn't have to be persisted, it can just manage creating an Exercise and the appropriate Change. Representing it RESTfully is trivial at that point.

Physical
Sep 26, 2007

by T. Finninho
Do you guys have any preferred gems for versioning/change logs? Stuff like this for example https://github.com/airblade/paper_trail

Physical fucked around with this message at 13:19 on Apr 20, 2012

asveepay
Jul 7, 2005
internobody

Physical posted:

Do you guys have any preferred gems for versioning/change logs? Stuff like this for example https://github.com/airblade/paper_trail

I attempted to insert paper_trail into a project at work but it doesn't seem to handle habtm associations very well (which is what I was attempting to track). I ended up just implementing a new join model with a separate model that tracks who made the changes.

Physical
Sep 26, 2007

by T. Finninho

asveepay posted:

I attempted to insert paper_trail into a project at work but it doesn't seem to handle habtm associations very well (which is what I was attempting to track). I ended up just implementing a new join model with a separate model that tracks who made the changes.
Can you elaborate on what it failed to do? And did you keep using paper_trail? Is the problem with the habtm is that it just won't "reify" them? I'm not so concerned with that, I just want all my changes to my models to be documented.

Physical fucked around with this message at 16:21 on Apr 20, 2012

Unixmonkey
Jul 3, 2002

Physical posted:

Do you guys have any preferred gems for versioning/change logs? Stuff like this for example https://github.com/airblade/paper_trail

I use vestal_versions https://github.com/laserlemon/vestal_versions, and like it.

Physical
Sep 26, 2007

by T. Finninho
I just spent some time over the weekend getting a has_man :through problem for paper_trail working. It was alot of fun. The biggest problem was that I made a typo and did a collection.to_s ==iId.to_s and it was causing things to not work right for like 2 hours until I realized my mistake.

Ahh the pleasures of wasting time during the weekend.

I'm proud of myself :smug:

8ender
Sep 24, 2003

clown is watching you sleep
If only I had paper_trail back at my previous job. We were wrestling with versioning like that using Java and never really got anywhere. Almost want to print out the github page and send it to my previous boss.

asveepay
Jul 7, 2005
internobody

Physical posted:

Can you elaborate on what it failed to do? And did you keep using paper_trail? Is the problem with the habtm is that it just won't "reify" them? I'm not so concerned with that, I just want all my changes to my models to be documented.

Basically what we wanted to do was take a model "Job" which habtm "permissions" and track who made changes and approve those changes. Because a user could submit multiple changes at once, having the approval keep track of which permissions were and were not approved, who submitted them, and when, was just too much for simple versioning, so I abandoned it pretty quickly and created a join model with an associated approval model which was a lot more one-to-one for the permission and the approver.

For different types of changes I'm sure it would have been useful, but not for that one.

Physical
Sep 26, 2007

by T. Finninho
I have about 4 methods that are pretty much copy and paste. How can I add these to my models like how I can do "has_paper_trail" or "inherit_resources" and write the code for it. What is that? A module seems to require the "include" keyword?

It's not as simple as making a module and then making that module have a "def has_my_module" is it?

Here is my module:
code:
module ApprovalLogModule
  
  class ActiveRecord::Base
    def self.has_approval_log
      include ApprovalLogModule
      Rails.logger.info("From approval log!")
    end    
  end  

  def current_version
   last_approval.blank? ?  0 : last_approval.version
  end

  def last_approval
   approvals.last
  end

  def approvals
   approvals = Approval.where("item_type LIKE ? AND item_id = ?",  self.class.to_s, self.id.to_s ).order("version")
  end  
    
end
I feel like I'm pretty close as ab "include ApprovalLogModule" works, but I'd like to change that to "has_approval_log".

Physical fucked around with this message at 20:18 on Apr 23, 2012

prom candy
Dec 16, 2005

Only I may dance
The essence of it is that you define some methods in a module, and then include that module in your class. What you're talking about is most often shipped around as a gem/plugin, so this would probably be a good read: http://guides.rubyonrails.org/plugins.html

However it's as simple as creating a module in lib/

code:
module MyModule
  def do_a_thing
    puts "I did a thing."
  end
end
and then requiring and including that module in your model:

code:
require 'my_module'
class MyModel < ActiveRecord::Base
  include MyModule
end
Instances of MyModel now have access to the do_a_thing method.

Physical
Sep 26, 2007

by T. Finninho
I was after the niffty one liner that doesn't use "include." I got it now though, I looked at how paper_trail and inherit_resources did it and now I got my own working! Here it is, it is for models. I just add "has_approval_log" to a model and bam it starts working!

code:
module ApprovalLogModule
  
  class ActiveRecord::Base
    def self.has_approval_log(base)
      include ApprovalLogModule
      Rails.logger.info("From approval log!")
    end   
    
    has_approval_log(self) 
  end
  
  def approve(user_name)
    app =  Approval.create({ :item_type => self.class.to_s,
                      :item_id => self.id,
                      :approval_date => Time.now.to_datetime,
                      :approved_by => user_name,
                      :version => current_version + 1
                    })
    #app.approval_file.  --SAVE APPROVED PDF
  end

  def current_version
   last_approval.blank? ?  0 : last_approval.version
  end

  def last_approval
   approvals.last
  end

  def approvals
   approvals = Approval.where("item_type LIKE ? AND item_id = ?",  self.class.to_s, self.id.to_s ).order("version")
  end  
    
end
edit: after a restart it stopped working! I have to do has_approval_log(self) in my model now. What gives? How do I get it back to being just has_approval_log like has_paper_trail?

Physical fucked around with this message at 21:39 on Apr 23, 2012

Physical
Sep 26, 2007

by T. Finninho
Oh I see, I have to make a file with the name and a class and stuff. I'll have to read more. Weird that it worked pre-restart though.

prom candy
Dec 16, 2005

Only I may dance
You've got some weird stuff going on in there. Do you want these methods to be available in all of your models? If so you don't need to reopen ActiveRecord::Base:

code:
module ApprovalLogModule
  def approve(user_name)
    app =  Approval.create({ :item_type => self.class.to_s,
                      :item_id => self.id,
                      :approval_date => Time.now.to_datetime,
                      :approved_by => user_name,
                      :version => current_version + 1
                    })
    #app.approval_file.  --SAVE APPROVED PDF
  end

  def current_version
   last_approval.blank? ?  0 : last_approval.version
  end

  def last_approval
   approvals.last
  end

  def approvals
   approvals = Approval.where("item_type LIKE ? AND item_id = ?",  self.class.to_s, self.id.to_s).order("version")
  end   
end

ActiveRecord::Base.send(:include, ApprovalLogModule)
Just throw that in a file in config/initializers and you should be good to go, these methods will be available in any class that inherits from ActiveRecord::Base

Physical
Sep 26, 2007

by T. Finninho
I want to be able to do the following

code:
class MyModel < ActiveRecord
  has_approval_log
end

Jam2
Jan 15, 2008

With Energy For Mayhem
I'm creating a simple rails app for a web app project. I need to create a model, view, and controller. Should I generate these individually? I ran generate scaffold state and the StatesController class was populated with a ton of out-of-the-box methods. I know for sure I won't need the majority of these (if any at all).

Does scaffold produce a bunch of junk or is it useful to generate rails stuff this way?

Also, are the default routes in config/routes.rb sufficient for sending page requests to /state/filter?=query=

or do I need to do something to get this working? My web server presently returns No route matches [GET] "/state" when I go to url localhost:3000/state

Do I need to run a rake command to update the application?

Do you have any suggested resources for someone getting started with rails apps? I'm using The Rails 3 Way and The Ruby Programming Language as references. These seem complete, but it's not always clear how important a lot of the information will be for basic uses.

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.

Be sure to check out Railstutorial.org as it has a ton of great resources.

Physical
Sep 26, 2007

by T. Finninho
How can I create my own http header request via command line? Like lets say I want to run the following route:

quote:

"post /version/:id/revert" => "version#revert"

Since it is post, I can't just add it to the link url.

prom candy
Dec 16, 2005

Only I may dance

Physical posted:

I want to be able to do the following

code:
class MyModel < ActiveRecord
  has_approval_log
end

Not sure if this is the favoured way, but something like this:

code:

module ApprovalLogModule
  module ClassMethods
    def has_approval_log
      class_eval do
        include InstanceMethods
      end
    end
  end

  module InstanceMethods
    def approve(user_name)
      app =  Approval.create({ :item_type => self.class.to_s,
                        :item_id => self.id,
                        :approval_date => Time.now.to_datetime,
                        :approved_by => user_name,
                        :version => current_version + 1
                      })
      #app.approval_file.  --SAVE APPROVED PDF
    end

    def current_version
     last_approval.blank? ?  0 : last_approval.version
    end

    def last_approval
     approvals.last
    end

    def approvals
     approvals = Approval.where("item_type LIKE ? AND item_id = ?",  self.class.to_s, self.id.to_s).order("version")
    end   
  end
end

ActiveRecord::Base.send(:extend, ApprovalLogModule::ClassMethods)

prom candy
Dec 16, 2005

Only I may dance

Physical posted:

How can I create my own http header request via command line? Like lets say I want to run the following route:


Since it is post, I can't just add it to the link url.

What do you mean via command line?

hmm yes
Dec 2, 2000
College Slice
Has anyone dealt with comparing large data sets in Ruby? We essentially want to intersect a hash of objects (hundreds) against all objects in the database (hundreds of thousands), returning unique objects that appear in both sets. This would happen many times an hour. Can ActiveRecord/Rails reasonably handle this kind of work out of box? Should we rely on a third party search service like Sphinx or Solr? Any insight would be appreciated.

Baxta
Feb 18, 2004

Needs More Pirate
I was having an issue with my escapes not escaping pesky <script>alert();</script> stuff with an app going through the whole git heroku thing. Also my new divs werent showing up.

The answer was before pushing, I needed to delete cached items before committing and pushing (so the .scss and .erb can regen new css and html). Hope this helps someone because it confused the hell out of me.

Now im getting a new pain in the rear end error with cedar stack. Pushing a db is coming back with a timestamp error (postgres). Research has dictated that its because im using 1.9.3 and cedar stack only lets you push dbs from 1.9.2 for some unknown bullshit reason.

Any ideas?

Cocoa Crispies
Jul 20, 2001

Vehicular Manslaughter!

Pillbug

atastypie posted:

Has anyone dealt with comparing large data sets in Ruby? We essentially want to intersect a hash of objects (hundreds) against all objects in the database (hundreds of thousands), returning unique objects that appear in both sets. This would happen many times an hour. Can ActiveRecord/Rails reasonably handle this kind of work out of box? Should we rely on a third party search service like Sphinx or Solr? Any insight would be appreciated.

What part of the object would you be comparing?

This sounds like something you could do with Redis:
  • When you write to the database, also add its key to a set in Redis
  • As you build up your hash (would it be coming from a single request?), add those keys to a new set in Redis
  • Tell the new set to expire in an hour perhaps
  • Ask Redis for the intersection of the two sets

Put that in a resque outside of the request loop if it takes more than a second or two.

Vivian Darkbloom
Jul 14, 2004


TextMate's nice for Ruby except that the indentation seems to break whenever I extend a statement over more than one line. Is there any fix for this?

Jam2
Jan 15, 2008

With Energy For Mayhem
I'm using a partial template to generate a tabbed menu.

I need to pass :locals to this partial to populate it with label and url pairs.

I figure its best practice to describe/place these label url pairs in the view that calls the partial, where all the other page content is located.

However, generating these locals involves creating an Array of Hashes of the form

[{:string => "Home", :url => "#home"}, {:string => "About", :url => "#about"}]

Sometimes there are five or six Hashes in the array, so it is cumbersome to create the Array this way. Should I be doing this data structure creation in the Controller for this view? Is there some way I can make it simpler in my view? Perhaps writing the string url pairs like this below and having it converted in some way:

(home, #home, About, #about, ..., ...)

prom candy
Dec 16, 2005

Only I may dance
As a rule you generally never want to set variables in the view. Where are these pairs coming from?

I would just use a straight hash for the data structure rather than an array of hashes:

code:
menu_items = {
  "Home" =>    "/",
  "About" =>   "/about",
  "Contact" => "/contact"
}
You can cycle through that pretty easily with each or map:
code:
menu_items.each do |title, url|
  ...
end
The code to build a menu out of the hash should probably go in a view helper.

Novo
May 13, 2003

Stercorem pro cerebro habes
Soiled Meat
Sometimes you want to control the order in which things show up. I have gotten into the habit of defining my navigation in lib/appname/navigation.rb using an Array instead of a Hash.

code:
module Porthole::Navigation
  TREE = [
    [ 'accounts',    :accounts    ],
    [ 'invitations', :invitations ],
    [ 'groups',
      [
        [ 'authorization', :groups_auth_groups ],
        [ 'distribution',  :groups_dist_groups ]
      ]
    ],
    [ 'reports',
      [
        [ 'entitlement flags', :entitlements_report     ],
        [ 'expiring soon',     :expiring_report         ],
        [ 'expired',           :expired_report          ],
        [ 'status mismatches', :status_mismatch_report  ],
        [ 'email forwarding',  :email_forwarding_report ]
      ]
    ],
    [ 'logs', :logs ]
  ]
end
It's pretty easy to traverse TREE and generate nested navigation markup for Bootstrap.

Also, you should never be writing literal URLs in a Rails app, use the route names or _url helpers, they will save you a lot of hassle.

prom candy
Dec 16, 2005

Only I may dance
Hashes are ordered in 1.9 aren't they?

Adbot
ADBOT LOVES YOU

Smol
Jun 1, 2011

Stat rosa pristina nomine, nomina nuda tenemus.
Yes, and in 1.8 you can use e.g. ActiveSupport::OrderedHash.

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