
Security News
Oxlint Introduces Type-Aware Linting Preview
Oxlint’s new preview brings type-aware linting powered by typescript-go, combining advanced TypeScript rules with native-speed performance.
Inspired by [7 Patterns to Refactor Fat ActiveRecord Models] (http://blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models/) and SRP
What it does?
Add this line to your application's Gemfile:
gem 'rfo', github: 'petergebala/rfo'
And then execute:
$ bundle
Or install it yourself as:
$ gem install rfo # Not yet!
It works great with Draper and Simple Form
Define simple model with relations eventually callbacks:
class Organisation < ActiveRecord::Base
WEBSITE_REGEXP = /[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?/ix
APPLY_FOR = [:under_2000, :over_2000]
belongs_to :grant, touch: true
has_one :address, as: :entity, dependent: :destroy
has_one :contact, as: :entity, dependent: :destroy
has_one :user, through: :grant
after_create :create_address
after_create :create_contact
delegate :postcode, to: :address
end
Define form:
# app/forms/organisation_form.rb
class OrganisationForm < RFO::Base
# About your organisation
attribute :amount_apply_for, String
attribute :organisation_name, String
attribute :charity_number, String
# Your address details
attribute :first_name, String
attribute :last_name, String
attribute :position, String
attribute :address_line_1, String
attribute :address_line_2, String
attribute :address_line_3, String
attribute :town, String
attribute :county, String
attribute :postcode, String
# Your contact details
attribute :phone_number, String
attribute :mobile_number, String
# Your organisation
attribute :website, String
attribute :description, String
# Validations
validates :description, presence: true, length: { maximum: 2000 }
validates :amount_apply_for, presence: true, inclusion: { in: Organisation::APPLY_FOR.map(&:to_s) }
validates :organisation_name, presence: true, length: { maximum: 255 }
validates :first_name, presence: true, length: { maximum: 255 }
validates :last_name, presence: true, length: { maximum: 255 }
validates :address_line_1, presence: true, length: { maximum: 255 }
validates :town, presence: true, length: { maximum: 255 }
validates :postcode, presence: true, length: { maximum: 10 }, format: { with: Address::POSTCODE_REGEXP }
validates :phone_number, presence: true, length: { maximum: 20 }, format: { with: Contact::PHONE_NUMBER_REGEXP }
validates :mobile_number, length: { maximum: 20 }, format: { with: Contact::PHONE_NUMBER_REGEXP }, allow_blank: true
validates :website, length: { maximum: 255 }, format: { with: Organisation::WEBSITE_REGEXP }, allow_blank: true
private
def assign_defaults
@grant.current_step = :organisation_details
organisation_contact = @organisation.contact
organisation_address = @organisation.address
user_contact = @organisation.user.contact
user_address = @organisation.user.address
# Initialize with values from diffrent models
self.organisation_name ||= @organisation.name
self.first_name ||= organisation_contact.first_name || user_contact.first_name
self.last_name ||= organisation_contact.last_name || user_contact.last_name
self.position ||= organisation_contact.position || user_contact.position
self.phone_number ||= organisation_contact.phone_number || user_contact.phone_number
self.mobile_number ||= organisation_contact.mobile_number || user_contact.mobile_number
self.address_line_1 ||= organisation_address.address_line_1 || user_address.address_line_1
self.address_line_2 ||= organisation_address.address_line_2 || user_address.address_line_2
self.address_line_3 ||= organisation_address.address_line_3 || user_address.address_line_3
self.town ||= organisation_address.town || user_address.town
self.county ||= organisation_address.county || user_address.county
self.postcode ||= organisation_address.postcode || user_address.postcode
end
def persist!
ActiveRecord::Base.transaction do |t|
@organisation.name = self.organisation_name
@organisation.amount_apply_for = self.amount_apply_for
@organisation.charity_number = self.charity_number
@organisation.website = self.website
@organisation.description = self.description
@contact = @organisation.contact
@contact.first_name = self.first_name
@contact.last_name = self.last_name
@contact.position = self.position
@contact.phone_number = self.phone_number
@contact.mobile_number = self.mobile_number
@address = @organisation.address
@address.address_line_1 = self.address_line_1
@address.address_line_2 = self.address_line_2
@address.address_line_3 = self.address_line_3
@address.town = self.town
@address.county = self.county
@address.postcode = self.postcode
@grant.current_step = @grant.next_step
@organisation.save!
@contact.save!
@address.save!
@grant.save!
end
end
end
Define skinny controller:
class OrganisationDetailsController < ApplicationController
before_filter :set_grant
respond_to :html
before_filter :set_organisation, only: [:edit, :update]
def edit ; end
def update
flash[:notice] = 'Organisation details saved!' if @organisation_form.update_attributes(organisations_params)
respond_with @organisation_form, location: @grant.current_path
end
private
def set_grant
@grant = current_user.grants.find(params[:grant_id]).decorate
end
def set_organisation
@organisation = @grant.organisation.decorate
@organisation_form = OrganisationForm.new(organisation: @organisation,
grant: @grant)
end
def organisations_params
params.require(:organisation_form).permit(:amount_apply_for,
:organisation_name,
:charity_number,
:first_name,
:last_name,
:position,
:address_line_1,
:address_line_2,
:address_line_3,
:town,
:county,
:postcode,
:phone_number,
:mobile_number,
:website,
:description)
end
end
And clean view!
= simple_form_for @organisation_form, url: grant_organisation_details_path(@grant), method: :patch do |f|
= f.error_notification
h2 About Your Organisation
fieldset
= f.input :amount_apply_for,
collection: @organisation.amount_apply_for_buttons_for_views,
as: :radio_buttons,
wrapper: :bootstrap_group_horizontal
= f.input :organisation_name
= f.input :charity_number
h2 Your Address Details
fieldset
= f.input :first_name
= f.input :last_name
= f.input :position
= f.input :address_line_1
= f.input :address_line_2
= f.input :address_line_3
= f.input :town
= f.input :county
= f.input :postcode
h2 Your Contact Details
fieldset
= f.input :phone_number
= f.input :mobile_number
h2 Your Organisation
fieldset
= f.input :website, as: :addon, input_html: { addon_text: 'http://' }
= f.input :description, as: :text
h2 Proceed
fieldset
= f.button :submit
Becasue Form Object is just plain ruby class you can:
git checkout -b my-new-feature
)git commit -am 'Add some feature'
)git push origin my-new-feature
)FAQs
Unknown package
We found that rfo demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Oxlint’s new preview brings type-aware linting powered by typescript-go, combining advanced TypeScript rules with native-speed performance.
Security News
A new site reviews software projects to reveal if they’re truly FOSS, making complex licensing and distribution models easy to understand.
Security News
Astral unveils pyx, a Python-native package registry in beta, designed to speed installs, enhance security, and integrate deeply with uv.