Gem, update and compatibility - ruby-on-rails

I have a User model, the user can gradually insert information on their profile (age, description, avatar, etc..). Those users can be viewed in the public web site only if they have complete their entire profile.
Whats is the best way in rails to put constraint on query without polluting every single call to Active Record User model. Is there're a way for
User.all
to return result with those constraints by default?
Tks a lot!

You could define a scope.
# user.rb
scope :complete, where("age IS NOT NULL", "description IS NOT NULL",...)
Then you can just do User.complete and it will fetch User objects matching those conditions. For more information:
http://api.rubyonrails.org/classes/ActiveRecord/NamedScope/ClassMethods.html

Related

Force filter on user_id

I made a new Rails project and added Devise for user management. I also made tables like 'posts' and 'tags' and they have a field 'user_id' because the data is per user.
Now I can make queries where I always include user_id as filter. This works fine, but I'm afraid that someday I will forget to filter on user_id and a user can see data of other users.
Is there a way in models to force a certain filter?
For some models like 'posts' and 'tags' I would like to always filter on the current_user. Is there a way to automatically do this or maybe raise an exception if I forget to filter on user?
Any tips are welcome.
(I could use something like Apartment, but I prefer a single database/schema for now)
In your proxy method for params, you can use the require method to require the user_id field. Thus if you restrain from using params directly, as everybody should, your contraint will be enforced.
Another way is to have a before_action filter, where you check your condition. That way, unless you purposefully exclude a method from this filter, your check will always be enforced (or 422 will be returned).
Putting a condition on the model itself seems wrong to me: the model should not know what the access conditions are because access control is an orthogonal feature and should not be entangled with the model.

Sort by timestamp on has_many after scope

I have a User object, a Package object (User has_many packages) and then a LocationTracker (User has_many location_trackers), which acts as a join table between User and Package, but just tracks details such as the most recent package delivery.
I'd like to sort my Users based on the most recent package they sent. The LocationTracker has an attribute last_received_from_user
I can easily sort the users from a certain location by ordering by the last_received_from_user attribute, however I'd also like to have a global index page that shows all of the Users, sorted by the last package they delivered.
I'm having trouble grouping the users. I'm attempting to use a DISTINCT ON(last_received_from_user), but then it complains that the attribute isn't in the group, and when I add it to the group, it groups by that timestamp, which is obviously pretty unique, so I get duplicate users showing up.
My current code is as follows:
User.includes(:location_trackers)
.group("location_trackers.user_id, users.id")
.order("location_trackers.last_received_from_user #{order} NULLS LAST")
Any help is greatly appreciated!
EDIT:
I've got the last_received_from_user which allows me to sort users from a SINGLE location well. However, I need to be able to scope based on what could be a number of different options. For example, only show users in a certain area (Which could be compromised of a few locations), or order by ALL users for ALL locations. The attribute works great for a single user-location relationship, but fails when it comes to attempting to perform the search on more than 1 location.
I'd like to sort my Users based on the most recent package they sent
Wouldn't it be easier (and way more efficient) having an attribute like latest_delivery_location and using a callback on the User model like:
class User < ApplicationRecord
after_update :update_latest_delivery_location
private
def update_latest_delivery_location
update_attributes(
latest_delivery_location: location_trackers.last.last_received_from_user
)
end
end
Or updating such attribute after an order has been placed / dispatched. I'd go for this approach because is easier to maintain and, if you want it more performing you could always add an index on users.latest_delivery_location for sorting operations.

How create separate DataBase for each user

I am using Rails 3 and want whenever user will be created, then separate Data Base should be created for newly created user.
e.g if I have 13 migration in my application, so 13 tables should be created for newly created user.
How I can achieve this functionality?
Also check out the audio/video that goes along with James slides here http://www.confreaks.com/videos/889-railsconf2012-ten-things-you-didn-t-know-rails-could-do. Move forward to around 15:30 for the section on one user per database.
This is a really bad idea to handle many DB in Rails!
You can add a field, say, user_id in each of your tables that are needed to be separated and then apply default_scope to their respective models (or make an abstract model with default_scope via self.abstract_class = true and inherit your "shareable" models from it).
Your default_scope, as you might guess, should look like:
default_scope lambda { where(user_id: current_user_id) }
How to get the current user, you may ask?
Models can't access session, so you can make the following "hack" in order your scope to work:
#in ApplicationController
before_filter do
user_id = session[:user_id]
ActiveRecord::Base.class.send :define_method, :current_user_id, lambda { user_id }
end
I guess you got the idea.
This is best post i follow and solve my problem
http://7fff.com/2010/12/02/activerecord-dropcreate-database-run-migrations-outside-of-rails/

rails3 authlogic admin roles

I have authlogic working fine but now have the need to let administrator users come in and have different access.
So I created a migration adding administrator column to the Users table as string. However, I just can not seem to get the value of it out!!
see below my index action:
print "\n administrator" + User.find(current_user.id).administrator.to_s
the above line never prints anything when I know that this user HAS administrator string set to true in the db.
Below is the User model
class User < ActiveRecord::Base
acts_as_authentic {|config|
config.validates_uniqueness_of_email_field_options :scope => :id
}
belongs_to :another_class
end
what am I doing wrong here? All I want to do is get the administrator column value out. In the logs I can see the select users.* from users where id = 2 query being run!
is there another best way to manage admin roles with authlogic??
You're likely better off using cancan for managing roles and permissions. It can be used in combination with authlogic.
If you are going to just add a flag "administrator" field to the user record, it should work as long as your rules are simple, but would be better as a boolean rather than a string.
You say you have an "administrator" column of strings in your database and you're looking for a value of true. Maybe you wanted a Boolean column?

Ruby on Rails - Optional Associations?

I would like to allow users to write comments on a site. If they are registered users their username is displayed with the comment, otherwise allow them to type in a name which is displayed instead.
I was going to create a default anonymous user in the database and link every non-registered comment to that user. Would there be a better way to do it?
Any advice appreciated.
Thanks.
The problem with creating an anonymous user is then you need to check if a comment was made by a "real" user, or an anonymous one when displaying the name, so that introduces complexity. Plus, if you have a way of viewing their profile page, which may include posting history, you'd need to exclude the anonymous user with an exception.
Generally it's better to have a column on your comments which represents the user's visible name, and just show that if provided, or the registered user's name otherwise. For instance, your view helper might look like this:
class Comment < ActiveRecord::Base
belongs_to :user
def user_name
self.anonymous_name or (self.user and self.user.name) or 'Anonymous'
end
end
This will display the contents of the anonymous_name field of the Comment record, or the user's name if a user is assigned, or 'Anonymous' as a last-ditch effort to show something.
Sometimes it's advantageous to actually de-normalize a lot of the database when dealing with large numbers of comments so you don't have to load in the user table via a join simply to display a name. Populating this field with the user's name, even if they're not anonymous, may help with this, though it does mean these values need to be updated when a username changes, presuming that's even possible.
I think you can make user_id on your comment model nullable since you want to allow non registered users to add comments as well. As far as adding names for the non registered users are concerned, there are two options for that
option 1. Add a column on Comment model and name it like anonymous_user where you will store names of non registered users
option 2. Create a another model AnonymousCommentor with name and comment_id attributes.
If you are going to use anonymous users for other things as well apart from comment in your application then you can make it polymorphic and use a suitable name like AnonymousUser instead of AnonymousCommentor

Resources