diff --git a/README.md b/README.md index be7780f..fda10e6 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,10 @@ # HasMagicFields +[![Gem Version](https://badge.fury.io/rb/has_magic_fields.png)](http://badge.fury.io/rb/has_magic_fields) -TODO: Write a gem description +Allows the addition of custom "magic" fields and attributes on a per-model +or per-parent-model basis. This is useful for situations where custom fields are +required for a specific model or for multi-user, multi-account environments where +accounts can customize attributes for subordinate models. ## Installation @@ -12,13 +16,143 @@ And then execute: $ bundle -Or install it yourself as: - $ gem install has_magic_fields +Create the migrations for MagicFileds and migrate: + + rails g has_magic_fields:install + rake db:migrate ## Usage -TODO: Write usage instructions here + + +### Model + +Sprinkle a little magic into an existing model: + +```ruby +class Person < ActiveRecord::Base + include HasMagicFields::Extend + has_magic_fields +end +``` + +Add magic fields to your model: + +```ruby +@charlie = Person.create(:email => "charlie@example.com") +@charlie.create_magic_fields(:name => "first_name") +``` + +Supply additional options if you have more specific requirements for your fields: + +```ruby +@charlie.charlie.create_magic_fields(:name => "last_name", :is_required => true) +@charlie.charlie.create_magic_fields(:name => "birthday", :datatype => :date) +@charlie.charlie.create_magic_fields(:name => "salary", :default => "40000", :pretty_name => "Yearly Salary") +``` + +The `:datatype` option supports: `:check_box_boolean`, `:date`, `:datetime`, `:integer` + +Use your new fields just like you would with any other ActiveRecord attribute: + +```ruby +@charlie.first_name = "Charlie" +@charlie.last_name = "Magic!" +@charlie.birthday = Date.today +@charlie.save +``` + +Find @charlie and inspect him: + +```ruby +@charlie = User.find(@charlie.id) +@charlie.first_name #=> "Charlie" +@charlie.last_name #=> "Magic!" +@charlie.birthday #=> # +@charlie.salary #=> "40000", this is from :salary having a :default +``` + +## Inherited Model + +A child can inherit magic fields from a parent. To do this, declare the parent +as having magic fields: + +```ruby +class Account < ActiveRecord::Base + include HasMagicFields::Extend + has_many :users + has_magic_fields +end +@account = Account.create(:name => "BobCorp") +``` + +And declare the child as having magic fields :through the parent. + +```ruby +class User < ActiveRecord::Base + include HasMagicFields::Extend + belongs_to :account + has_magic_fields :through => :account +end +@alice = User.create(:name => "alice", :account => @account) +``` + +To see all the magic fields available for a child from its parent: + +```ruby +@alice.magic_fields #=> [#,...] +@account.magic_fields #=> [#,...] +@product.magic_fields #=> [#,...] +@alice.account.magic_fields #=> [#,...] +@product.account.magic_fields #=> [#,...] +``` + +To add magic fields, go through the parent or child: + +```ruby +@alice.magic_fields.create(...) +@account.magic_fields.create(...) +``` + +All children for a given parent will have access to the same magic fields: + +```ruby +@alice.create_magic_fields(:name => "salary") +@alice.salary = "40000" + +@bob = User.create(:name => "bob", :account => @account) +# Magic! No need to add the column again! +@bob.salary = "50000" +``` + + +###Different Model Inherited from The Samle Model +the other modle Inherited from Account + +```ruby +class Product < ActiveRecord::Base + include HasMagicFields::Extend + belongs_to :account + has_magic_fields :through => :account +end +@product = Product.create(:name => "car", :account => @account) +``` +@product haven't salary magic field. +@product.salary + +##To Do + +Here's a short list of things that need to be done to polish up this gem: + +* more data_type sppuort +* Benchmark and optimize + +Maintainers +=========== + +* Davy Zhou([ikeqiao](http://github.com/ikeqiao)) + ## Contributing @@ -27,3 +161,10 @@ TODO: Write usage instructions here 3. Commit your changes (`git commit -am 'Add some feature'`) 4. Push to the branch (`git push origin my-new-feature`) 5. Create new Pull Request + + +Credits +======= + +* Thank you to Brandon Keene for his original work making this plugin. +* Thank you to latortuga for his original work making this plugin. [has_magic_fields](https://github.com/latortuga/has_magic_columns.git) diff --git a/has_magic_fields.gemspec b/has_magic_fields.gemspec index 124bda2..88becdb 100644 --- a/has_magic_fields.gemspec +++ b/has_magic_fields.gemspec @@ -8,9 +8,9 @@ Gem::Specification.new do |s| s.version = HasMagicFields::VERSION s.authors = ["ikeqiao"] s.email = ["zhzsi@126.com"] - s.description = %q{TODO: Write a gem description} - s.summary = %q{TODO: Write a gem summary} - s.homepage = "" + s.description = %q{Custom fields forActiveRecord models, suppport Rails 4!} + s.summary = %q{Allow addition of custom 'magic' fields to ActiveRecord models.} + s.homepage = "git@github.com:ikeqiao/has_magic_fields.git" s.license = "MIT" s.files = `git ls-files`.split($/) diff --git a/lib/has_magic_fields/extend.rb b/lib/has_magic_fields/extend.rb index 3a31925..b864894 100644 --- a/lib/has_magic_fields/extend.rb +++ b/lib/has_magic_fields/extend.rb @@ -42,8 +42,9 @@ module HasMagicFields self.magic_fields.create options.merge(type_scoped: type_scoped ) end - def magic_fields_with_scoped - magic_fields_without_scoped.where(type_scoped: self.class.name) + def magic_fields_with_scoped(type_scoped = nil) + type_scoped = type_scoped.blank? ? self.class.name : type_scoped.classify + magic_fields_without_scoped.where(type_scoped: type_scoped) end def method_missing(method_id, *args) @@ -61,13 +62,13 @@ module HasMagicFields end end - def magic_field_names - magic_fields.map(&:name) + def magic_field_names(type_scoped = nil) + magic_fields_with_scoped(type_scoped).map(&:name) end def valid?(context = nil) output = super(context) - magic_fields.each do |field| + magic_fields_with_scoped.each do |field| if field.is_required? validates_presence_of(field.name) end @@ -94,7 +95,7 @@ module HasMagicFields end def find_magic_field_by_name(attr_name) - magic_fields.to_a.find {|column| column.name == attr_name} + magic_fields_with_scoped.to_a.find {|column| column.name == attr_name} end def create_magic_attribute(magic_field, value) diff --git a/spec/has_magic_fields/magic_fileds_spec.rb b/spec/has_magic_fields/magic_fileds_spec.rb index b4cdaf6..35542b5 100644 --- a/spec/has_magic_fields/magic_fileds_spec.rb +++ b/spec/has_magic_fields/magic_fileds_spec.rb @@ -8,10 +8,6 @@ describe HasMagicFields do @charlie = Person.create(name: "charlie") end - after(:each) do - @charlie.destroy! - end - it "initializes magic fields correctly" do expect(@charlie).not_to be(nil) expect(@charlie.class).to be(Person) @@ -87,13 +83,7 @@ describe HasMagicFields do before(:each) do @account = Account.create(name:"important") @alice = User.create(name:"alice", account: @account ) - @sample = Sample.create(name:"TR", account: @account ) - end - - after(:each) do - @sample.destroy! - @alice.destroy! - @account.destroy! + @product = Product.create(name:"TR", account: @account ) end it "initializes magic fields correctly" do @@ -106,16 +96,15 @@ describe HasMagicFields do expect(@alice.magic_fields).not_to be(nil) end - it "allows adding a magic field to the child" do + it "allows adding a magic field from the child" do @alice.create_magic_filed(:name => 'salary') expect(@alice.magic_fields.length).to eq(1) expect(lambda{@alice.salary}).not_to raise_error - - expect(lambda{@account.salary}).not_to raise_error + expect(lambda{@account.salary}).to raise_error end - it "allows adding a magic field to the parent" do - @account.create_magic_filed(:name => 'age') + it "allows adding a magic field from the parent" do + @account.create_magic_filed(:name => 'age',type_scoped: "User") expect(lambda{@alice.age}).not_to raise_error end @@ -125,13 +114,17 @@ describe HasMagicFields do expect(lambda{@alice.birthday}).not_to raise_error @bob.birthday = "2014-07-29" expect(@bob.save).to be(true) - expect(@account.birthday).to be(nil) expect(@alice.birthday).to be(nil) @alice.birthday = "2013-07-29" expect(@alice.save).to be(true) expect(@alice.birthday).not_to eq(@bob.birthday) end + it "defferent model has defferent scope" do + @alice.create_magic_filed(:name => 'salary') + expect(lambda{@alice.salary}).not_to raise_error + expect(lambda{@product.salary}).to raise_error + end it "validates_uniqueness_of name in all models object" do @alice.create_magic_filed(:name => 'salary') @@ -140,12 +133,10 @@ describe HasMagicFields do expect(lambda{@alice.create_magic_filed(:name => 'salary')}).to raise_error expect(@alice.magic_fields.length).to eq(1) expect(before_fields_count).to eq(MagicField.count) - @bob = User.create(name:"bob", account: @account ) expect(lambda{@bob.create_magic_filed(:name => 'salary')}).to raise_error - expect(lambda{@sample.create_magic_filed(:name => 'salary')}).not_to raise_error + expect(lambda{@product.create_magic_filed(:name => 'salary')}).not_to raise_error expect(lambda{@account.create_magic_filed(:name => 'salary')}).not_to raise_error - end end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 8525283..e6238f1 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -22,7 +22,7 @@ end ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:") # ActiveRecord::Base.configurations = true -ActiveRecord::Base.logger = Logger.new(STDOUT) +# ActiveRecord::Base.logger = Logger.new(STDOUT) ActiveRecord::Schema.verbose = false @@ -41,7 +41,7 @@ ActiveRecord::Schema.define do t.column "name", :text end - create_table "samples", :force => true do |t| + create_table "products", :force => true do |t| t.column "name", :text t.column "account_id", :integer end @@ -73,7 +73,7 @@ RSpec.configure do |config| has_magic_fields :through => :account end - class Sample < ActiveRecord::Base + class Product < ActiveRecord::Base include HasMagicFields::Extend belongs_to :account has_magic_fields :through => :account -- libgit2 0.21.0