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

enki42 posted:

I could be wrong, but it sounds like you're all set from the cookie side, and you just need to detect whether the user is logged in or not from the javascript side, and redirect to the login page once their session has expired.

I think you'd probably need some sort of "heartbeat" type call on a controller that could tell you whether you have an active session, and ping it every minute or so to see if your user is still active. If you don't get a "logged-in" status from that service, redirect to the login page.

You don't need a heartbeat, just make sure your app is sending the proper response to any request with an expired session - probably a 401 in this case. How you handle that depends on your front-end setup but you will add something like an ajax response hook or ember route error handler where you will inspect the response code and do whatever logic you need like redirecting the user or popping up an auth modal.

Adbot
ADBOT LOVES YOU

prom candy
Dec 16, 2005

Only I may dance
I have a Rails app that has four tiers of users: Member, Contributor, Admin, and Super Admin. The permissions for these tiers are pretty simple:

Super Admin: Can create other members of any other role, can assign any role to any user
Admin: Can create other members of any other role except super admin, can edit any other user except super admin, can assign any role to any user except super admin
Contributor and Member: Can only edit self, can't assign roles at all.

Where is the proper place to put code to ensure that Admins are not passing the Super Admin role's id as part of the user[role_ids][] parameter in order to grant themselves super powers? Right now I'm kind of working it out as part of my strong_params, like so.

code:
    def resource_params
      if current_user.is_admin? || current_user.is_super_admin?
        cleaned_role_ids(params.require(:user).permit!)
      else
        untrusted_params
      end
    end

    def cleaned_role_ids(rp)
      sa_role = Tenon::Role.find_by_title('Super Admin')
      if sa_role && rp[:role_ids] && !current_user.is_super_admin?
        rp[:role_ids].delete(sa_role.id.to_s)
      end
      rp
    end

    def untrusted_params
      params.require(:user).permit(
        :email,
        :password,
        :password_confirmation
      )
    end
  end
Is there a cleaner place to basically whitelist acceptable values that change based on the current_user's role?

enki42
Jun 11, 2001
#ATMLIVESMATTER

Put this Nazi-lover on ignore immediately!

Anveo posted:

You don't need a heartbeat, just make sure your app is sending the proper response to any request with an expired session - probably a 401 in this case. How you handle that depends on your front-end setup but you will add something like an ajax response hook or ember route error handler where you will inspect the response code and do whatever logic you need like redirecting the user or popping up an auth modal.

Normally you don't, but the yoyodyne's problem was that his app wouldn't redirect to the login page unless the user clicked a link - if you want your app to redirect to the login page without any interaction from a user when a session expires, you need some sort of timed request that checks login.

mmachine
Jan 5, 2006
I'm about to go crazy trying to get a CanCan / Rolify setup going. Here's the gist:

I've got a User model.
I've got an Album model.

Users have access to Album by varying degrees. By default, they should not see any Albums unless they have a defined role. Those roles might be:

- Owner
- Editor
- Manager

So in my Ability class, I've got:

code:
can :manage, Album if user.has_role?(:owner, Album)
And for applying roles, I'd run a command like this:

code:
@user = current_user
@album = Album.find(params[:id])

user.add_role :owner, @album
All good there -- a Role record gets added as expected, with proper resource_id and resource_type how they should be. Then, my assumption was that in a controller, if I did this:

code:
Album.all
..it would return all records based filtered by role permissions. I then learned that wasn't the case, as I was getting ALL records, so I learned I had to do something like this in my controller:

code:
Album.accessible_by(current_ability)
...and all that got me was NO records, even if I was a user with :owner roles on a record in the DB.

So, where can I start looking to sort this out? I'm confused because it seems like the CanCan and Rolify setup process adds all this overhead that I now don't see working. It creates a Role model, though it seems I now have to explicitly declare these relationships again anyway, which is why I wonder if I'm missing something key.

I've had success using CanCan in this app to control access to views / controllers. Just seems to be the model permissions that I'm getting muddled on.

Smol
Jun 1, 2011

