Austin Story

Ruby, Rails and Javascript Blog

Powered by Genesis

Creating private_attr_reader in Ruby

February 16, 2016 By Austin Story Leave a Comment

In my current project we use a whole lot of plain ruby objects. One day I was looking at them and noticed that we follow this pattern for just about everything.
[ruby]
module MyModule
class MyClass
attr_reader :params

def initialize(params:)
@params = params
end
def call
params.do_things
end
end
end
[/ruby]

The params attr_reader is used so that we don’t have to use @params throughout the object. I got used to this format and like that my ide looks better without all the @vars everywhere. But I think that it is a false contract. The public method for our objects is `call` and is all that we ever intend for someone else to use. However, the user of attr_reader says that this is a public method.

To get around this, i decided to add a quick patch so that we could still have the use of the params method locally for instance variable lookup but keep it private so that noone accidentally starts using it only for us to change it in the future.

Here is the patch I added to Object. I didn’t go all the way down to Kernel because all of our objects inherit from Object.

[ruby]
class Object
def self.private_attr_reader(*args)
args.each do |arg|
define_method(arg) { instance_variable_get("@#{arg}") }
private arg
end
end
end
[/ruby]

After adding this patch to Object we can now do this in our object and var1 and var2 would both be have attr_readers that are private to the class.

[ruby]
private_attr_reader :var1, var2
[/ruby]

Filed Under: Ruby, Ruby on Rails Tagged With: Metaprogramming, monkey patching, ruby

Digging Stripe using Map and Select

January 7, 2016 By Austin Story Leave a Comment

Had a client who had a bad subscription plan in their stripe account that was applied over a year ago.  They have enough volume that it didn’t make sense to go through the web admin to clean up the data so we cleaned it up using the Stripe ruby gem.  Here is the process that I went through to discover the correct commands to issue.

To start, this was a promotional amount that was only applied for a few days in january for the start of the year.  So off the bat I wanted to narrow it down to the related customers.

[ruby]
users = User.where("created_at >= ?", 1.year.ago).where("created_at <?", 330.days.ago)

paying_users = users.where.not(stripe_customer_id: nil)

customer_ids = users.map(&:stripe_payment_id)
[/ruby]

Now that we had the customer ids from tripe i wanted to see what the data looked like

[ruby]
Stripe::Customer.retrieve(customer_ids.first)
[/ruby]

the Stripe::Customer that is returned looks and acts like an open struct or hashie mash. So you can call methods on it similar to javascript objects in order to get values of a key that is in the object.

I didn’t know the specific name of the subscription (didn’t have web access). So needed to discover what it was called. I remembered it had the word special in it.

Next is to find the specific customers that we need to look at

[ruby]
stripe_customers = customer_ids.map{|c| Stripe::Customer.retrieve(c)}
stripe_customers.select(&:subscription).map{|c| c.subscription.plan.id}.uniq
[/ruby]

This returns an array of [‘premium’, ‘othersubscriptions’,….,’newyearsspecial’]. So i know that it is the newyearsspecial that i need to update.

[ruby]
special_customers = stripe_customers.select(&:subscription).select{|c| c.subscription.plan.id == ‘newyearsspecial’}

special_subscriptions = special_customers.map{|c| c.subscription.id}

special_subscriptions = special_customers.map(&:subscription)
[/ruby]

The next part is a little vague, in the documentation it says to set the ‘at_period_end’ parameter to true in order to delete it and keep it active until the end of the subscription, so i just did both.

[ruby]
special_subscriptions.each do |subscription|
subscription.at_period_end = true
subscription.delete(at_period_end: true)
end
[/ruby]

Now all of the subscriptions will expire at the end of the year, Yeah!

Filed Under: Ruby on Rails, Stripe Tagged With: API, ruby, Stripe, Stripe APi, Stripe ruby

How to create a User and an Account in one form with Devise

November 22, 2015 By Austin Story Leave a Comment

Most of my apps these days that are pure html with a backend are written in Ruby on Rails and use the Devise engine to handle password and account creation type things.

For this example we will be assume a few things

  • You have rails 4+ and Devise Setup
  • Devise routes are setting the registration controller as your custom controller.
  • models are User and Account
  • User belongs_to Account (so User has an account_id)
  • User responds to set_admin to deal with however admin is setup.

I was reading through the source the other day and saw this block option in the RegistrationsController for devise

[ruby]

class Devise::RegistrationsController

# POST /resource
def create
build_resource(sign_up_params)
resource.save

yield resource if block_given?
#other devise stuff
respond_with resource
end
end
[/ruby]

 

[ruby]yield resource if block_given[/ruby]

means that we can pass some code in as a block (which is just an anonymous function) that will receive the resource as a parameter.

 

In your resources controller you can override like this

[ruby]

class RegistrationsController < Devise::RegistrationsController
def create
super {|user| user.create_account }
end
end

[/ruby]

So with this code, super sends the block up the chain.  So the result is that when we get to the yield resource, the resources receives the message ‘create_account’.

This is great, now we are able to delegate all of our registration logic to devise.  But wait, what if we now want to set the user as admin on the account and make sure that it is all wrapped up in a transaction?  That is easy, just expand the block.

[ruby]
def create
ActiveRecord::Base.transaction do
super do |user|
user.create_account
user.set_admin
end
end
end
[/ruby]

At this point, we have fulfilled the feature that we create the account along with the user and set that user as the admin on the account, so ship the feature!

Filed Under: Devise, Ruby, Ruby on Rails Tagged With: Devise, Rails, ruby, ruby on Rails, Ruby super

  • « Previous Page
  • 1
  • 2
  • 3
  • 4
  • Next Page »

Categories

  • AngularJS
  • Books
  • Devise
  • Elasticsearch
  • ES6
  • Information Security
  • Integrations
  • Javascript
  • Linux
  • Minitest
  • PhoneGap
  • Programming
  • React
  • Redux
  • Ruby
  • Ruby on Rails
  • Stripe
  • Testing
  • Theory
  • TypeScript
  • Uncategorized
  • Vue
  • Webpack