I've seen some great resources for creating invitation systems where the app sends an email invitation with a link to the invited user's email, like devise_invitable.
What I'm trying to figure out is how to generate a bunch of invite codes so that I can give them out to specific people, and then they can sign up with that invite code. I have some ideas of what I would do but I'm wondering if anyone's every come across this before and has some tried and true methods.
I'm using devise for authentication by the way.
Any help is much appreciated.
You could always create an InviteCode model that contains a randomly generated redeemable code that can be issued on demand and validated at a later point in time.
For example:
class User < ActiveRecord::Base
has_one :invite_code_used,
:class_name => 'InviteCode',
:foreign_key => 'user_redeemer_id'
has_many :invite_codes,
:foreign_key => 'user_creator_id'
end
class InviteCode < ActiveRecord::Base
belongs_to :user_creator,
:class_name => 'User',
:foreign_key => 'user_creator_id'
belongs_to :user_redeemer,
:class_name => 'User',
:foreign_key => 'user_redeemer_id'
end
You'd create a randomly generated string to use as the invite code, presumably somewhere like before_validation to ensure it's populated before saving. When the code is redeemed, link the code to the user that was created so you can see who actually claimed it.
Creating an invite code for a user is as simple as something like this:
#invite_code = #user.invite_codes.create(:email => 'someone#example.com')
You can add some validations on the creation of an InviteCode to ensure that a given user hasn't created more than they should've and any other business logic you might require.
Related
I have a website that has User and Group models and all is well. The User and Group models are two types of accounts that we have and they are currently used for contact information, authentication and authorization.
Now I'm building out the subscription part of the site so we can start billing users (and groups/organizations) who subscribe to our premium services. I've opted to put this new code in a Rails Engine because I hope to deploy the engine only to an environment on a host that is reachable via our VPN, like so:
mount Billing::Engine, :at => '/billing' if Rails.env.admin?
I've got three models that I'm working with to manage subscriptions:
module Billing
class PricingPlan < ActiveRecord::Base
has_many :subscriptions
end
end
module Billing
class Subscription < ActiveRecord::Base
belongs_to :pricing_plan
belongs_to :subscriber, :polymorphic => true
# Used for eager loading
belongs_to :users, :foreign_key => 'subscriber_id', :class_name => '::User'
belongs_to :groups, :foreign_key => 'subscriber_id', :class_name => '::Group'
has_many :payments
end
end
module Billing
class Payments < ActiveRecord::Base
belongs_to :subscription
end
end
The Billing::Subscription.subscriber part is what is currently vexing me. As you can see, I'm currently reaching across the engine boundary to get ahold of the ::User and ::Group models that live in my application, but that feels icky.
I thought about creating Billing::User and Billing::Group AR models so that the engine and application can be completely isolated from one another, but it seems a bit weird to duplicate information between two models that are, for now, in the same database (e.g. first_name, last_name, email, etc.)...plus I'd have to duplicate information between them, which is a recipe for disaster, I'm sure.
I also thought about using some kind of wrapping model to abstract away the actual implementation, something like this:
module Billing
class User < ::User
end
end
But if I recall correctly, I ran into problems with the polymorphic behavior I'm after and/or problems with rspec mocking and stubbing so I abandoned that approach.
I'd appreciate any guidance. I've made numerous trips to Google searching for answers but nothing I've seen so far seems directly applicable.
UPDATE
Using Carl Zulauf's suggestion, I came up with the following:
# File: app/models/concerns/billing/subscribable.rb
require 'active_support/concern'
module Billing
module Subscribable
extend ActiveSupport::Concern
included do
has_one :subscription, {
:class_name => '::Billing::Subscription',
:foreign_key => 'subscriber_id',
:as => :subscriber
}
base = self
Billing::Subscription.class_eval do
belongs_to base.name.tableize.to_sym, {
:foreign_key => 'subscriber_id',
:class_name => base.to_s
}
end
end
end
end
Which I then invoke thusly:
class User < ActiveRecord::Base
include Billing::Subscribable
can_subscribe
end
This works...so long as I load User before I call Billing::Subscription.eager_load :users...which seems really dicey. Got any suggestions for me?
UPDATE #2
I wound up creating an initializer to handle this. This works, but if there are any better options, I'm all ears.
# File: config/initializers/setup_billing.rb
User.class_eval do
include Billing::Subscribable
end
Group.class_eval do
include Billing::Subscribable
end
One approach would be to have a module in your engine that would add a class macro to User and Group.
class User < ActiveRecord::Base
include Billing::ModelHelper
has_subscription # new macro
end
has_subscription could then:
Look up the class name (User)
Add the has_many/has_one/belongs_to association to User
Add the special association to Billing::Subscription (belongs_to :user, ...)
Pretty new to rails, and coding in general. I'm working on my own app right now, in which I'm trying to create user profiles. I know that there have been a few questions about this, but what I'm specifically trying to do is...
Upon authentication (which I've set up using Devise), the user is redirected to his/her profile page where he/she can set up their own profile, with fields similar to what you may find on a social networking website.
I'm running rails 4.1 and ruby 2.1 right now. Does anyone have any suggestions on the best way to go about doing this. As I mentioned I'm fairly new to rails, and have spent the last few days furiously searching for advice on the internet.
Does anyone know of a step by step guide?
I suppose what I need is just guidance on where to start.
Thanks!
You can add other fields like first name, last name, and date of birth to user table itself if you have minimum number of attributes you want to add. You can get all the details from current_user. But if you have many fields that you want to add to user profile then you can create a new model name UserProfile and add other related fields to this model. And add a one-to-one relationship between User and UserProfile table. So in the future if you want to add another relation/attribute with/to user, you can add it with UserProfile. That will reduce making a mess in your database in later stages.
recently i created user profile so that user can add/edit his personal details,see what he has uploaded.what he has liked,posted and edit/delete/update anything that he has created/uploaded.So in user profile all you need is to fetch all details/associated models of that user and show.So as u already have devise..you can get current_user and use user.rb model to understand all associations of user and get the data using associations ans display it on profile page
i have created a profile_controller
so in my nav_bar i have a link_to <% link_to "View Profile",show_profile_path(current_user) %>
where user is directed to profiles controller and i show the details without creating a new model(user has_one :profile)
i have a dedicated page to show profile details + a small page to show any user profile when hovered on users image
take a look here for view side idea... user profile page on bootstrap 3
=======updated part===========
suppose i have a user.rb(using devise)
###different associations of user can be:=
##this user can like/dislike any model having acts_as_votable
acts_as_voter
##user can tags post/audio/videos/images
acts_as_tagger
##my user can create post,pages,upload images/videos/songs/locations etc...
has_many :posts, :class_name => 'Post', :dependent => :destroy
has_many :pages, :class_name => 'Page', :dependent => :destroy
has_many :images, :class_name => 'Image', :dependent => :destroy
has_many :videos, :class_name => 'Video', :dependent => :destroy
has_many :audios, :class_name => 'Audio', :dependent => :destroy
has_many :places, :class_name => 'Place', :dependent => :destroy
has_many :profile_pictures, :class_name => 'ProfilePicture', :dependent => :destroy
#####so..as now i know that **my user can have post/pages/audios/videos** etc...i can also get the details about those associations(assuming you have configured belongs_to in associated models as well + tables with foreign_key as user_id in eash associtated table),such as:-*
##to get all videos that user has uploaded
#user.videos
##same applies for other associated models as well
#user.images..#user.audios...#user.pages.....#user.post....#user.places...#user.profile_pictures...etc
####So now you have all user(current_user data)...
###its time to show data in profiles_controller..
##your show method
## profile#show
def show
#user=User.find current_user.id
#all_user_videos=#user.videos..and so on
##get all user videos/images..etc and show it in your view file
##your view file can be the one that i shared the link or any other way that you want...
###there are lot of ways...google around and then you can get an idea as how to display user_profile page..as now you have the data(*Yipee*)
end##method ends
hope this helps
In a small app I am building, I have a controller that creates an exchange. When a user creates an exchange they are simultaneously the organizer of the exchange and a participant in the exchange. Participants are tracked by a join table that joins a user_id and an exchange_id. Organizers are tracked by a foreign user_id key in the exchange table.
I am trying to figure out where to put the code that will automatically create a new membership record for the organizer of the exchange. Should I put this in the exchange_controller's create action itself, or in an after_filter triggered by the create action? Or maybe somewhere else? Part of the problem is that I could not find any good examples of proper after_filter use (guides.rubyonrails.org only had sparse mention of it), so any links pointing in the correct direction would be appreciated as well.
Here is relevant model code:
app/models/user.rb:
# Returns array of exchanges user is participating in
has_many :participations,
:through => :memberships,
:source => :exchange
# Returns array of exchanges user has organized
has_many :organized_exchanges,
:foreign_key => :organizer_id,
:class_name => "Exchange"
app/models/membership.rb:
class Membership < ActiveRecord::Base
attr_accessible :exchange_id, :user_id, :role
belongs_to :exchange
belongs_to :user
end
app/modles/exchange.rb:
belongs_to :organizer,
:foreign_key => :organizer_id,
:class_name => "User"
has_many :memberships, :dependent => :destroy
has_many :participants,
:through => :memberships,
:source => :user
And here is the relevant controller code:
app/controllers/exchanges_controller.rb:
def create
#exchange = Exchange.new(params[:exchange])
#exchange.organizer_id = current_user.id
if #exchange.save
redirect_to exchange_path(#exchange.id)
else
render 'new'
end
end
after_filter is a completely different thing in this context. It is called when your view is completely processed and so you want to call some action to do something.
You can use after_create callback that is triggered when a record is created in the database.
In your case, a user is creating an exchange and so after the exchange is created, the after_create callback is triggered and you can apply your functionality over there to make the current user who created the exchange to be a participant.
The way to write in a model is like this:
after_create :do_something
def do_something
something.do!
end
Note: It is not good to use after_save here because it is triggered every time you save a record or even if you update a record.
There is a nice SO post that clearly tells you the difference between the after_create and after_save.
See this SO post for the difference between the two.
More on the callbacks is here.
I am building a small app which has classes User, Student, Tutor, Meeting.
Each user can be tutor in one Meeting, but student in another meeting. I have been thinking about how to model these relationship.
Right now, I have a User model, a separate Participant model with an attribute Role = "tutor"/"student". Tutor and Student extend Participant using single-table inheritance, and belong to Meeting.
However, I wonder if this is a good design. (It seems to be unintuitive to me).
What would you do in my situation?
Thank you.
It is acceptable but there are other ways that are cleaner. You could design you Meeting model like this:
has_and_belongs_to_many :users, :as => :studens
belongs_to :tutor, :foreign_key => 'tutor_id', :class_name => 'User'
Your User Model:
has_and_belongs_to_many :meetings, :as => :meetings_taken
has_many :meetings_given, :foreign_key => 'tutor_id', :class_name => 'Meeting'
So you would only need two models.
// edit
For propose, accept, decline,.. I would create a Invitation Model user_id:integer (Invited User), meeting_id(Through this you know who is allowed to invite other people because Meeting belongs to the tutor), status:string (waiting, accepted, delicesed might be options) maybe explaination:text (When somebody delices).
users => has_many :contacts, :through => :user_contacts
contacts => has_many :users, :through => :user_contacts
profiles
now for profiles, there's a single profile for each user but there are two ways to access it, based on the url. There's a public url and a private url. A public url belongs to a user but the private url belongs to a contact (i.e assigned to the contact as a private url to the profile of the user to which that contact belongs). I'm confused how to treat profiles association with user and contacts in this scenario.
should i use STI for profiles like class Profile < ActiveRecord::Base, class PublicProfile < Profile, class PrivateProfile < Profile
but if that's valid, how do i manage the associations here?
what about simply having a single url type and differentiating with a type in the table. Then you can have the relationships for each TYPE of url with something along the lines of:
belongs_to :private_url, :class_name => "Profiles", :conditions => "type = 0"
belongs_to :public_url, :class_name => "Profiles", :conditions => "type = 1"
This would significantly "simplify" your assciations you have to manage. It's not the whole answer I don't think but perhaps if you can make it work this simplifies things enough that the problem you have becomes simpler to address.
I may have the exact syntax above incorrect but you should get the gist of what I'm suggesting...