Stat rosa pristina nomine, nomina nuda tenemus.
What does User#has_role? look like?

mmachine
Jan 5, 2006

Smol posted:

What does User#has_role? look like?

That's a method from rolify.

code:
    def has_role?(role_name, resource = nil)
      if new_record?
        self.roles.detect { |r| r.name == role_name.to_s && (r.resource == resource || resource.nil?) }.present?
      else
        self.class.adapter.where(self.roles, :name => role_name, :resource => resource).size > 0
      end
    end
https://github.com/EppO/rolify/blob/master/lib/rolify/role.rb

kayakyakr
Feb 16, 2004

Kayak is true
I think he means what does has_role? return.

I'm not sure how fine the resource resolution is, though. I'd usually implement that via a through relation with the role defined on the intermediary class. Maybe see if you can define a has_many :through via the role table.

mmachine
Jan 5, 2006

kayakyakr posted:

I think he means what does has_role? return.

I'm not sure how fine the resource resolution is, though. I'd usually implement that via a through relation with the role defined on the intermediary class. Maybe see if you can define a has_many :through via the role table.

Oh has_role? returns appropriately in the console tests I did. Should pop some debug in the ability check though just to be sure.

And you're saying it might help to have a has_many association in my Role class that points to my Album class?

Smol
Jun 1, 2011

Stat rosa pristina nomine, nomina nuda tenemus.
Yeah, I don't know anything about rolify or cancan, but I recommended stepping through the code with a good debugger. Rubymine has an excellent debugger, if you still haven't tried it out. Well worth the money in any case.

kayakyakr
Feb 16, 2004

Kayak is true

mmachine posted:

And you're saying it might help to have a has_many association in my Role class that points to my Album class?

This is the appropriate way to do it when you're not using a gem like Rolify. Might be the appropriate way to do it when you are using a gem like Rolify too.

mmachine
Jan 5, 2006

kayakyakr posted:

This is the appropriate way to do it when you're not using a gem like Rolify. Might be the appropriate way to do it when you are using a gem like Rolify too.

Definitely starting to seem that way. Only luck I've had so far has been with a definition like this in my Album model:

code:
has_many :albums,
    through: :roles,
    source: :resource,
    source_type: "Album"
Which technically isn't really using rolify at all, just one of the tables it rolls.

kayakyakr
Feb 16, 2004

Kayak is true

mmachine posted:

Definitely starting to seem that way. Only luck I've had so far has been with a definition like this in my Album model:

code:
has_many :albums,
    through: :roles,
    source: :resource,
    source_type: "Album"
Which technically isn't really using rolify at all, just one of the tables it rolls.

I mean, that's a has_many through and is pretty much the way to do things in rails. You can add association extensions to that to select out the role types like:

Ruby code:
has_many :albums do
  def admin
    where role: 'admin'
  end
end
Though with a bit more wordiness

Peristalsis
Apr 5, 2004
Move along.
I have a number of has_many :through relationships in the app I'm working on, and I want to keep the join tables from filling with junk. Say we have a Doctor model linked to a Patient model through an Appointment model. If I delete a patient, I naturally want to delete any appointments that patient has. I can do this using :dependent => :destroy in the models' links, like so:

code:
has_many :appointments, :dependent => :destroy
but I wonder if this is a common enough request there's a way to tell rails always to delete join rows when one of the joined rows is deleted, or if I need to specify the dependency in each side of every join model. (I know to be careful only to delete the appointment, and not the associated doctor, in the example above.)

We're using rails 3.2.1, if that matters.

Smol
Jun 1, 2011

Stat rosa pristina nomine, nomina nuda tenemus.
You'll want to read the "Deleting associations" section here.

http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html

Peristalsis
Apr 5, 2004
Move along.

Smol posted:

You'll want to read the "Deleting associations" section here.

http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html

Thanks for the link - it turns out that I had read some bad info, and didn't keep reading to see it corrected. So, as I understand it:

* There is no further shortcut - I need :dependent => :destroy for each linkage.

* I can put the :dependent => :destroy on the has_many link to the join table, OR on the has_many, :through link to the other real table. Is one considered better than the other? For the previous example, that means choosing between these:

code:
class doctor
  has_many :appointments, :dependent => :destroy
  has_many :patients, :through => :appointments
end

class patient
  has_many :appointments, :dependent => :destroy
  has_many :doctors, :through => :appointments
end

class appointments
  belongs_to :doctor
  belongs_to :patient
end

code:
class doctor
  has_many :appointments
  has_many :patients, :through => :appointments, :dependent => :destroy
end

class patient
  has_many :appointments
  has_many :doctors, :through => :appointments, :dependent => :destroy
end

class appointments
  belongs_to :doctor
  belongs_to :patient
end

kayakyakr
Feb 16, 2004

Kayak is true
it's more clear what you are doing if the :dependent => :destroy is on the through table.

KoRMaK
Jul 31, 2012



Heyyyy, I just learned how to override a column name with a method on Active record and still be able to get the column (db) value.

This causes a stack overflow due to recursion
Ruby code:
def my_items
	_my_items = self.my_items #this calls the function we are already in, I meant to grab the db value instead and erroneously thought that self. would differentiate between the two
	MyItem.find(_my_items)
	_my_items
end
Instead, I meant this:
Ruby code:
def my_items
	_my_items = self[:my_items] #this gets it from the db. also self.read_attribute(:my_items) would work
	MyItem.find(_my_items)
	_my_items
end

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.

I need a ActiveRecord.connection.execute-like method that blocks the thread. Both execute and update_sql seem to be async calls which is uhh no bueno for my purposes right now.

edit: or some way to hold until the execute returns

kayakyakr
Feb 16, 2004

Kayak is true

A MIRACLE posted:

I need a ActiveRecord.connection.execute-like method that blocks the thread. Both execute and update_sql seem to be async calls which is uhh no bueno for my purposes right now.

edit: or some way to hold until the execute returns

uhhhh why? this seems like a really bad idea.

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.

kayakyakr posted:

uhhhh why? this seems like a really bad idea.

Ehh we're sending push notifications that reference data that's supposed to be added in the execute command. The push notifications are sometimes hitting phones before the insert is finished and opening the app in that little time window breaks stuff

Smol
Jun 1, 2011

Stat rosa pristina nomine, nomina nuda tenemus.
Prettu sure it blocks already. Can't remember if the return value is anything useful though.

Smol
Jun 1, 2011

Stat rosa pristina nomine, nomina nuda tenemus.
Prettu sure it blocks already. Can't remember if the return value is anything useful though.

EAT THE EGGS RICOLA
May 29, 2008

A MIRACLE posted:

I need a ActiveRecord.connection.execute-like method that blocks the thread. Both execute and update_sql seem to be async calls which is uhh no bueno for my purposes right now.

edit: or some way to hold until the execute returns

Can't you use after_commit to push the notification after the execute is done?

EAT THE EGGS RICOLA fucked around with this message at 16:46 on Mar 26, 2014

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.

EAT THE EGGS RICOLA posted:

Can't you use after_commit to push the notification after the execute is done?

Mayyyybe. I'll look into it.

Smol posted:

Prettu sure it blocks already. Can't remember if the return value is anything useful though.

I dunno, this looks kinda thread-y. I haven't done thread stuff since I was a .NET developer many moons ago so I'm pretty fuzzy on this stuff.

Ruby code:
      # Executes an SQL statement, returning a PGresult object on success
      # or raising a PGError exception otherwise.
      def execute(sql, name = nil)
        log(sql, name) do
          @connection.async_exec(sql)
        end
      end

Smol
Jun 1, 2011

Stat rosa pristina nomine, nomina nuda tenemus.

A MIRACLE posted:

Mayyyybe. I'll look into it.


I dunno, this looks kinda thread-y. I haven't done thread stuff since I was a .NET developer many moons ago so I'm pretty fuzzy on this stuff.

Ruby code:
      # Executes an SQL statement, returning a PGresult object on success
      # or raising a PGError exception otherwise.
      def execute(sql, name = nil)
        log(sql, name) do
          @connection.async_exec(sql)
        end
      end

I'm not an expert on the pg gem, but what I can tell, async_exec still blocks but uses rb_thread_select to release the GIL while waiting for the I/O to finish.

kayakyakr
Feb 16, 2004

Kayak is true

Smol posted:

I'm not an expert on the pg gem, but what I can tell, async_exec still blocks but uses rb_thread_select to release the GIL while waiting for the I/O to finish.

unless you're using rbx or jruby which don't have a GIL applied.

still after_commit should occur after the row has been finalized, so if you're doing it in a callback scope, hook in there.

Oh My Science
Dec 29, 2008
is rubygems.org timing out for anyone else? I've been having issues updating gems all day.

Their twitter feed seems to be fine.

Cocoa Crispies
Jul 20, 2001

Vehicular Manslaughter!

Pillbug

Smol posted:

I'm not an expert on the pg gem, but what I can tell, async_exec still blocks but uses rb_thread_select to release the GIL while waiting for the I/O to finish.

Both exec and async_exec on PG::Connection allow other Ruby threads to run, but async_exec also allows signal processing to continue as well.

https://bitbucket.org/ged/ruby-pg/src/6c2444dc63e17eb695363993e8887cc5d67750bc/ext/pg_connection.c?at=default#cl-829

C code:
/*
 * call-seq:
 *    conn.exec(sql) -> PG::Result
 *    conn.exec(sql) {|pg_result| block }
 *
 * Sends SQL query request specified by _sql_ to PostgreSQL.
 * Returns a PG::Result instance on success.
 * On failure, it raises a PG::Error.
 *
 * …
 *
 * #exec is implemented on the synchronous command processing API of libpq, whereas
 * #async_exec is implemented on the asynchronous API.
 * #exec is somewhat faster that #async_exec, but blocks any signals to be processed until
 * the query is finished. This is most notably visible by a delayed reaction to Control+C.
 * Both methods ensure that other threads can process while waiting for the server to
 * complete the request.
 */

/*
 * call-seq:
 *    conn.async_exec(sql [, params, result_format ] ) -> PG::Result
 *    conn.async_exec(sql [, params, result_format ] ) {|pg_result| block }
 *
 * This function has the same behavior as #exec,
 * but is implemented using the asynchronous command
 * processing API of libpq.
 */
From the caller's point of view, they're both synchronous, just one's an insignificant bit slower but works better.

prom candy
Dec 16, 2005

Only I may dance

KoRMaK posted:

Heyyyy, I just learned how to override a column name with a method on Active record and still be able to get the column (db) value.

This causes a stack overflow due to recursion
Ruby code:
def my_items
	_my_items = self.my_items #this calls the function we are already in, I meant to grab the db value instead and erroneously thought that self. would differentiate between the two
	MyItem.find(_my_items)
	_my_items
end
Instead, I meant this:
Ruby code:
def my_items
	_my_items = self[:my_items] #this gets it from the db. also self.read_attribute(:my_items) would work
	MyItem.find(_my_items)
	_my_items
end

