Casey Provost

Joined

1,840 Experience
3 Lessons Completed
2 Questions Solved

Activity

Posted in How to use Uppy with ActiveStorage Discussion

Anyone figure out how to test Uppy with Capybara without doing javascript hacks in your test?

Posted in Row-level Multitenancy with ActsAsTenant Discussion

Honestly I don't even do pure row level tenancy most of the time, just query by top level account, company, etc. I only move to multi-tenant when clients require it or for white-labeled SAAS solutions.

What does your code like that receives and parses the email?

My assumption: A conversation is only between 2 people

So I think one thing that would make this easier to by putter an author_id on a message. This way you know who composed and sent the message. If you do this then you can just send a notification on the after_create callback of the Message model. In that callback I would do something like.

def after_create
  UserMailer.new_message(self.id).deliver_later
end

class UserMailer
  def new_message(message_id)
        message = Message.includes(conversation: [:sender, :recipient]).find(message_id)
        recipient = message.conversation.sender_id == message.author_id ? message.conversation.recipient : message.conversation.sender
        mail(to: recipient.email)
    end
end

Posted in Editable emails templates

You are most welcome. The resources I listed are not recommendations to install and use :) They are reference material so you can see examples of how others have done similar tasks concretely and with documentation. The idea being if you need to rebuild all or a portion of those solutions you have some pretty solid inspiration.

Talor, would you mind posting the message model as well?

Posted in Editable emails templates

If you are just letting them change a few things like the subject, maybe disclaimer text, etc you can probably get by with a user_email_templates table with columns that map to those variables. Then when you go to send the email...simply load the template and inject the variables (with erb)

Posted in Editable emails templates

This is a pretty large project :) I assume you want a model called email_templates. Then I think you want a "rich_text_field" with name body_html (or similar). Then you will want to use something like the liquid templating language to parse and replace {{ variable_name }} when rendering said template.

Resources

Posted in Companies / Employees / Products

So it sounds like you have a join table possibly missing called company_employees or company_users that would allow users to belong to multiple companies. That should give you the base foundation for users being able to pull a list of their companies and a company knowing all of it's users.

As far as invitations are concerned there are a few ways to do this. One way is to create a model called company_invitation that has a inviter_id, user_id, company_id, token:string, and accepted:boolean. This would give you the ability to send out unique links (with token) that users can click to accept invitations.

So far so good right? We have the data tied together between users and companies and the data storage for how to invite users to those companies...cool.

The next part is just a little bit harder. Basically you would have a UI where a user would enter an email address and click "invite". The controller/business-logic needs to determine if that email belongs to an existing user or not. If it does you can just send that user a link that they click and the logic to handle that is as simple as marking the invitation as accepted and assigning the user_id to it (for tracking purposes) and creating that company/user join model we discussed earlier. However...if the email address does not belong to the user than that "accept" page has to be less automatic. Instead of simply accepting, we have to collect the fields required by a user so we can create one, then post that form to the controller and create/validate the user, accept the invite, and send them on their way.

I hope this helps, but if you need more deets then hit me up on the slack GoRails community or on here.

Posted in Best way to create a report/spam button?

@ryan it is pretty straight-forward. Typically you count how many times that button is pushed (if it is user facing) and then start applying rules based on that count to auto-remove and what not. You could do that with a simple counter on the model in question. Just have it do it via AJAX and it will be a smooth and nice interaction.

On the other hand if this is admin facing and just flags the comment/post then I would create a table called flags or something like that and it could store the type as a string ("spam" or "reported") and then contain the model name and id (polymorphic). This would give you a list of all the comments/posts that had been flagged or reported and allow you to do whatever you wanted with them.

In actuality the second approach is probably the most flexible since it allows any model to be reported or be considered a spam entry. The only difference is you would be the counter on that model if the UX was user facing.

Anyway, that is a couple of ways to do it. Hope it helps!

@luca you are definitely fine in accessing tenant_id in the session. It is super common practice infact to store the current_user that way as well. As long as you are serving over https you are fine and sessions are notoriously hard to break into.

That said, you probably have the name/subdomain of the tenant in the subdomain and therefore never really need to store that info in the session since it is unique enough to identify the apartment directly it is effectively the tenant_id right?

If I am missing something feel free to hit me back on here. Have a good one!

So Rails has some interesting behaviors to learn when saving models with join models. Most noteably you can save the join by adding the secondary child and passing it to the array on the parent. For example:

  note = Note.first
    tag = Tag.create(name: 'foo')
    note.tags << tag

Or you can do what the module does below here and build up all the objects and save them in a transaction (for proper rollback behavior).

module Taggable
  extends ActiveSupport::Concern

  included do
    has_many :taggings, as: :taggable
    has_many :tags, through: :taggings
  end

  def tag_list
    tags.pluck(:name)
  end

  def add_tag(tag_name)
    self.class.transaction do
      tagging = taggings.new
      tagging.tags.new(name: tag_name)
      tagging.save
    end
  end
end

class Note < ApplicationRecord
  include Taggable

  belongs_to :notable, polymorphic: true
end

class TagsController < ApplicationController
  before_action :authenticate_user!

  def create
    if @taggable.add_tag(tag_params[:name])
      redirect_to @taggable, success: "New tag created."
    else
      render :new
    end
  end

  private

  def tag_params
    params.require(:tag).permit(:name)
  end
end

Posted in How do I create a virtual balance model in Rails?

You seem pretty close. balanace should a method on user. Something like this:

  def balance
        account_transactions.sum(:amount)
    end

You also want to make sure the record was created via User.first.account_transactions.count. If it is > than 0 then you should be all set. I hit you up on Skype too so we can chat a bit faster there and iterate if that works for you.

Posted in How do I create a virtual balance model in Rails?

You are real close. If you re-read my post I answer your last question ;) It is generally not recommended to store the balance as a single field on user because of read/write concurrency issues. The sum method I have you would work perfectly for current balance purposes. Everything else for the most part looks fine, you just have some honing to do (adapting the cargo-culting).

Feel free to hit me up in the gorails slack community my username is caseyprovost. I would be happy to pair review with you via screenhero or similar.

Posted in How do I create a virtual balance model in Rails?

I would advise a transactions (or similar) model. You can then create a record with a "type" of "credit" of 100,000. You can then create a transaction for each purchase and sell event to track how that balance moves. This is give you nice auditability into how the balance changed and why. It is also very easy to get the balance in 1 query user.transactions.sum(:amount).

As far as performing the stock sale itself along with the balance update...it sounds like you have a classic service class situation. Example below.

class StockTransfer
  def initialize(user:, stock:, quantity:)
    @user = user
    @stock = stock
    @quantity = quantity
  end

  def call
    # insert logic here for the stock transfer

    # logic for the transaction
    @user.transactions.create!(
      type: (quantity > 0 ? 'credit' : 'debit'),
      event: (quantity > 0 ? 'purchase' : 'sale'),
      stock: @stock
    )
  end
end

Posted in Hiring Part Time Rails Devs

I went ahead and emailed you :) You can also find some of us in #gigs in the GoRails slack channel if you want to have a little faster interactions.