rails_dictionary 0.0.8 → 0.0.9

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -1 +1,3 @@
1
- pkg/
1
+ pkg/
2
+ .git/
3
+ .gitignore
data/CHANGELOG ADDED
@@ -0,0 +1,6 @@
1
+ 0.0.9
2
+ add Rails Engine to redesign the gem
3
+ use Rspec instead of Test::Unit to write test code
4
+ remove many nonsence code
5
+ 0.0.1-0.0.8
6
+ old mixin coding style
data/Gemfile CHANGED
@@ -1,4 +1,10 @@
1
1
  source "http://rubygems.org"
2
2
 
3
- # Specify your gem's dependencies in dictionary.gemspec
3
+ # Specify your gem's dependencies in rails_dictionary.gemspec
4
4
  gemspec
5
+
6
+ group :development,:test do
7
+ gem 'rspec', '>= 2.5.0'
8
+ gem 'rails', '>= 3.0.0'
9
+ gem 'sqlite3'
10
+ end
data/README.rdoc CHANGED
@@ -1,6 +1,7 @@
1
1
  = Intro
2
- There are many static data in application.
3
- For example in a student application,there may be some static data like diploma kind,school and city of school.This gem can map these static data to a Dictionary#method like Dictionary#student_diploma_kind which return data list of diploma kind and generate a list of instance method on Student like @student.named_city which return city name of @student city
2
+ There are always some static data(not static page) in application.For example product type or diploma kind of student.
3
+
4
+ This gem can map these static data to a Dictionary#method like Dictionary#student_diploma_kind and generate a list of instance method on Student like @student.named_city which return city name (with locale if you need).
4
5
 
5
6
  = Usage
6
7
  == Installation
@@ -43,10 +44,11 @@ These task are just generate table dictionaries,dict_types,students and some sam
43
44
  | 2 | shanghai@dict.com | 3 | |
44
45
  +----+-------------------+------+--------+
45
46
  2 rows in set
46
- There is one conventions of DictType.name value.All value of DictType.name is "model_method" : student is model and city is method of student model.
47
+ There is one convention of DictType.name value.All value of DictType.name is "model_method" : student is model and city is method of student model.
47
48
 
48
49
  === Table Definition
49
50
  Make sure you have two tables which named as dict_types and dictionaries.
51
+
50
52
  Table dictionaries has one convention of naming column : name_locale.So the name_fr means this column have a french value,you can see more usage later.
51
53
  The students table is not required and variable by your application.
52
54
 
@@ -65,13 +67,15 @@ Here is what should be like.Student model can be other models.
65
67
  acts_as_dict_slave
66
68
  end
67
69
 
68
- == Features : Methods and results (relies on the above data)
70
+ == Features (relies on the above data) :
69
71
  DictType.all_cached #=> return cache of DictType.all
70
72
  DictType.all_types = %w[student_city student_school] # also cached
71
73
  Dictionary.student_city #=> [Dictionary.find(5),Dictionary.find(6)]
72
- student_city is a dynamic method which returns a list of dictionary object which dict_type is "student_city".Actually Dictionary will have as many dynamic methods as DictType.count and each dynamic method name is DictType.name(This methods returning an array,not ActiveRelation).
74
+ student_city is a dynamic method which returns a list of dictionary object which dict_type is "student_city".
75
+ Actually Dictionary will have as many dynamic methods as DictType.count and each dynamic method name is DictType.name.
76
+ Before version 0.1.0 or 0.2.0 ,all dynamic methods return an array,not ActiveRelation.So
73
77
  Dictionary.student_school = []
74
- Dictionary.student_city :locale => :en = [["shanghai",1],["beijing",2]]
78
+ Dictionary.student_city :locale => :en #=> [["shanghai",1],["beijing",2]]
75
79
  You can use it in form select method like
76
80
  collection_select :student,:city,Dictionary.student_city,:id,:name_en
77
81
  select :student,:city,Dictionary.student_city(params)
@@ -80,6 +84,9 @@ If params contains :locale => :fr,it returns a list of french name of student ci
80
84
  Here is an other solution for international translation.
81
85
  Student.find(1).named_city(:zh) = "北京"
82
86
  Student.find(1).named_city(:fr) = "Pékin"
87
+ Student.find(1).named_city(:en) = "beijing"
88
+ Make sure your locale is en,not en-US.
89
+
83
90
  Student has two belongs_to assocition which named as city_dict and school_dict,the naming convention is method_dict.
