Commit 2e70600e09740b5c6b62e97f60c8669c9983615b

Authored by ikeqiao
1 parent c32bea85
Exists in master

defferent model has defferent scope

README.md
1 1 # HasMagicFields
  2 +[![Gem Version](https://badge.fury.io/rb/has_magic_fields.png)](http://badge.fury.io/rb/has_magic_fields)
2 3  
3   -TODO: Write a gem description
  4 +Allows the addition of custom "magic" fields and attributes on a per-model
  5 +or per-parent-model basis. This is useful for situations where custom fields are
  6 +required for a specific model or for multi-user, multi-account environments where
  7 +accounts can customize attributes for subordinate models.
4 8  
5 9 ## Installation
6 10  
... ... @@ -12,13 +16,143 @@ And then execute:
12 16  
13 17 $ bundle
14 18  
15   -Or install it yourself as:
16 19  
17   - $ gem install has_magic_fields
  20 +Create the migrations for MagicFileds and migrate:
  21 +
  22 + rails g has_magic_fields:install
  23 + rake db:migrate
18 24  
19 25 ## Usage
20 26  
21   -TODO: Write usage instructions here
  27 +
  28 +
  29 +### Model
  30 +
  31 +Sprinkle a little magic into an existing model:
  32 +
  33 +```ruby
  34 +class Person < ActiveRecord::Base
  35 + include HasMagicFields::Extend
  36 + has_magic_fields
  37 +end
  38 +```
  39 +
  40 +Add magic fields to your model:
  41 +
  42 +```ruby
  43 +@charlie = Person.create(:email => "charlie@example.com")
  44 +@charlie.create_magic_fields(:name => "first_name")
  45 +```
  46 +
  47 +Supply additional options if you have more specific requirements for your fields:
  48 +
  49 +```ruby
  50 +@charlie.charlie.create_magic_fields(:name => "last_name", :is_required => true)
  51 +@charlie.charlie.create_magic_fields(:name => "birthday", :datatype => :date)
  52 +@charlie.charlie.create_magic_fields(:name => "salary", :default => "40000", :pretty_name => "Yearly Salary")
  53 +```
  54 +
  55 +The `:datatype` option supports: `:check_box_boolean`, `:date`, `:datetime`, `:integer`
  56 +
  57 +Use your new fields just like you would with any other ActiveRecord attribute:
  58 +
  59 +```ruby
  60 +@charlie.first_name = "Charlie"
  61 +@charlie.last_name = "Magic!"
  62 +@charlie.birthday = Date.today
  63 +@charlie.save
  64 +```
  65 +
  66 +Find @charlie and inspect him:
  67 +
  68 +```ruby
  69 +@charlie = User.find(@charlie.id)
  70 +@charlie.first_name #=> "Charlie"
  71 +@charlie.last_name #=> "Magic!"
  72 +@charlie.birthday #=> #<Date: 4908497/2,0,2299161>
  73 +@charlie.salary #=> "40000", this is from :salary having a :default
  74 +```
  75 +
  76 +## Inherited Model
  77 +
  78 +A child can inherit magic fields from a parent. To do this, declare the parent
  79 +as having magic fields:
  80 +
  81 +```ruby
  82 +class Account < ActiveRecord::Base
  83 + include HasMagicFields::Extend
  84 + has_many :users
  85 + has_magic_fields
  86 +end
  87 +@account = Account.create(:name => "BobCorp")
  88 +```
  89 +
  90 +And declare the child as having magic fields :through the parent.
  91 +
  92 +```ruby
  93 +class User < ActiveRecord::Base
  94 + include HasMagicFields::Extend
  95 + belongs_to :account
  96 + has_magic_fields :through => :account
  97 +end
  98 +@alice = User.create(:name => "alice", :account => @account)
  99 +```
  100 +
  101 +To see all the magic fields available for a child from its parent:
  102 +
  103 +```ruby
  104 +@alice.magic_fields #=> [#<MagicColumn>,...]
  105 +@account.magic_fields #=> [#<MagicColumn>,...]
  106 +@product.magic_fields #=> [#<MagicColumn>,...]
  107 +@alice.account.magic_fields #=> [#<MagicColumn>,...]
  108 +@product.account.magic_fields #=> [#<MagicColumn>,...]
  109 +```
  110 +
  111 +To add magic fields, go through the parent or child:
  112 +
  113 +```ruby
  114 +@alice.magic_fields.create(...)
  115 +@account.magic_fields.create(...)
  116 +```
  117 +
  118 +All children for a given parent will have access to the same magic fields:
  119 +
  120 +```ruby
  121 +@alice.create_magic_fields(:name => "salary")
  122 +@alice.salary = "40000"
  123 +
  124 +@bob = User.create(:name => "bob", :account => @account)
  125 +# Magic! No need to add the column again!
  126 +@bob.salary = "50000"
  127 +```
  128 +
  129 +
  130 +###Different Model Inherited from The Samle Model
  131 +the other modle Inherited from Account
  132 +
  133 +```ruby
  134 +class Product < ActiveRecord::Base
  135 + include HasMagicFields::Extend
  136 + belongs_to :account
  137 + has_magic_fields :through => :account
  138 +end
  139 +@product = Product.create(:name => "car", :account => @account)
  140 +```
  141 +@product haven't salary magic field.
  142 +@product.salary
  143 +
  144 +##To Do
  145 +
  146 +Here's a short list of things that need to be done to polish up this gem:
  147 +
  148 +* more data_type sppuort
  149 +* Benchmark and optimize
  150 +
  151 +Maintainers
  152 +===========
  153 +
  154 +* Davy Zhou([ikeqiao](http://github.com/ikeqiao))
  155 +
22 156  
23 157 ## Contributing
24 158  
... ... @@ -27,3 +161,10 @@ TODO: Write usage instructions here
27 161 3. Commit your changes (`git commit -am 'Add some feature'`)
28 162 4. Push to the branch (`git push origin my-new-feature`)
29 163 5. Create new Pull Request
  164 +
  165 +
  166 +Credits
  167 +=======
  168 +
  169 +* Thank you to Brandon Keene for his original work making this plugin.
  170 +* Thank you to latortuga for his original work making this plugin. [has_magic_fields](https://github.com/latortuga/has_magic_columns.git)
... ...
has_magic_fields.gemspec
... ... @@ -8,9 +8,9 @@ Gem::Specification.new do |s|
8 8 s.version = HasMagicFields::VERSION
9 9 s.authors = ["ikeqiao"]
10 10 s.email = ["zhzsi@126.com"]
11   - s.description = %q{TODO: Write a gem description}
12   - s.summary = %q{TODO: Write a gem summary}
13   - s.homepage = ""
  11 + s.description = %q{Custom fields forActiveRecord models, suppport Rails 4!}
  12 + s.summary = %q{Allow addition of custom 'magic' fields to ActiveRecord models.}
  13 + s.homepage = "git@github.com:ikeqiao/has_magic_fields.git"
14 14 s.license = "MIT"
15 15  
16 16 s.files = `git ls-files`.split($/)
... ...
lib/has_magic_fields/extend.rb
... ... @@ -42,8 +42,9 @@ module HasMagicFields
42 42 self.magic_fields.create options.merge(type_scoped: type_scoped )
43 43 end
44 44  
45   - def magic_fields_with_scoped
46   - magic_fields_without_scoped.where(type_scoped: self.class.name)
  45 + def magic_fields_with_scoped(type_scoped = nil)
  46 + type_scoped = type_scoped.blank? ? self.class.name : type_scoped.classify
  47 + magic_fields_without_scoped.where(type_scoped: type_scoped)
47 48 end
48 49  
49 50 def method_missing(method_id, *args)
... ... @@ -61,13 +62,13 @@ module HasMagicFields
61 62 end
62 63 end
63 64  
64   - def magic_field_names
65   - magic_fields.map(&:name)
  65 + def magic_field_names(type_scoped = nil)
  66 + magic_fields_with_scoped(type_scoped).map(&:name)
66 67 end
67 68  
68 69 def valid?(context = nil)
69 70 output = super(context)
70   - magic_fields.each do |field|
  71 + magic_fields_with_scoped.each do |field|
71 72 if field.is_required?
72 73 validates_presence_of(field.name)
73 74 end
... ... @@ -94,7 +95,7 @@ module HasMagicFields
94 95 end
95 96  
96 97 def find_magic_field_by_name(attr_name)
97   - magic_fields.to_a.find {|column| column.name == attr_name}
  98 + magic_fields_with_scoped.to_a.find {|column| column.name == attr_name}
98 99 end
99 100  
100 101 def create_magic_attribute(magic_field, value)
... ...
spec/has_magic_fields/magic_fileds_spec.rb
... ... @@ -8,10 +8,6 @@ describe HasMagicFields do
8 8 @charlie = Person.create(name: "charlie")
9 9 end
10 10  
11   - after(:each) do
12   - @charlie.destroy!
13   - end
14   -
15 11 it "initializes magic fields correctly" do
16 12 expect(@charlie).not_to be(nil)
17 13 expect(@charlie.class).to be(Person)
... ... @@ -87,13 +83,7 @@ describe HasMagicFields do
87 83 before(:each) do
88 84 @account = Account.create(name:"important")
89 85 @alice = User.create(name:"alice", account: @account )
90   - @sample = Sample.create(name:"TR", account: @account )
91   - end
92   -
93   - after(:each) do
94   - @sample.destroy!
95   - @alice.destroy!
96   - @account.destroy!
  86 + @product = Product.create(name:"TR", account: @account )
97 87 end
98 88  
99 89 it "initializes magic fields correctly" do
... ... @@ -106,16 +96,15 @@ describe HasMagicFields do
106 96 expect(@alice.magic_fields).not_to be(nil)
107 97 end
108 98  
109   - it "allows adding a magic field to the child" do
  99 + it "allows adding a magic field from the child" do
110 100 @alice.create_magic_filed(:name => 'salary')
111 101 expect(@alice.magic_fields.length).to eq(1)
112 102 expect(lambda{@alice.salary}).not_to raise_error
113   -
114   - expect(lambda{@account.salary}).not_to raise_error
  103 + expect(lambda{@account.salary}).to raise_error
115 104 end
116 105  
117   - it "allows adding a magic field to the parent" do
118   - @account.create_magic_filed(:name => 'age')
  106 + it "allows adding a magic field from the parent" do
  107 + @account.create_magic_filed(:name => 'age',type_scoped: "User")
119 108 expect(lambda{@alice.age}).not_to raise_error
120 109 end
121 110  
... ... @@ -125,13 +114,17 @@ describe HasMagicFields do
125 114 expect(lambda{@alice.birthday}).not_to raise_error
126 115 @bob.birthday = "2014-07-29"
127 116 expect(@bob.save).to be(true)
128   - expect(@account.birthday).to be(nil)
129 117 expect(@alice.birthday).to be(nil)
130 118 @alice.birthday = "2013-07-29"
131 119 expect(@alice.save).to be(true)
132 120 expect(@alice.birthday).not_to eq(@bob.birthday)
133 121 end
134 122  
  123 + it "defferent model has defferent scope" do
  124 + @alice.create_magic_filed(:name => 'salary')
  125 + expect(lambda{@alice.salary}).not_to raise_error
  126 + expect(lambda{@product.salary}).to raise_error
  127 + end
135 128  
136 129 it "validates_uniqueness_of name in all models object" do
137 130 @alice.create_magic_filed(:name => 'salary')
... ... @@ -140,12 +133,10 @@ describe HasMagicFields do
140 133 expect(lambda{@alice.create_magic_filed(:name => 'salary')}).to raise_error
141 134 expect(@alice.magic_fields.length).to eq(1)
142 135 expect(before_fields_count).to eq(MagicField.count)
143   -
144 136 @bob = User.create(name:"bob", account: @account )
145 137 expect(lambda{@bob.create_magic_filed(:name => 'salary')}).to raise_error
146   - expect(lambda{@sample.create_magic_filed(:name => 'salary')}).not_to raise_error
  138 + expect(lambda{@product.create_magic_filed(:name => 'salary')}).not_to raise_error
147 139 expect(lambda{@account.create_magic_filed(:name => 'salary')}).not_to raise_error
148   -
149 140 end
150 141 end
151 142 end
... ...
spec/spec_helper.rb
... ... @@ -22,7 +22,7 @@ end
22 22  
23 23 ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
24 24 # ActiveRecord::Base.configurations = true
25   -ActiveRecord::Base.logger = Logger.new(STDOUT)
  25 +# ActiveRecord::Base.logger = Logger.new(STDOUT)
26 26  
27 27 ActiveRecord::Schema.verbose = false
28 28  
... ... @@ -41,7 +41,7 @@ ActiveRecord::Schema.define do
41 41 t.column "name", :text
42 42 end
43 43  
44   - create_table "samples", :force => true do |t|
  44 + create_table "products", :force => true do |t|
45 45 t.column "name", :text
46 46 t.column "account_id", :integer
47 47 end
... ... @@ -73,7 +73,7 @@ RSpec.configure do |config|
73 73 has_magic_fields :through => :account
74 74 end
75 75  
76   - class Sample < ActiveRecord::Base
  76 + class Product < ActiveRecord::Base
77 77 include HasMagicFields::Extend
78 78 belongs_to :account
79 79 has_magic_fields :through => :account
... ...