I THINK (not totally clear what you're trying to do here) that the best way to write this would be:

code:
def my_items
  @my_items ||= MyItem.find(read_attribute(:my_items))
end
The @my_items ||= means that the first call will cache the result of MyItem.find into an instance variable so subsequent calls won't hit the database. You should avoid using self. when calling internal methods (except for setters) but in my opinion you should use read_attribute rather than self[] because its a bit more clear what you're doing.

You may not want to use the instance variable caching (aka memoization) because if you change the database value of my_items in a single request the #my_items method will not change result, so that part depends on your usage.

Lexicon
Jul 29, 2003

I had a beer with Stephen Harper once and now I like him.
I have two rails apps that I'm developing simultaneously. They are in separate repos, separate DBs (though they both connect to MySQL locally - different databases of course).

I've noticed that my 'rakeall' command (bundle exec rake db:drop db:create db:migrate db:seed db:test:prepare) clobbers the other app's test database stuff. If I rakeall the first app, the tests in the other will fail - and vice versa.

What the hell is going on here?

enki42
Jun 11, 2001
#ATMLIVESMATTER

Put this Nazi-lover on ignore immediately!
What's the name of your database in the test section of database.yml? Development and test store their settings differently, and if the name was accidentally duplicated between your two apps, you'd see this behaviour (and development would still work perfectly fine)

Lexicon
Jul 29, 2003

I had a beer with Stephen Harper once and now I like him.

enki42 posted:

What's the name of your database in the test section of database.yml? Development and test store their settings differently, and if the name was accidentally duplicated between your two apps, you'd see this behaviour (and development would still work perfectly fine)

Jesus Christ, I am a goddamn idiot, first for duplicating my database.yml carelessly, and second for not realizing the reason behind this very obvious [in hindsight] symptom.

Thank you kindly!

Pardot
Jul 25, 2001





Any chance I can convince you to use something else?

Lexicon
Jul 29, 2003

I had a beer with Stephen Harper once and now I like him.

Pardot posted:

Any chance I can convince you to use something else?

Yeah, I'm definitely aware of MySQL's various shortcomings, and really like what I've seen of PostreSQL so far. I definitely intend to permanently migrate away from MySQL, but I have two reasons I haven't done it yet (neither of which is well-justified):

1) I'm very familiar with MySQL, its warts, using it locally and on RDS, etc. It's like an old pair of slippers that I'm sad to throw away, even though I've a way better pair sitting unboxed.
2) I absolutely love Sequel Pro as an OS X database client. It doesn't support PostreSQL yet.

As I said - not well-justified. I will switch one day :)

Ferdinand the Bull
Jul 30, 2006

Hey everyone,

I have zero useful points to add to the thread. I just want to point out that I finally understand what you guys are talking about.

I've been studying programming generally for the past year. This past month I've been going to a Ruby on Rails programming school.

This thread has been such a great resource for me. Thank you so much to all of you.

waffle enthusiast
Nov 16, 2007



Namespacing question. Is it generally considered appropriate to namespace an entire application, or just sub-components.

I'm working on a beer review application (probably pretty similar to the other one discussed here), that lets folks review (in-depth) as well as keep tabs on which beers they're cellaring/drinking. Let's say I'm calling it "DrinkUp" or something. Would it make sense to start namespacing all my controllers?

e.g.

DrinkUp::BeersController
DrinkUp::BreweriesController
etc.

So pretty much everything would be DrinkUp::Whatever. Or is that unnecessary in the context of an entire application?

kayakyakr
Feb 16, 2004

Kayak is true

Dangerllama posted:

Namespacing question. Is it generally considered appropriate to namespace an entire application, or just sub-components.

I'm working on a beer review application (probably pretty similar to the other one discussed here), that lets folks review (in-depth) as well as keep tabs on which beers they're cellaring/drinking. Let's say I'm calling it "DrinkUp" or something. Would it make sense to start namespacing all my controllers?

e.g.

DrinkUp::BeersController
DrinkUp::BreweriesController
etc.

So pretty much everything would be DrinkUp::Whatever. Or is that unnecessary in the context of an entire application?

No, your application is your application. If you were building a gem, something that gets embedded in a different application, then you would want to namespace, but in this case, you're in your own application's space.

prom candy
Dec 16, 2005

Only I may dance
Wait are you the same guy that was building the Cellaring application like 10-20 pages ago or is that just a common idea around here?

waffle enthusiast
Nov 16, 2007



No. It's just a common idea. I've been dicking around with a beer review app for the last few years but just re-started again in earnest recently.

I've had it in my head that I should probably get some JavaScript under my belt before really diving in, which I do now (Angular and JQuery). But I've wanted to do the heavy lifting in a language I was more comfortable with, i.e. ruby.

Adbot
ADBOT LOVES YOU

Slow News Day
Jul 4, 2007

Could someone lend me a hand with this? I have a proof of concept demo tomorrow and I've been banging my head against it all evening.

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