84
91
  Student.find(1).city_dict #=> Dictionary.find(6)
85
92
 
@@ -97,5 +104,10 @@ The rails cache would not refresh.
97
104
  In short,when you confused with the debug data,try running "rails tmp:clear" first.
98
105
 
99
106
  = TODO & Problems
100
- There are no convention and implemention to map Class like Ckeditor::Asset to a method.
107
+ There are no convention and implemention to map Class like Ckeditor::Asset to a legal method name.
108
+
109
+ Rebuild core code.Using Rails engine.
110
+
111
+ Make cached type of DictType to an array of symbols
112
+
101
113
  Rewrite Testing,make it more maintainable.
data/Rakefile CHANGED
@@ -3,6 +3,7 @@ Bundler::GemHelper.install_tasks
3
3
 
4
4
  desc "Running Test"
5
5
  task :test do
6
- system "ruby -I . test/rails_dictionary_test.rb "
6
+ # system "ruby -I . test/rails_dictionary_test.rb " # used with version 0.0.8 or before it
7
+ system "rspec spec/rails_dictionary_spec.rb"
7
8
  end
8
9
 
@@ -0,0 +1,4 @@
1
+ module RailsDictionary
2
+ class Engine < ::Rails::Engine
3
+ end
4
+ end
@@ -0,0 +1,45 @@
1
+ module RailsDictionary
2
+ module ActiveRecordExtension
3
+ def self.included(base)
4
+ base.extend(ClassMethods)
5
+ end
6
+
7
+ module ClassMethods
8
+ # TODO: move macro define in each module file
9
+ # See Usage in readme.doc.
10
+ def acts_as_dict_type
11
+ self.class_eval do
12
+ has_many :dictionaries
13
+ validates_uniqueness_of :name
14
+ after_save :delete_all_caches
15
+ after_destroy :delete_all_caches
16
+ end
17
+ include RailsDictionary::ActsAsDictType
18
+ end
19
+
20
+ def acts_as_dictionary
21
+ self.class_eval do
22
+ belongs_to :dict_type
23
+ after_save :delete_dicts_cache
24
+ after_destroy :delete_dicts_cache
25
+ end
26
+ include RailsDictionary::ActsAsDictionary
27
+ end
28
+
29
+ # :except - remove dict mapping column
30
+ # :add - add dict mapping column
31
+ # :locale - add and initialize class attribute default_dict_locale
32
+ def acts_as_dict_slave(ops={})
33
+ include RailsDictionary::ActsAsDictSlave
34
+ class_attribute :default_dict_locale,:instance_writer => false
35
+ cattr_accessor :dict_mapping_columns,:instance_writes => false
36
+ self.default_dict_locale = ops[:locale] if ops[:locale]
37
+ self.dict_mapping_columns = dict_columns(ops)
38
+ unless dict_mapping_columns.nil?
39
+ add_dynamic_column_method
40
+ end
41
+ end
42
+
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,55 @@
1
+ module RailsDictionary
2
+ module ActsAsDictSlave
3
+ def self.included(base)
4
+ base.extend(ClassMethods)
5
+ end
6
+
7
+ module ClassMethods
8
+
9
+ # return columns that exist in DictType#tab_and_column
10
+ def columns_in_dict_type
11
+ DictType.tab_and_column[self.name.underscore.to_sym]
12
+ end
13
+
14
+ # columns which map to dictionary
15
+ def dict_columns(ops={})
16
+ conf={except: nil,add: nil}
17
+ conf.update(ops)
18
+ cidt=self.columns_in_dict_type || []
19
+ cidt.delete(conf[:except])
20
+ case conf[:add]
21
+ when String
22
+ cidt.push(conf[:add])
23
+ when Array
24
+ cidt.push(*conf[:add])
25
+ else nil
26
+ end
27
+ cidt.uniq! || cidt
28
+ end
29
+
30
+ # add a belongs_to(Dictionary) association and a named_{column} method
31
+ def add_dynamic_column_method
32
+ dict_mapping_columns.each { |e| belongs_to "#{e.to_s}_dict".to_sym,class_name: "Dictionary",foreign_key: e }
33
+ dict_mapping_columns.each { |ele| named_dict_value ele.to_sym }
34
+ end
35
+
36
+ # Generate dynamic instance method named_column to slave model
37
+ # def named_city(locale=nil)
38
+ # locale = locale.presence || default_dict_locale.presence || :en
39
+ # locale = "name_#{locale}"
40
+ # self.send(city_dict).try(:send,locale)
41
+ # end
42
+ def named_dict_value(method_name)
43
+ belongs_to_name="#{method_name.to_s}_dict".to_sym
44
+ method_name="named_#{method_name.to_s}"
45
+ define_method(method_name) do | locale=nil |
46
+ locale = locale.presence || default_dict_locale.presence || :en
47
+ locale = "name_#{locale}"
48
+ self.send(belongs_to_name).try(:send,locale)
49
+ end
50
+ end
51
+
52
+ end
53
+
54
+ end
55
+ end
@@ -0,0 +1,54 @@
1
+ module RailsDictionary
2
+ module ActsAsDictType
3
+ def self.included(base)
4
+ base.extend(ClassMethods)
5
+ base.send :include,InstanceMethods
6
+ end
7
+
8
+ module ClassMethods
9
+
10
+ def all_types
11
+ Rails.cache.fetch("DictType.all_types") { all.map(&:name).map(&:to_sym) }.dup
12
+ end
13
+
14
+ def cached_all
15
+ Rails.cache.fetch("DictType.cached_all") { all }.dup
16
+ end
17
+
18
+ # short method to transfer id to name or name to id
19
+ def revert(arg)
20
+ if arg.is_a?(String)
21
+ DictType.where(name: arg).first.try(:id)
22
+ elsif arg.is_a?(Fixnum)
23
+ DictType.where(id: arg).first.try(:name)
24
+ end
25
+ end
26
+
27
+ # TODO: get a more accurate method name
28
+ #
29
+ # Parse the name value to get which column and model are listed in DictType
30
+ #
31
+ # Programmer DOC:
32
+ # There are two chooses to get subclass,one is subclasses the other is descendants,
33
+ # I don't know which is better,but descendants contains subclass of subclass,it contains more.
34
+ # Class like +Ckeditor::Asset+ transfer to "ckeditor/asset",but we can not naming method like that,
35
+ # So it still not support, the solution may be simple,just make another convention to escape "/"
36
+ def tab_and_column
37
+ Rails.cache.fetch("DictType.tab_and_column") do
38
+ all_model_class=ActiveRecord::Base.descendants.map(&:name).map(&:underscore)
39
+ all_types.map(&:to_s).extract_to_hash(all_model_class)
40
+ end
41
+ end
42
+ end
43
+
44
+ module InstanceMethods
45
+ def delete_all_caches
46
+ Rails.cache.delete("DictType.all_types")
47
+ Rails.cache.delete("DictType.cached_all")
48
+ Rails.cache.delete("DictType.tab_and_column")
49
+ return true
50
+ end
51
+ end
52
+
53
+ end
54
+ end
@@ -0,0 +1,56 @@
1
+ module RailsDictionary
2
+ module ActsAsDictionary
3
+ def self.included(base)
4
+ base.extend(ClassMethods)
5
+ base.send :include,InstanceMethods
6
+ end
7
+
8
+ module ClassMethods
9
+
10
+ # Return an instance of array
11
+ # Programmer DOC:
12
+ # Following design is failed with sqlite3 in test
13
+ # scope :dict_type_name_eq,lambda {|method_name| joins(:dict_type).where("dict_types.name" => method_name)}
14
+ # remove the all seems not pass test,return following errors
15
+ # TypeError: no marshal_dump is defined for class SQLite3::Database
16
+ def dict_type_name_eq(method_name)
17
+ joins(:dict_type).where("dict_types.name" => method_name).all
18
+ end
19
+
20
+ # Generate methods like Dictionary.student_city
21
+ # Dictionary.student_city - a list of dictionary object which dict type is student_city
22
+ # Dictionary.student_city(:locale => :zh) - a select format array which can be used
23
+ # in view method select as choice params
24
+ # Programmer DOC && TODO:
25
+ # rethink about the cache.
26
+ # cache methods like Dictionary.student_city(:locale => :zh,:sort => :name_fr)
27
+ # but not cache Dictionary.student_city,return it as relation
28
+ def method_missing(method_id,options={},&block)
29
+ method_name=method_id.to_s.downcase
30
+ if DictType.all_types.include? method_id
31
+ Rails.cache.fetch("Dictionary.#{method_name}") { dict_type_name_eq(method_name) }
32
+ listed_attr=Rails.cache.read("Dictionary.#{method_name}").dup
33
+ # Instance of activerelation can not be dup?
34
+ if options.keys.include? :locale or options.keys.include? "locale"
35
+ locale="name_#{ options[:locale] }"
36
+ listed_attr.map! { |a| [a.send(locale),a.id] }
37
+ listed_attr.sort { |a,b| a.first <=> b.first }
38
+ # maybe remove the above line,or change some sorting and caching design
39
+ else
40
+ listed_attr
41
+ end
42
+ else
43
+ super
44
+ end
45
+ end
46
+ end
47
+
48
+ module InstanceMethods
49
+ def delete_dicts_cache
50
+ method_name=DictType.revert(self.dict_type_id)
51
+ Rails.cache.delete("Dictionary.#{method_name}")
52
+ return true
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,17 @@
1
+ require 'rails'
2
+
3
+ require File.join(File.dirname(__FILE__),"array_core_ext")
4
+ require File.join(File.dirname(__FILE__),"models/acts_as_dict_type")
5
+ require File.join(File.dirname(__FILE__),"models/acts_as_dictionary")
6
+ require File.join(File.dirname(__FILE__),"models/acts_as_dict_slave")
7
+
8
+ module RailsDictionary
9
+ class Railtie < ::Rails::Railtie
10
+ initializer 'rails_dictionary' do |app|
11
+ ActiveSupport.on_load(:active_record) do
12
+ require File.join(File.dirname(__FILE__), 'models/active_record_extension')
13
+ ::ActiveRecord::Base.send :include, RailsDictionary::ActiveRecordExtension
14
+ end
15
+ end
16
+ end
17
+ end
@@ -1,3 +1,3 @@
1
1
  module RailsDictionary
2
- VERSION = "0.0.8"
2
+ VERSION = "0.0.9"
3
3
  end
@@ -1,4 +1,2 @@
1
- require "rails_dictionary/acts_as_dictionary"
2
- require "rails_dictionary/acts_as_dict_slave"
3
- require "rails_dictionary/acts_as_dict_type"
4
- require "rails_dictionary/array_core_ext"
1
+ require File.join(File.dirname(__FILE__), 'rails_dictionary/railtie')
2
+ require File.join(File.dirname(__FILE__), 'rails_dictionary/engine')
@@ -0,0 +1,2 @@
1
+
2
+ ***** Debugger requested, but was not available (ensure ruby-debug is listed in Gemfile/installed as gem): Start server with --debugger to enable *****
@@ -6,7 +6,7 @@ Gem::Specification.new do |s|
6
6
  s.name = "rails_dictionary"
7
7
  s.version = RailsDictionary::VERSION
8
8
  s.platform = Gem::Platform::RUBY
9
- s.authors = ["raykin"]
9
+ s.authors = ["Raykin Lee"]
10
10
  s.email = ["raykincoldxiao@campus.com"]
11
11
  s.homepage = "https://github.com/raykin/rails_dictionary"
12
12
  s.summary = %q{dictionary data for web application}
data/spec/fake_app.rb ADDED
@@ -0,0 +1,36 @@
1
+
2
+ # database
3
+ ActiveRecord::Base.configurations = {'test' => {:adapter => 'sqlite3', :database => ':memory:'}}
4
+ ActiveRecord::Base.establish_connection('test')
5
+
6
+ # config
7
+ app = Class.new(Rails::Application)
8
+ app.config.active_support.deprecation = :log
9
+ app.initialize!
10
+
11
+ # models
12
+ class DictType < ActiveRecord::Base
13
+ acts_as_dict_type
14
+ end
15
+
16
+ class Dictionary < ActiveRecord::Base
17
+ acts_as_dictionary
18
+ end
19
+
20
+ class Student < ActiveRecord::Base
21
+ end
22
+
23
+ #migrations
24
+ class CreateAllTables < ActiveRecord::Migration
25
+ def self.up
26
+ create_table(:dict_types) {|t| t.string :name}
27
+ create_table(:dictionaries) {|t| t.string :name_en; t.string :name_zh ; t.string :name_fr ; t.integer :dict_type_id}
28
+ create_table(:students) {|t| t.string :email; t.integer :city; t.integer :school}
29
+ end
30
+
31
+ def self.down
32
+ drop_table :dict_types
33
+ drop_table :dictionaries
34
+ drop_table :students
35
+ end
36
+ end
@@ -0,0 +1,90 @@
1
+ # -*- coding: utf-8 -*-
2
+ require File.expand_path('spec_helper', File.dirname(__FILE__))
3
+
4
+
5
+ describe RailsDictionary::ActiveRecordExtension do
6
+ %w[acts_as_dict_type acts_as_dictionary acts_as_dict_slave].each do |method_name|
7
+ it "contains #{method_name}" do
8
+ ActiveRecord::Base.methods.include?(method_name.to_sym).should be_true
9
+ end
10
+ end
11
+ end
12
+
13
+ describe RailsDictionary do
14
+ let!(:dt_stu_city) { DictType.create! :name => "student_city" }
15
+ let!(:dt_stu_school) { DictType.create! :name => "student_school" }
16
+ let!(:dy_shanghai) { Dictionary.create! name_en: "shanghai",name_zh: "上海",name_fr: "shanghai",dict_type_id: dt_stu_city.id }
17
+ let!(:dy_beijing) { Dictionary.create! name_en: "beijing",name_zh: "北京",name_fr: "Pékin",dict_type_id: dt_stu_city.id }
18
+ let!(:stu_beijing) { Student.create! email: "beijing@dict.com",city: dy_beijing.id }
19
+ let!(:stu_shanghai) { Student.create! email: "shanghai@dict.com",city: dy_shanghai.id }
20
+
21
+ describe DictType do
22
+ it "parse model and method" do
23
+ expected_hash={:student => %w[city school]}
24
+ DictType.tab_and_column.should == expected_hash
25
+ end
26
+
27
+ it "all types" do
28
+ DictType.all_types.should == [:student_city, :student_school]
29
+ end
30
+
31
+ it "reverts id to name or name to id" do
32
+ DictType.revert(dt_stu_school.id).should == "student_school"
33
+ DictType.revert(100).should be_nil
34
+ end
35
+
36
+ it "after one record removed" do
37
+ dt_stu_school.destroy
38
+ DictType.all_types.should == [:student_city]
39
+ DictType.tab_and_column.should == Hash[:student,["city"]]
40
+ end
41
+ end
42
+
43
+ describe Dictionary do
44
+ it "generate student_city method" do
45
+ Dictionary.student_city.should == [dy_shanghai,dy_beijing]
46
+ end
47
+
48
+ it "generate student_city method with locale" do
49
+ Dictionary.student_city(:locale => :zh).should == [["上海", 1],["北京", 2]]
50
+ end
51
+
52
+ it "after record added or removed" do
53
+ @dy_wuhan=Dictionary.create! name_en: "wuhan",name_zh: "武汉",name_fr: "wuhan",dict_type_id: dt_stu_city.id
54
+ Dictionary.student_city(:locale => :en).should == [["beijing", 2],["shanghai",1],["wuhan", 3]]
55
+ @dy_wuhan.destroy
56
+ Dictionary.student_city(:locale => :en).should == [["beijing", 2],["shanghai",1]]
57
+ end
58
+ end
59
+
60
+ describe Student do
61
+ before :each do
62
+ Student.acts_as_dict_slave
63
+ end
64
+ it "method of columns_in_dict_type and dict_columns" do
65
+ Student.columns_in_dict_type.should == %w[city school]
66
+ Student.dict_columns == %w[city school]
67
+ end
68
+
69
+ it "named_city with different locale" do
70
+ stu_shanghai.named_city(:en).should == "shanghai"
71
+ stu_shanghai.named_city("").should == "shanghai"
72
+ stu_beijing.named_city(:fr).should == "Pékin"
73
+ end
74
+
75
+ it "override default locale" do
76
+ Student.acts_as_dict_slave :locale => :fr
77
+ stu_beijing.named_city.should == "Pékin"
78
+ end
79
+ end
80
+ end
81
+
82
+ describe Array do
83
+ let(:an_array) { %w[root student_school student_city admin_role] }
84
+ let(:expected_hash) { {:student => %w[school city],:admin => %w[role]} }
85
+ let(:blank_hash) { Hash.new }
86
+ it "extract to hash" do
87
+ an_array.extract_to_hash(%w[student admin]).should == expected_hash
88
+ an_array.extract_to_hash(%w[students]).should == blank_hash
89
+ end
90
+ end
@@ -0,0 +1,19 @@
1
+ # copy and modify the test design of kaminari(a paginate gem for Rails3)
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
4
+ require 'rails'
5
+ require 'active_record'
6
+ require 'action_controller/railtie'
7
+ require 'action_view/railtie'
8
+ require 'rails_dictionary'
9
+
10
+ require File.join(File.dirname(__FILE__), 'fake_app')
11
+
12
+ require 'rspec/rails'
13
+
14
+ $stdout = StringIO.new # remove the noise output
15
+
16
+ RSpec.configure do |config|
17
+ config.use_transactional_fixtures = true
18
+ CreateAllTables.up unless ActiveRecord::Base.connection.table_exists? 'dict_types'
19
+ end
@@ -1,4 +1,7 @@
1
1
  # -*- coding: utf-8 -*-
2
+ # Testing for version 0.0.8 or lower.Copy the test design from acts_as_tree
3
+ # Usage: run "ruby -I . test/rails_dictionary_test.rb " in root dir
4
+ #
2
5
  require "test/unit"
3
6
  require "active_support"
4
7
  require "active_record"
@@ -6,7 +9,6 @@ require "ruby-debug" # coupled with debugger to debug code
6
9
  Object.const_set "RAILS_CACHE", ActiveSupport::Cache.lookup_store
7
10
  require "active_support/cache"
8
11
  require "rails"
9
- # $: << "/home/raykin/studio/rails_dictionary/lib" # tmply added for local testing
10
12
  require "#{File.dirname(__FILE__)}/../lib/rails_dictionary.rb"
11
13
 
12
14
  ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
@@ -53,7 +55,6 @@ end
53
55
  class Student < ActiveRecord::Base
54
56
  end
55
57
 
56
-
57
58
  class CoreExtTest < Test::Unit::TestCase
58
59
  def test_array
59
60
  expected_hash={:student => %w[school city],:admin => %w[role]}
@@ -92,6 +93,7 @@ class DictTypeTest < Test::Unit::TestCase
92
93
  # test revert method in acts_as_dict_type
93
94
  def test_dt_revert
94
95
  assert_equal "student_school",DictType.revert(@dt_stu_school.id)
96
+ assert_equal nil,DictType.revert(100)
95
97
  end
96
98
 
97
99
  # test dynamic instance methods in slave model
@@ -111,18 +113,18 @@ class DictTypeTest < Test::Unit::TestCase
111
113
  end
112
114
 
113
115
  def test_dictionary_method_missing
114
- assert_equal [["shanghai",1],["beijing",2]],Dictionary.student_city(:locale => :en)
116
+ assert_equal [["beijing",2],["shanghai",1]],Dictionary.student_city(:locale => :en)
115
117
  end
116
118
 
117
119
  def test_dictionary_method_missing_with_locale
118
- assert_equal [["上海", 1], ["北京", 2]],Dictionary.student_city(:locale => :zh)
120
+ assert_equal [["上海", 1],["北京", 2]],Dictionary.student_city(:locale => :zh)
119
121
  end
120
122
 
121
123
  def test_delete_dicts_cache
122
124
  @dy_wuhan=Dictionary.create! name_en: "wuhan",name_zh: "武汉",name_fr: "wuhan",dict_type_id: @dt_stu_city.id
123
- assert_equal [["shanghai", 1], ["beijing", 2], ["wuhan", 3]],Dictionary.student_city(:locale => :en)
125
+ assert_equal [["beijing", 2],["shanghai",1],["wuhan", 3]],Dictionary.student_city(:locale => :en)
124
126
  @dy_wuhan.destroy
125
- assert_equal [["shanghai", 1], ["beijing", 2]],Dictionary.student_city(:locale => :en)
127
+ assert_equal [["beijing", 2],["shanghai",1]],Dictionary.student_city(:locale => :en)
126
128
  assert_equal [@dy_shanghai,@dy_beijing],Dictionary.student_city
127
129
  end
128
130
 
metadata CHANGED
@@ -2,16 +2,15 @@
2
2
  name: rails_dictionary
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.0.8
5
+ version: 0.0.9
6
6
  platform: ruby
7
7
  authors:
8
- - raykin
8
+ - Raykin Lee
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-03-21 00:00:00 +08:00
14
- default_executable:
13
+ date: 2011-04-14 00:00:00 Z
15
14
  dependencies: []
16
15
 
17
16
  description: Rails plugin for mapping static data of web application to Dictionary class
@@ -25,19 +24,26 @@ extra_rdoc_files: []
25
24
 
26
25
  files:
27
26
  - .gitignore
27
+ - CHANGELOG
28
28
  - Gemfile
29
29
  - README.rdoc
30
30
  - Rakefile
31
31
  - lib/rails_dictionary.rb
32
- - lib/rails_dictionary/acts_as_dict_slave.rb
33
- - lib/rails_dictionary/acts_as_dict_type.rb
34
- - lib/rails_dictionary/acts_as_dictionary.rb
35
32
  - lib/rails_dictionary/array_core_ext.rb
33
+ - lib/rails_dictionary/engine.rb
34
+ - lib/rails_dictionary/models/active_record_extension.rb
35
+ - lib/rails_dictionary/models/acts_as_dict_slave.rb
36
+ - lib/rails_dictionary/models/acts_as_dict_type.rb
37
+ - lib/rails_dictionary/models/acts_as_dictionary.rb
38
+ - lib/rails_dictionary/railtie.rb
36
39
  - lib/rails_dictionary/version.rb
37
40
  - lib/tasks/dicts.rake
41
+ - log/development.log
38
42
  - rails_dictionary.gemspec
43
+ - spec/fake_app.rb
44
+ - spec/rails_dictionary_spec.rb
45
+ - spec/spec_helper.rb
39
46
  - test/rails_dictionary_test.rb
40
- has_rdoc: true
41
47
  homepage: https://github.com/raykin/rails_dictionary
42
48
  licenses: []
43
49
 
@@ -61,9 +67,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
61
67
  requirements: []
62
68
 
63
69
  rubyforge_project: rails_dictionary
64
- rubygems_version: 1.6.2
70
+ rubygems_version: 1.7.2
65
71
  signing_key:
66
72
  specification_version: 3
67
73
  summary: dictionary data for web application
68
74
  test_files:
75
+ - spec/fake_app.rb
76
+ - spec/rails_dictionary_spec.rb
77
+ - spec/spec_helper.rb
69
78
  - test/rails_dictionary_test.rb
79
+ has_rdoc:
@@ -1,69 +0,0 @@
1
- module ActsAsDictSlave
2
- def self.included(base)
3
- base.extend(ClassMethods)
4
- end
5
-
6
- module ClassMethods
7
- # :except - remove dict mapping column
8
- # :add - add dict mapping column
9
- # :locale - add and initialize class attribute default_dict_locale
10
- def acts_as_dict_slave(ops={})
11
- class_attribute :default_dict_locale,:instance_writer => false
12
- cattr_accessor :dict_mapping_columns,:instance_writes => false
13
- self.default_dict_locale = ops[:locale] if ops[:locale]
14
- self.dict_mapping_columns = dict_columns(ops)
15
- unless dict_mapping_columns.nil?
16
- add_dynamic_column_method
17
- end
18
- end
19
-
20
- # return columns that exist in DictType#tab_and_column
21
- def columns_in_dict_type
22
- DictType.tab_and_column[self.name.underscore.to_sym]
23
- end
24
-
25
- # columns which map to dictionary
26
- def dict_columns(ops={})
27
- conf={except: nil,add: nil}
28
- conf.update(ops)
29
- cidt=self.columns_in_dict_type || []
30
- cidt.delete(conf[:except])
31
- case conf[:add]
32
- when String
33
- cidt.push(conf[:add])
34
- when Array
35
- cidt.push(*conf[:add])
36
- else nil
37
- end
38
- cidt.uniq! || cidt
39
- end
40
-
41
- # add a belongs_to(Dictionary) association and a named_{column} method
42
- def add_dynamic_column_method
43
- self.extend(DynamicInsMethods)
44
- dict_mapping_columns.each { |e| belongs_to "#{e.to_s}_dict".to_sym,class_name: "Dictionary",foreign_key: e }
45
- dict_mapping_columns.each { |ele| named_dict_value ele.to_sym }
46
- end
47
- end
48
-
49
- module DynamicInsMethods
50
- # generate dynamic instance method named_column to slave model
51
- # def named_city(locale=nil)
52
- # locale = locale.presence || default_dict_locale.presence || :en
53
- # locale = "name_#{locale}"
54
- # self.send(city_dict).try(:send,locale)
55
- # end
56
- def named_dict_value(method_name)
57
- belongs_to_name="#{method_name.to_s}_dict".to_sym
58
- method_name="named_#{method_name.to_s}"
59
- define_method(method_name) do | locale=nil |
60
- locale = locale.presence || default_dict_locale.presence || :en
61
- locale = "name_#{locale}"
62
- self.send(belongs_to_name).try(:send,locale)
63
- end
64
- end
65
-
66
- end
67
-
68
- end
69
- ActiveRecord::Base.class_eval { include ActsAsDictSlave }
@@ -1,56 +0,0 @@
1
- module ActsAsDictType
2
- def self.included(base)
3
- base.extend(ClassMethods)
4
- end
5
-
6
- module ClassMethods
7
- def acts_as_dict_type(ops={})
8
- self.class_eval do
9
- has_many :dictionaries
10
- include InstanceMethods
11
- validates_uniqueness_of :name
12
- after_save :delete_all_caches
13
- after_destroy :delete_all_caches
14
-
15
- def self.all_types
16
- Rails.cache.fetch("DictType.all_types") { all.map(&:name) }.dup
17
- end
18
-
19
- def self.cached_all
20
- Rails.cache.fetch("DictType.cached_all") { all }.dup
21
- end
22
-
23
- # short method to transfer id to name or name to id
24
- def self.revert(arg)
25
- if arg.is_a?(String)
26
- DictType.where(name: arg).try(:first).id
27
- elsif arg.is_a?(Fixnum)
28
- DictType.where(id: arg).try(:first).name
29
- end
30
- end
31
-
32
- # TODO: get a more accurate method name
33
- # Parse the name value to get which column and model are listed in DictType
34
- def self.tab_and_column
35
- tab_and_column={}
36
- # There are two chooses,one is subclasses the other is descendants,
37
- # I don't know which is better,but descendants contains subclass of subclass,it contains more.
38
- # Class like +Ckeditor::Asset+ transfer to "ckeditor/asset",but we can not naming method like that,
39
- # So it still not support, the solution may be simple,just make another convention to escape "/"
40
- all_model_class=ActiveRecord::Base.descendants.map(&:name).map(&:underscore)
41
- tab_and_column=all_types.extract_to_hash(all_model_class)
42
- end
43
- end
44
- end
45
-
46
- module InstanceMethods
47
- def delete_all_caches
48
- Rails.cache.delete("DictType.all_types")
49
- Rails.cache.delete("DictType.cached_all")
50
- return true
51
- end
52
- end
53
-
54
- end
55
- end
56
- ActiveRecord::Base.class_eval { include ActsAsDictType }
@@ -1,57 +0,0 @@
1
- module ActsAsDictionary
2
- def self.included(base)
3
- base.extend(ClassMethods)
4
- end
5
-
6
- module ClassMethods
7
-
8
- def acts_as_dictionary
9
- belongs_to :dict_type
10
- after_save :delete_dicts_cache
11
- after_destroy :delete_dicts_cache
12
-
13
- # Return an instance of array
14
- def dict_type_name_eq(method_name)
15
- joins(:dict_type).where("dict_types.name" => method_name).all
16
- end
17
- #Following design is not successed with sqlite3 in test
18
- # scope :dict_type_name_eq,lambda {|method_name| joins(:dict_type).where("dict_types.name" => method_name)}
19
- # remove the all seems not pass test,return following errors
20
- # TypeError: no marshal_dump is defined for class SQLite3::Database
21
- include InstanceMethods
22
- # Generate methods like Dictionary.student_city
23
- # Dictionary.student_city - a list of dictionary object which dict type is student_city
24
- # Dictionary.student_city(:locale => :zh) - a select format array which can be used
25
- # in view method select as choice params
26
- # Is this design good?
27
- def self.method_missing(method_id,options={},&block)
28
- method_name=method_id.to_s.downcase
29
- if DictType.all_types.include? method_id.to_s
30
- Rails.cache.fetch("Dictionary.#{method_name}") { dict_type_name_eq(method_name) }
31
- listed_attr=Rails.cache.read("Dictionary.#{method_name}").dup
32
- # Instance of activerelation can not be dup?
33
- if options.keys.include? :locale or options.keys.include? "locale"
34
- locale="name_#{ options[:locale] }"
35
- listed_attr.map! { |a| [a.send(locale),a.id] }
36
- listed_attr.sort {|a,b| a.last <=> b.last } # maybe remove this line
37
- else
38
- listed_attr
39
- end
40
- else
41
- super
42
- end
43
- end
44
-
45
- end
46
- end
47
-
48
- module InstanceMethods
49
- def delete_dicts_cache
50
- method_name=DictType.revert(self.dict_type_id)
51
- Rails.cache.delete("Dictionary.#{method_name}")
52
- return true
53
- end
54
- end
55
-
56
- end
57
- ActiveRecord::Base.class_eval { include ActsAsDictionary }