Skip to content

Instantly share code, notes, and snippets.

@structuralartistry
Last active August 6, 2016 19:54
Show Gist options
  • Select an option

  • Save structuralartistry/6ab5f0d3860dd7392cc9 to your computer and use it in GitHub Desktop.

Select an option

Save structuralartistry/6ab5f0d3860dd7392cc9 to your computer and use it in GitHub Desktop.

Revisions

  1. structuralartistry revised this gist Aug 6, 2016. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion gistfile1.rb
    Original file line number Diff line number Diff line change
    @@ -60,7 +60,7 @@ def self.included(base)
    end

    module ClassMethods
    def method_missing(meth, *args, &block)
    def lookup_for(*args, &block)
    if meth == :lookup_for
    define_lookup_methods_for(args, &block)
    else
  2. structuralartistry revised this gist Aug 5, 2016. 1 changed file with 2 additions and 1 deletion.
    3 changes: 2 additions & 1 deletion gistfile1.rb
    Original file line number Diff line number Diff line change
    @@ -27,7 +27,8 @@ class MyModel < ActiveRecord::Base
    > :ending

    # automatic id assignment
    m.function_type_id = 5
    m.function_type_id
    > 5

    # and also if want
    MyModel.get_function_type_by(:value, :none)
  3. structuralartistry revised this gist Aug 5, 2016. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion gistfile1.rb
    Original file line number Diff line number Diff line change
    @@ -207,7 +207,7 @@ class MyClass
    end

    describe 'implements rspec matcher for expect and shoulda' do
    debugger

    describe MyClass do
    it { MyClass.should implement_lookup_for(:record_type) }

  4. Dakmali "Alexi" Karuna renamed this gist Nov 25, 2014. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  5. Dakmali "Alexi" Karuna revised this gist Nov 24, 2014. 1 changed file with 10 additions and 1 deletion.
    11 changes: 10 additions & 1 deletion gistfile1.txt
    Original file line number Diff line number Diff line change
    @@ -30,9 +30,18 @@ end
    m.function_type_id = 5

    # and also if want
    MyModel.function_types.get_function_type_by(:value, :none)
    MyModel.get_function_type_by(:value, :none)
    > { id: 1, value: :none }

    # and
    MyModel.function_types
    > [
    { id: 1, value: :none },
    ...
    { id: 5, value: :ending }
    ]


    # also a spec helper to check for correct implementation
    expect(MyModel).to_implement_lookup_for(:function_type)

  6. Dakmali "Alexi" Karuna created this gist Nov 24, 2014.
    219 changes: 219 additions & 0 deletions gistfile1.txt
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,219 @@
    # the point of this is to add simple lookup table-like values to an AR model or really any other rails class.
    # it assumes that if you have a lookup named :some_lookup that the model will have a :some_lookup_id field

    # EXAMPLE:

    class MyModel < ActiveRecord::Base
    include Lookup

    lookup_for :function_type do
    [
    { id: 1, value: :none },
    { id: 2, value: :introduction },
    { id: 3, value: :instruction },
    { id: 4, value: :exercise },
    { id: 5, value: :ending }
    ]
    end
    end

    # then you get:

    # assignment
    m.function_type = :ending

    # direct accessor
    m.function_type
    > :ending

    # automatic id assignment
    m.function_type_id = 5

    # and also if want
    MyModel.function_types.get_function_type_by(:value, :none)
    > { id: 1, value: :none }

    # also a spec helper to check for correct implementation
    expect(MyModel).to_implement_lookup_for(:function_type)






    # CODE:

    module Lookup

    def self.included(base)
    base.extend(ClassMethods)
    end

    module ClassMethods
    def method_missing(meth, *args, &block)
    if meth == :lookup_for
    define_lookup_methods_for(args, &block)
    else
    super
    end
    end

    def define_lookup_methods_for(args)
    lookup_name = args[0]

    # class methods
    define_singleton_method("#{lookup_name}s") do
    yield
    end

    define_singleton_method("get_#{lookup_name}_by") do |key_to_search_on, value_to_match|
    # args[0] is the key in the hash we are seeking on, arbs[1] is the matching val
    lookup_names = self.send("#{lookup_name}s")
    lookup_names.select { |t| t[key_to_search_on] == value_to_match }.first
    end

    # instance methods for setter and getter based on the lookup_name + _id field assumption

    # getter
    define_method(lookup_name) do
    lookup_id = send("#{lookup_name}_id")
    lookup_data = self.class.send("#{lookup_name}s")
    matching_items = lookup_data.select { |item| item[:id] == lookup_id }
    matching_items.empty? ? nil : matching_items[0][:value]
    end

    # setter
    define_method("#{lookup_name}=") do |value|
    value = value.to_sym if value
    lookup_data = self.class.send("#{lookup_name}s")
    # should be only one match but we may refactor this later
    matching_items = lookup_data.select { |item| item[:value] == value }
    matching_items.empty? ? item = nil : item = matching_items[0][:id]
    send("#{lookup_name}_id=", item)
    end
    end

    end

    end


    # SPECS
    require 'spec_helper'

    describe Lookup do

    # in theory this should work with an active record query or whatever code returning an appropriate array
    # of hashes in the result in the block passed, but not going this far to test right now
    describe 'with an object for lookup data' do

    class MyClass
    include Lookup

    # this could be AR attribute or other
    attr_accessor :record_type_id

    # the second param could be from anywhere - just an array of hashes with the right values
    # in theory this could be an executable AR query
    # also note that we dont have an :order attribute, as we leave leeway for the developer to change the
    # order of the array of hashes as desired
    # also note that the reference in the second param must be coded to the root of app class structure and not
    # refer implicitly to self as self can mean different things when the code in this module is executed
    # note that the lookup name must be singular
    lookup_for :record_type do
    [
    { id: 1, value: :first_value, friendly: 'something friendly', notes: 'notes are here' },
    { id: 2, value: :second_value, friendly: 'something friendly', notes: 'notes are here' },
    { id: 3, value: :third_value, friendly: 'something friendly', notes: 'notes are here' }
    ]
    end

    end

    let(:my_class_instance) { MyClass.new }

    describe 'created instance methods' do

    describe 'setter attribute' do

    it 'creates instance method on class' do
    expect(my_class_instance.respond_to?(:record_type=)).to eq true
    end

    it 'assigns the set value to the [lookup]_id attribute' do
    expect(my_class_instance.record_type).to eq nil
    my_class_instance.record_type = :second_value
    expect(my_class_instance.record_type).to eq :second_value
    end

    it 'assigns string' do
    my_class_instance.record_type = 'third_value'
    expect(my_class_instance.record_type).to eq :third_value
    end

    it 'can clear the value' do
    my_class_instance.record_type = :second_value
    expect(my_class_instance.record_type_id).to eq 2
    my_class_instance.record_type = nil
    expect(my_class_instance.record_type).to eq nil
    end

    end

    describe 'getter attribute' do

    it 'creates instance method on class' do
    expect(my_class_instance.respond_to?(:record_type)).to eq true
    end

    it 'returns the set value from the [lookup]_id attribute' do
    my_class_instance.record_type_id = 3
    expect(my_class_instance.record_type).to eq :third_value
    end

    end

    end

    describe 'create class methods' do

    describe 'lookup list' do

    it 'creates class method on class' do
    expect(MyClass.respond_to?(:record_types)).to eq true
    end

    it 'returns the results as an array of hashes' do
    record_types = MyClass.record_types
    expect(record_types.class).to eq Array
    expect(record_types[0].class).to eq Hash
    end

    end

    it 'has lookup shortcut for finding data' do
    expect(MyClass.get_record_type_by(:value, :third_value)).to eq MyClass.record_types[2]
    end

    end

    describe 'implements rspec matcher for expect and shoulda' do
    debugger
    describe MyClass do
    it { MyClass.should implement_lookup_for(:record_type) }

    it 'do it in a bigger block' do
    MyClass.should implement_lookup_for(:record_type)
    end

    end

    it { expect(MyClass).to implement_lookup_for(:record_type) }

    end

    end

    end