Skip to content

Instantly share code, notes, and snippets.

@mikeadeleke
Last active August 29, 2015 14:00
Show Gist options
  • Save mikeadeleke/68484c00fa4e1eaa685b to your computer and use it in GitHub Desktop.
Save mikeadeleke/68484c00fa4e1eaa685b to your computer and use it in GitHub Desktop.
Invite Roommates with Unique Tokens
property.rb
class Property < ActiveRecord::Base
before_create :generate_token
validates :total_bedrooms, presence: true
validates :total_bedrooms, numericality: true
validates :total_bathrooms, presence: true
validates :total_bathrooms, numericality: true
validates :address, presence: true
validates :address, length: { minimum: 5 }
validates :title, presence: true
validates :title, length: { maximum: 100 }
validates :description, presence: true
validates :description, length: { maximum: 400 }
validates :zip_code, presence: true
validates :zip_code, numericality: true
validates :city, presence: true
validates :city, length: { minimum: 5 }
validates :state, presence: true
validates :state, length: { minimum: 1 }
validate :has_at_least_3_images
validate :image_extensions
has_one :listing
has_many :rooms
has_many :images, :as => :attachable
has_many :tenants
accepts_nested_attributes_for :images, reject_if: Proc.new {|attr| attr[:photo].blank? }
geocoded_by :address
after_validation :geocode
reverse_geocoded_by :latitude, :longitude
after_validation :reverse_geocode
has_many :invites
has_paper_trail
def has_at_least_3_images
errors.add(:images, 'Please add at least 3 photos. Someone might live there :) ') unless images.size >= 3
end
def image_extensions
errors.add(:images,
'Please add at least 3 photos with gif, jpg, or png extension' +
'. Someone might live there :) ') if images.length < 3
end
private
def generate_token
self.token ||= SecureRandom.urlsafe_base64(8)
end
end
_form.html.erb (property)
<div class="property-form">
<%= simple_nested_form_for @property, :html=> {:multipart => true } do |f| %>
<% if @property.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@property.errors.count, "error") %> prohibited this property from being saved:</h2>
<ul>
<% @property.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.hidden_field :title %>
<div class="field">
<%= f.hidden_field :total_bedrooms %>
<div class="field">
<%= f.hidden_field :total_bathrooms %>
<div class="field">
<%= f.hidden_field :address %>
<div class="field">
<%= f.hidden_field :city %>
<div class="field">
<%= f.hidden_field :state %>
<div class="field">
<%= f.hidden_field :zip_code %>
<div class="field">
<%= f.hidden_field :description %>
<div class="actions">
</div>
</div></div></div></div></div></div>
</div>
<form class="form-horizontal">
<fieldset>
<legend>Add your space</legend>
<div class="field">
<ul>
<%= f.fields_for :images do |image_form| %>
<% unless image_form.object.new_record? %>
<ul class="present-images">
<li> <%= image_tag image_form.object.photo.url %></li>
<li><%= image_form.link_to_remove "Remove this image" %></li>
</ul>
<% else %>
<li><%= image_form.file_field :photo %></li>
<li><%= image_form.link_to_remove "Remove this image" %></li>
<% end %>
<% end %>
</ul>
<p><%= f.link_to_add "Add photo", :images %></p>
</div>
<div class="form-group">
<label for="inputEmail" class="col-lg-2 control-label">Title</label>
<div class="col-lg-10">
<%= f.text_field :title, class: "form-control", id: "inputPassword" %>
</div>
</div>
<div class="form-group">
<label for="inputPassword" class="col-lg-2 control-label">Total Bedrooms</label>
<div class="col-lg-10">
<%= f.number_field :total_bedrooms, class: "form-control", id: "inputPassword" %>
<div class="checkbox">
<label>
</label>
</div>
</div>
</div>
<div class="form-group">
<label for="inputPassword" class="col-lg-2 control-label">Total Bathrooms</label>
<div class="col-lg-10">
<%= f.number_field :total_bathrooms, class: "form-control", id: "inputEmail" %>
<div class="checkbox">
<label>
</label>
</div>
</div>
</div>
<div class="form-group">
<label for="inputPassword" class="col-lg-2 control-label">Address</label>
<div class="col-lg-10">
<%= f.text_field :address, class: "form-control", id: "inputEmail" %>
<div class="checkbox">
<label>
</label>
</div>
</div>
</div>
<div class="form-group">
<label for="inputPassword" class="col-lg-2 control-label">City</label>
<div class="col-lg-10">
<%= f.text_field :city, class: "form-control", id: "inputEmail" %>
<div class="checkbox">
<label>
</label>
</div>
</div>
</div>
<div class="form-group">
<label for="inputPassword" class="col-lg-2 control-label">State</label>
<div class="col-lg-10">
<%= f.text_field :state, class: "form-control", id: "inputEmail" %>
<div class="checkbox">
<label>
</label>
</div>
</div>
</div>
<div class="form-group">
<label for="inputPassword" class="col-lg-2 control-label">Zip code</label>
<div class="col-lg-10">
<%= f.text_field :zip_code, class: "form-control", id: "inputEmail" %>
<div class="checkbox">
<label>
</label>
</div>
</div>
</div>
<div class="form-group">
<label for="textArea" class="col-lg-2 control-label">Description</label>
<div class="col-lg-10">
<%= f.text_area :description, class: "form-control", id: "textArea" %>
</div>
</div>
<div class="form-group">
<label for="textArea" class="col-lg-2 control-label">Invite your roommates</label>
<div class="col-lg-10">
<%= text_area_tag :emails %>
</div>
</div>
<div class="form-group">
<div class="col-lg-10 col-lg-offset-2">
<br><%= f.submit "Claim your place", class: "btn btn-primary" %>
</div>
</div>
</fieldset>
</form>
<% end %>
invites_controller.rb
class InvitesController < ApplicationController
def proceed
@invite = Invite.find_by_token(params[:token])
if @invite
InviteMailer.invite_notification(@invite, @invite.user).deliver
redirect_to property_path(@invite.property)
end
end
end
mail_invite.rb
class MailInvite
def initialize(emails, property)
@property = Property.find(params[:id])
@emails = separate_emails(email)
end
def call
@emails.each do |email|
invite = create_invite(email)
InviteMailer.invite_notification(@invite, @invite.user).deliver
end
end
private
def create_invite(email)
user = User.new(email: email)
@property.invites.create(user: user)
end
def separate_emails
params[:emails].gsub(' ','').split(',') if params[:emails].present?
end
end
routes.rb
Domimvp::Application.routes.draw do
get "invites/create"
devise_for :admin_users, ActiveAdmin::Devise.config
ActiveAdmin.routes(self)
get "comments/create"
get "faq" => "faq#index", as: :faq_index
get "how-it-works" => "about#index", as: :about_index
get "mission" => "mission#index", as: :mission_index
get "help" => "help#index", as: :help_index
get "inbox" => "dashboard#index", as: :dashboard_index
post 'twilio/voice' => 'twilio#voice'
match "sms/inbound" => "sms#inbound", via: [:get, :post]
# /beta_key/:invite_code
get 'invite/:token' => 'invites#proceed', as: :invite_token
resource :inbox, :controller => 'inbox', :only => [:show,:create]
resources :properties do
resource :image, only: [:create]
resources :rooms
end
resources :tenants
resources :dashboard, only: [:index]
resources :appointments do
resources :comments
end
resources :users
resources :listings do
resources :appointments
end
resources :profiles
resources :subletters
devise_for :users, controllers: {registrations: "users/registrations", sessions: "users/sessions", passwords: "users/passwords", omniauth_callbacks: "users/omniauth_callbacks"}, skip: [:sessions, :registrations]
# The priority is based upon order of creation: first created -> highest priority.
# See how all your routes lay out with "rake routes".
# You can have the root of your site routed with "root"
root 'homes#index'
devise_scope :user do
get "login" => "devise/sessions#new", as: :new_user_session
post "login" => "devise/sessions#create", as: :user_session
delete "signout" => "devise/sessions#destroy", as: :destroy_user_session
get "signup" => "devise/registrations#new", as: :new_user_registration
post "signup" => "devise/registrations#create", as: :user_registration
put "signup" => "devise/registrations#update", as: :update_user_registration
get "account" => "devise/registrations#edit", as: :edit_user_registration
end
end
invite_mailer.rb
class InviteMailer < ActionMailer::Base
default from: "mike@domiapp.co"
def invite_notification(invite, user)
@invite = invite
@url = invite_token_url(@invite.token)
mail(to: @user.email, subject: 'An invite with your name on it!')
end
end
properties_controller.rb
class PropertiesController < ApplicationController
#->Prelang (scaffolding:rails/scope_to_user)
before_filter :require_user_signed_in, only: [:new, :edit, :create, :update, :destroy]
before_action :set_property, only: [:show, :edit, :update, :destroy]
# GET /properties
# GET /properties.json
def index
@properties = Property.all
end
# GET /properties/1
# GET /properties/1.json
def show
end
# GET /properties/new
def new
@property = Property.new
@property.images.build
end
# GET /properties/1/edit
def edit
@property = Property.includes(:images).find(params[:id])
end
# POST /properties
# POST /properties.json
def create
@emails = separate_emails
@property = Property.new(property_params)
MailInvite.new(params[:email].call, @property)
respond_to do |format|
if @property.save
current_user.properties << @property
current_user.save
format.html { redirect_to new_listing_path, notice: 'Your place was claimed successfully.' }
else
format.html { render action: 'new' }
format.json { render json: @property.errors, status: :unprocessable_entity }
end
end
end
def invite_roommates
end
# PATCH/PUT /properties/1
# PATCH/PUT /properties/1.json
def update
puts property_params.inspect
respond_to do |format|
if @property.update(property_params)
format.html { redirect_to @property, notice: 'Property was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: @property.errors, status: :unprocessable_entity }
end
end
end
# DELETE /properties/1
# DELETE /properties/1.json
def destroy
@property.destroy
respond_to do |format|
format.html { redirect_to properties_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_property
@property = Property.find(params[:id])
end
def separate_emails
params[:emails].gsub(/ /,'').split(',') if params[:emails].present?
end
# Never trust parameters from the scary internet, only allow the white list through.
def property_params
params.require(:property).permit(:title, :total_bedrooms, :total_bathrooms, :address, :city, :state, :zip_code, :description, :commute_to_campus_in_minutes, :emails, :listing_id, :tenant_id, :token, images_attributes: [:photo,:id, :_destroy])
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment