Manage newsletter subscribers from one or two models? - Rails 5 - ruby-on-rails

I want my Rails app to send a newsletter. I first implemented it so that Users can subscribe and receive the newsletter. But now I'd like people who are not a user to be able to join the newsletter as well. Therefore I created a new model: NewsletterSubscribers.
The thing I'm running in now though is that I want to make sure that whenever someone first joined the newsletter and later on signs up for an account, he doesn't get the newsletter twice.
Im doubting how to go forward with this. I see two options:
Send it to NewsLetterSubscribers and then before sending it to the Users, check if their email is present in a record of the NewsletterSubscriber table. And if it is present, not send it to that email again. My worry though is that this is very slow. Also it feels like bad practice to manage my newsletter subscription with two models.
To manage the newsletter only from the NewsletterSubscriber model. Everyone can subscribe (visitors and users). This would simplify it a lot, but I want to be able to check whether a user is subscribed to the newsletter or not in my views. So then I would need a belongs_to - has_many association between NewsletterSubscriber and Users. But then visitors can not subscribe anymore because of the validations that come with this association.
As you can read, I'm stuck... Does anyone have an idea how to best approach this?
ps. I use Devise with Twitter omniauth to authenticate users. Wanted to let you know, in case this simplifies or complicates a possible solution.

You can just disable the validation generated by belongs_to by passing the optional: true option:
class User < ApplicationRecord
has_many :newsletter_subscriptions
# or
has_one :newsletter_subscription
end
class NewsletterSubscription < ApplicationRecord
belongs_to :user, optional: :true
end
Another way you might want to consider is using Single Table Inheritance (STI) which will let you create different logic for guest and registered subscriptions while still using a single table. You can set this up by adding a string column named type to the newsletter_subscriptions table.
# rails g model NewsletterSubscription type:string email:string user:references
class NewsletterSubscription < ApplicationRecord
# shared logic
end
# app/models/users/newsletter_subscription.rb
module Users
class NewsletterSubscription < ::NewsletterSubscription
belongs_to :user
delegate :email, to: :user
end
end
# app/models/guests/newsletter_subscription.rb
module Guests
class NewsletterSubscription < ::NewsletterSubscription
validates_presence_of :email
end
end

Related

RoR modelling for different users, Devise, Active Admin

I have a single users table through Devise. Branching off this table are 3 other models (author.rb, seller.rb and buyer.rb) with each having a one to one relationship with the main Users table.
The reason for this is each have some unique attributes and I want to keep the main Users table tidy. I am using active admin and want to avoid redundant fields when registering a new user.
Currently I am using enums to assign user roles:
enum role: [:author, :sellers, :buyers]
The problem is when I set a role it works in the sense that I can restrict what a user sees based on that role however there is a big issue I have below.
The problem:
I want to be able to register an Author. Everything good so far. But I also want to be able to register a Buyer and then associate that buyer with the author as two different users. At the moment a user is becoming both at the same time through nested forms in active admin I used which is not what I want. I want a user to be a buyer and the other user to be an author.
Maybe I don't have my relationships set up correctly for this? Or it could be a problem in active admin?
class Author < ActiveRecord::Base
belongs_to :user
end
class Buyer < ActiveRecord::Base
belongs_to :user
end
class User < ActiveRecord::Base
has_one :author
has_one :buyer
end
Basically I want to be able to register two different users and after that associate them and I don't know how to do this. Any advice much appreciated.

Rails STI vs Polymorphic vs Neither

I have a Users class in my rails app. I need two types of users, 1) Players, 2) Managers. Users will all log in using Devise and have same basic user fields. I will have a League model. What is the best way to model this? STI doesn't seem quite right but not sure if Polymorphic works either since if both Manager < User && Player < User. The only real role a manager will have will be admin roles such as adding/removing players from leagues, setting up schedules etc.
class League < ActiveRecord::Base
has_one :manager
has_many :players
end
class Match < ActiveRecord::Base
has_and_belongs_to_many :players
belongs_to :league
end
class User < ActiveRecord::Base
has_and_belongs_to_many :matches
has_and_belongs_to_many :leagues
end
class Player < User
has_and_belongs_to_many :leagues
has_and_belongs_to_many :matches
end
class Manager < User
has_many :leagues
end
Any suggestions for the best way to set this up are greatly appreciated!
Using STI for players ActiveRecord is looking for Player table for the join but it doesn't exist.
STI can work for this, but since the difference between the types of users is basically a flag that says a user is an admin, you just need something on a user to check whether they are allowed certain actions. Roles can be either exclusive or inclusive (so that a user can be both a Player and a Manager), but once set up you can shape the interface around the capabilities a user has:
<% if #user.has_role?('manager') %>
<%= render 'manager_fields' # or manager_page, etc. %>
<% end %>
How you handle this in the controller depends on how you implement the roles, either via gems like Pundit, CanCanCan, etc. or through explicit checks in something you write yourself. The gems will give you helper methods to reduce the amount of typing involved in views and a more declarative syntax on the back end.
STI eliminates the need of separate tables for each class, given that most (or ideally all) attributes are shared between the two models.
In this case we'd add a new column in the users table called type which will indicate the class that this record will be parsed to, so either Player or Manager
As for the models
class Player < User
and
class Manager < User
As for the permission you could check if the user instance is of type Player or Manager
Of course you don't need to do STI if you don't want to, instead you'll create two tables players and managers and you'll need to join them with the User model, which would be tricky, since not all users have managers and not all users have players, so one or the other will always return nil, .. unless you create a polymorphic relation, but then you'll need to check the type of the object, .. idk
I think STI is your best solution, for the time being

Adding A LOT Attributes to Rails Devise

I am implementing a login system, which require to collect a lot of user data, for example:
college, course, graduate year, start year, hobby, .... about 20-30 of them.
Is it wise to put them all into Devise? Or create another Model to handle that?
Its not good idea to put so much of data in devise model. Devise model record is always fetched from database for every request.(You can see it from logs)
You can add it in another model and add association.
e.g. you can add profile model
Assuming you have User model as devise model.
You have to take care of creating profile record after either User creation or User logs in first time or as per your requirement.
class User < ActiveRecord::Base
has_one :profile, :dependent => :destroy
end
class Profile < ActiveRecord::Base
belongs_to :user
end
You can create a user_info model with this association, in user.rb
has_one :user_info
On, sign_in it should create an instance of user_info if its not present in the databse
This approach would be better if you want to add 20-30 columns

Confused about Ruby on Rails Active Record structure

I'm having trouble coming up with a way to structure my models to the the following:
I have Users through Devise - Users can have a role of (amongst others) Sales, Admin and Client. This is set through a HABTM with the Role model. I've set up a method so I can do the following
user.is? :Client
What I need is the following:
Users that have the Role of Sales can have any amount of clients.
So when a SalesPerson logs on, I can do User.clients to fetch all clients related to them.
Users that have the Role of Client can only have one client.
When a new Client signs up online, I want to create their user trough devise, and then also create a client through nested values, linked to the user they created.
Clients should have one SalesAgent, using the User model
When viewing the client, one should be able to have a dropdown to select the SalesAgent from. This should, as above, use the User model.
Clients should have only one Devise User with the role of Client, using the User class
Clients should be able to log on through devise to access their details, track orders, etc.
As you can see, this is incredibly confusing, and I'm not sure what the best way would be to pull this off. The only thing I can think of would be to use a HABTM between Users and Clients, and then Joins and hacks in the forms to make it work. Is there a better way to do this? I've looked at perhaps using
has_one :sales_agent, :class_name => "User"
But can't get it working. :/
Rather than overloading the User class with a roll-your-own single table inheritance scheme, it's often better to break out the roles in the db. It sure makes things clearer at this stage, and it's a better way to store data specific to clients or sales agents that don't belong to any user. E.g.:
class User < ActiveRecord::Base
has_many :clients
has_many :sales_agents
end
class Client < ActiveRecord::Base
belongs_to :user
belongs_to :sales_agent
end
class SalesAgent < ActiveRecord::Base
belongs_to :user
has_many :clients
end

Ruby On Rails Hierarchical Relationship Modeling

I have a base table called users which holds all common information about a user such as name, address, phone number...etc
I have another table called clients which holds specific information about a client (such as the client's company name and their url) and inherits user information from the users table. A client has a foreign key user_id which maps back to the information about a user.
I have another table called client_admins which hold specific information about client_admins and also has a user_id field AND a client_id field (which links to the clients table).
I have another table called super_admins which links to the users table and has specific information about a Super admin.
I know I could probably get away with Single Table Inheritance as there is not a lot of different data between each of the types, just different functionality and privileges.
What is the best way to model this in Rails 3?
Inside your user model:
has_one :client
has_one :client_admin
has_one :super_admin
Inside your client model:
belongs_to :user
has_one :client_admin
Inside your client_admin model:
belongs_to :user
belongs_to :client
Inside your super_admin model:
belongs_to :user
I am unsure of whether this is exactly what you were aiming for, but with my citier gem you could do this:
class User < ActiveRecord::Base
acts_as_citier
# User methods and validation, inherited by all children (so client & super admins)
# Useful for things like validating user permissions etc
end
class Admin < User
acts_as_citier
# Admin specific methods and validation, inherited by all children
end
class Client < ActiveRecord::Base
end
class ClientAdmin < Admin
acts_as_citier
belongs_to :client
# Client admin specific methods and validation
end
class SuperAdmin < Admin
acts_as_citier
# Super admin specific methods and validation
end
Allows each model to have unique fields so better than STI, but also shares methods and properties like normal inheritance.
Check it out - http://peterhamilton.github.com/citier/

Resources