rails_growth 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (115) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +20 -0
  3. data/README.md +28 -0
  4. data/Rakefile +32 -0
  5. data/app/controllers/growth/admin/aim_entities_controller.rb +30 -0
  6. data/app/controllers/growth/admin/aim_logs_controller.rb +21 -0
  7. data/app/controllers/growth/admin/aim_users_controller.rb +30 -0
  8. data/app/controllers/growth/admin/aims_controller.rb +73 -0
  9. data/app/controllers/growth/admin/base_controller.rb +4 -0
  10. data/app/controllers/growth/admin/praise_incomes_controller.rb +61 -0
  11. data/app/controllers/growth/admin/reward_expenses_controller.rb +63 -0
  12. data/app/controllers/growth/admin/reward_incomes_controller.rb +59 -0
  13. data/app/controllers/growth/admin/rewards_controller.rb +65 -0
  14. data/app/controllers/growth/controller/application.rb +77 -0
  15. data/app/controllers/growth/my/aim_logs_controller.rb +45 -0
  16. data/app/controllers/growth/my/aim_users_controller.rb +25 -0
  17. data/app/controllers/growth/my/aims_controller.rb +44 -0
  18. data/app/controllers/growth/my/base_controller.rb +4 -0
  19. data/app/controllers/growth/my/gifts_controller.rb +27 -0
  20. data/app/controllers/growth/my/rewards_controller.rb +28 -0
  21. data/app/models/growth/aim.rb +5 -0
  22. data/app/models/growth/aim_code.rb +5 -0
  23. data/app/models/growth/aim_entity.rb +5 -0
  24. data/app/models/growth/aim_log.rb +5 -0
  25. data/app/models/growth/aim_user.rb +5 -0
  26. data/app/models/growth/model/aim.rb +52 -0
  27. data/app/models/growth/model/aim_code.rb +40 -0
  28. data/app/models/growth/model/aim_entity.rb +74 -0
  29. data/app/models/growth/model/aim_log.rb +79 -0
  30. data/app/models/growth/model/aim_user.rb +60 -0
  31. data/app/models/growth/model/card.rb +25 -0
  32. data/app/models/growth/model/cash.rb +17 -0
  33. data/app/models/growth/model/entity.rb +74 -0
  34. data/app/models/growth/model/praise_compute.rb +70 -0
  35. data/app/models/growth/model/praise_income.rb +82 -0
  36. data/app/models/growth/model/praise_user.rb +47 -0
  37. data/app/models/growth/model/promote.rb +30 -0
  38. data/app/models/growth/model/reward.rb +67 -0
  39. data/app/models/growth/model/reward_expense.rb +98 -0
  40. data/app/models/growth/model/reward_income.rb +35 -0
  41. data/app/models/growth/model/royalty_compute.rb +72 -0
  42. data/app/models/growth/model/user.rb +21 -0
  43. data/app/models/growth/praise_income.rb +7 -0
  44. data/app/models/growth/praise_user.rb +5 -0
  45. data/app/models/growth/reward.rb +5 -0
  46. data/app/models/growth/reward_expense.rb +5 -0
  47. data/app/models/growth/reward_income.rb +5 -0
  48. data/app/models/growth.rb +11 -0
  49. data/app/views/application/_growth_nav.html.erb +12 -0
  50. data/app/views/growth/admin/aim_entities/_filter.html.erb +10 -0
  51. data/app/views/growth/admin/aim_entities/index.html.erb +68 -0
  52. data/app/views/growth/admin/aim_entities/show.html.erb +22 -0
  53. data/app/views/growth/admin/aim_logs/_filter.html.erb +9 -0
  54. data/app/views/growth/admin/aim_logs/index.html.erb +62 -0
  55. data/app/views/growth/admin/aim_logs/show.html.erb +14 -0
  56. data/app/views/growth/admin/aim_users/_filter.html.erb +7 -0
  57. data/app/views/growth/admin/aim_users/index.html.erb +63 -0
  58. data/app/views/growth/admin/aim_users/show.html.erb +30 -0
  59. data/app/views/growth/admin/aims/_filter.html.erb +8 -0
  60. data/app/views/growth/admin/aims/_form.html.erb +14 -0
  61. data/app/views/growth/admin/aims/_item_field.html.erb +3 -0
  62. data/app/views/growth/admin/aims/_item_form.html.erb +24 -0
  63. data/app/views/growth/admin/aims/add_item.js.erb +9 -0
  64. data/app/views/growth/admin/aims/index.html.erb +54 -0
  65. data/app/views/growth/admin/aims/remove_item.js.erb +1 -0
  66. data/app/views/growth/admin/aims/show.html.erb +38 -0
  67. data/app/views/growth/admin/managers/_edit.html.erb +13 -0
  68. data/app/views/growth/admin/managers/_form.html.erb +34 -0
  69. data/app/views/growth/admin/managers/_new.html.erb +13 -0
  70. data/app/views/growth/admin/managers/_search_form.html.erb +8 -0
  71. data/app/views/growth/admin/managers/edit.js.erb +8 -0
  72. data/app/views/growth/admin/managers/index.html.erb +68 -0
  73. data/app/views/growth/admin/managers/new.js.erb +8 -0
  74. data/app/views/growth/admin/managers/show.html.erb +0 -0
  75. data/app/views/growth/admin/managers/update.js.erb +1 -0
  76. data/app/views/growth/admin/praise_incomes/_filter.html.erb +5 -0
  77. data/app/views/growth/admin/praise_incomes/_form.html.erb +3 -0
  78. data/app/views/growth/admin/praise_incomes/edit.html.erb +11 -0
  79. data/app/views/growth/admin/praise_incomes/index.html.erb +59 -0
  80. data/app/views/growth/admin/praise_incomes/new.html.erb +11 -0
  81. data/app/views/growth/admin/praise_incomes/show.html.erb +18 -0
  82. data/app/views/growth/admin/reward_expenses/_filter.html.erb +5 -0
  83. data/app/views/growth/admin/reward_expenses/_form.html.erb +7 -0
  84. data/app/views/growth/admin/reward_expenses/index.html.erb +49 -0
  85. data/app/views/growth/admin/reward_expenses/show.html.erb +26 -0
  86. data/app/views/growth/admin/reward_incomes/_filter.html.erb +10 -0
  87. data/app/views/growth/admin/reward_incomes/_form.html.erb +3 -0
  88. data/app/views/growth/admin/reward_incomes/edit.html.erb +11 -0
  89. data/app/views/growth/admin/reward_incomes/index.html.erb +49 -0
  90. data/app/views/growth/admin/reward_incomes/new.html.erb +11 -0
  91. data/app/views/growth/admin/reward_incomes/show.html.erb +18 -0
  92. data/app/views/growth/admin/rewards/_filter.html.erb +14 -0
  93. data/app/views/growth/admin/rewards/_form.html.erb +27 -0
  94. data/app/views/growth/admin/rewards/index.html.erb +84 -0
  95. data/app/views/growth/admin/rewards/show.html.erb +26 -0
  96. data/app/views/growth/my/aims/_aim.json.jbuilder +6 -0
  97. data/app/views/growth/my/aims/index.json.jbuilder +3 -0
  98. data/app/views/growth/my/aims/show.json.jbuilder +1 -0
  99. data/app/views/growth/my/gifts/_gift.json.jbuilder +1 -0
  100. data/app/views/growth/my/gifts/_praise_income.json.jbuilder +8 -0
  101. data/app/views/growth/my/gifts/give.json.jbuilder +8 -0
  102. data/app/views/growth/my/gifts/index.json.jbuilder +9 -0
  103. data/app/views/growth/my/rewards/_praise_user.json.jbuilder +2 -0
  104. data/app/views/growth/my/rewards/top.json.jbuilder +6 -0
  105. data/config/locales/en.notify.yml +7 -0
  106. data/config/locales/en.yml +29 -0
  107. data/config/locales/zh.controller.yml +24 -0
  108. data/config/locales/zh.notify.yml +7 -0
  109. data/config/locales/zh.yml +11 -0
  110. data/config/routes.rb +57 -0
  111. data/lib/rails_growth/config.rb +13 -0
  112. data/lib/rails_growth/engine.rb +19 -0
  113. data/lib/rails_growth/serial_number_helper.rb +28 -0
  114. data/lib/rails_growth.rb +4 -0
  115. metadata +170 -0
@@ -0,0 +1,47 @@
1
+ module Growth
2
+ module Model::PraiseUser
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ attribute :amount, :decimal, precision: 10, scale: 2, default: 0
7
+ attribute :position, :integer
8
+
9
+ belongs_to :user
10
+ belongs_to :reward
11
+ belongs_to :entity, polymorphic: true
12
+ has_many :praise_incomes, ->(o){ where(reward_id: o.reward_id) }, foreign_key: :user_id, primary_key: :user_id
13
+ has_many :same_praise_users, ->(o){ where(reward_id: o.reward_id, entity_type: o.entity_type) }, class_name: 'PraiseUser', foreign_key: :entity_id, primary_key: :entity_id
14
+
15
+ after_initialize if: :new_record? do
16
+ if reward
17
+ self.entity_type = reward.entity_type
18
+ self.entity_id = reward.entity_id
19
+ end
20
+ end
21
+ after_commit :reset_position, if: -> { saved_change_to_amount? }
22
+
23
+ acts_as_list scope: [:entity_type, :entity_id]
24
+ end
25
+
26
+ def compute_amount
27
+ self.praise_incomes.sum(:amount)
28
+ end
29
+
30
+ def reset_position
31
+ lower_count = same_praise_users.default_where('amount-gte': self.amount).count
32
+ self.insert_at(lower_count)
33
+ end
34
+
35
+ class_methods do
36
+ def reset_position
37
+ self.select(:entity_type, :entity_id).distinct.each do |pu|
38
+ self.where(entity_type: pu.entity_type, entity_id: pu.entity_id).order(amount: :desc).each.with_index(1) do |item, index|
39
+ item.update_column :position, index
40
+ end
41
+ end
42
+ end
43
+ end
44
+
45
+
46
+ end
47
+ end
@@ -0,0 +1,30 @@
1
+ module Growth
2
+ module Model::Promote
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ has_many :aim_users, primary_key: :user_id, foreign_key: :user_id
7
+ has_many :reward_expenses, primary_key: :user_id, foreign_key: :user_id
8
+ has_many :praise_incomes, primary_key: :user_id, foreign_key: :user_id
9
+ has_many :earned_incomes, class_name: 'PraiseIncome', primary_key: :user_id, foreign_key: :earner_id
10
+ end
11
+
12
+ def compute_income_amount
13
+ origin_amount = super
14
+ aim_amount = self.aim_users.sum(:reward_amount)
15
+
16
+ earned_amount = self.earned_incomes.sum(:royalty_amount)
17
+ reward_amount = self.reward_expenses.sum(:amount)
18
+
19
+ origin_amount + aim_amount + earned_amount + reward_amount
20
+ end
21
+
22
+ def compute_expense_amount
23
+ origin_amount = super
24
+ praise_amount = self.praise_incomes.sum(:amount)
25
+
26
+ origin_amount + praise_amount
27
+ end
28
+
29
+ end
30
+ end
@@ -0,0 +1,67 @@
1
+ module Growth
2
+ module Model::Reward
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ attribute :min_piece, :decimal, precision: 10, scale: 2, default: RailsGrowth.config.default_min_piece
7
+ attribute :max_piece, :decimal, precision: 10, scale: 2, default: RailsGrowth.config.default_max_piece
8
+ attribute :amount, :decimal, precision: 10, scale: 2
9
+ attribute :income_amount, :decimal, precision: 10, scale: 2
10
+ attribute :expense_amount, :decimal, precision: 10, scale: 2
11
+ attribute :start_at, :datetime
12
+ attribute :finish_at, :datetime
13
+ attribute :enabled, :boolean, default: true
14
+ attribute :lock_version, :integer
15
+
16
+ belongs_to :entity, polymorphic: true
17
+ has_many :reward_incomes, dependent: :destroy
18
+ has_many :praise_incomes, dependent: :destroy
19
+ has_many :reward_expenses, dependent: :destroy
20
+ has_many :aim_users, ->(o){ where(entity_type: o.entity_type) }, primary_key: :entity_id, foreign_key: :entity_id
21
+ has_many :praise_users, dependent: :destroy
22
+
23
+ validates :max_piece, numericality: { greater_than_or_equal_to: -> (o) { o.min_piece } }, allow_blank: true
24
+ validates :min_piece, numericality: { less_than_or_equal_to: -> (o) { o.max_piece } }, allow_blank: true
25
+ validates :amount, numericality: { greater_than_or_equal_to: 0 }, allow_blank: true
26
+ end
27
+
28
+ def compute_expense_amount
29
+ self.reward_expenses.sum(:amount)
30
+ end
31
+
32
+ def compute_income_amount
33
+ inhouse = self.reward_incomes.sum(:reward_amount)
34
+ praise = self.praise_incomes.sum(:reward_amount)
35
+
36
+ inhouse + praise
37
+ end
38
+
39
+ def available?
40
+ enabled? &&
41
+ amount > 0
42
+ end
43
+
44
+ def per_piece
45
+ if self.amount > 0
46
+ r = self.max_piece - 1 / (self.amount + 1/(self.max_piece - min_piece))
47
+ else
48
+ r = 0
49
+ end
50
+ pad = (max_piece - r)
51
+
52
+ rand((r - pad)..(r + pad)).round(2)
53
+ end
54
+
55
+ def save_with_amount(amount = 0)
56
+ self.reward_incomes.build(reward_amount: amount) if amount > 0
57
+ self.save
58
+ end
59
+
60
+ class_methods do
61
+ def entity_types
62
+ self.distinct(:entity_type).pluck(:entity_type)
63
+ end
64
+ end
65
+
66
+ end
67
+ end
@@ -0,0 +1,98 @@
1
+ module Growth
2
+ module Model::RewardExpense
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ attribute :amount, :decimal, precision: 10, scale: 2, default: 0
7
+
8
+ belongs_to :reward
9
+ belongs_to :user, optional: true
10
+ belongs_to :coin, primary_key: :user_id, foreign_key: :user_id, optional: true, inverse_of: :reward_expenses
11
+ belongs_to :aim, optional: true
12
+
13
+ has_one :aim_entity, inverse_of: :reward_expense
14
+ has_one :coin_log, -> (o){ where(user_id: o.user_id) }, as: :source
15
+ has_one :cash_log, -> (o){ where(user_id: o.user_id) }, as: :source
16
+
17
+ validates :amount, numericality: { greater_than_or_equal_to: 0 }
18
+
19
+ after_save :sync_to_reward, :sync_to_account, if: -> { saved_change_to_amount? }
20
+ after_create_commit :sync_log
21
+ end
22
+
23
+ def sync_to_reward
24
+ reward.reload
25
+ reward.expense_amount += self.amount
26
+ if reward.expense_amount == reward.compute_expense_amount
27
+ reward.save!
28
+ else
29
+ reward.errors.add :expense_amount, 'not equal'
30
+ logger.error "#{self.class.name}/Reward: #{reward.errors.full_messages.join(', ')}"
31
+ raise ActiveRecord::RecordInvalid.new(reward)
32
+ end
33
+ end
34
+
35
+ def sync_to_account
36
+ return unless user_id
37
+
38
+ if RailsGrowth.config.reward_purchase == 'Coin'
39
+ sync_to_coin
40
+ else
41
+ sync_to_cash
42
+ end
43
+ end
44
+
45
+ def sync_to_cash
46
+ cash = user.cash.reload
47
+
48
+ cash.income_amount += self.amount
49
+ if cash.income_amount == cash.compute_income_amount
50
+ cash.save!
51
+ else
52
+ cash.errors.add :income_amount, 'not equal'
53
+ logger.error "#{self.class.name}/Cash: #{cash.errors.full_messages.join(', ')}"
54
+ raise ActiveRecord::RecordInvalid.new(cash)
55
+ end
56
+ end
57
+
58
+ def sync_to_coin
59
+ coin = user.coin.reload
60
+ compute_amount = coin.compute_income_amount
61
+ coin.income_amount += self.amount
62
+ if coin.income_amount == compute_amount
63
+ coin.save!
64
+ else
65
+ coin.errors.add :income_amount, "Amount: #{coin.income_amount} not equal Compute: #{compute_amount}"
66
+ logger.error "#{self.class.name}/Coin: #{coin.errors.full_messages.join(', ')}"
67
+ raise ActiveRecord::RecordInvalid.new(coin)
68
+ end
69
+ end
70
+
71
+ def sync_log
72
+ return unless user_id
73
+
74
+ if RailsGrowth.config.reward_purchase == 'Coin'
75
+ sync_coin_log
76
+ else
77
+ sync_cash_log
78
+ end
79
+ end
80
+
81
+ def sync_cash_log
82
+ wl = self.cash_log || self.build_cash_log
83
+ wl.title = self.reward.entity&.title
84
+ wl.tag_str = self.aim&.name
85
+ wl.amount = self.amount
86
+ wl.save
87
+ end
88
+
89
+ def sync_coin_log
90
+ cl = self.coin_log || self.build_coin_log
91
+ cl.title = self.reward.entity&.title
92
+ cl.tag_str = self.aim&.name
93
+ cl.amount = self.amount
94
+ cl.save
95
+ end
96
+
97
+ end
98
+ end
@@ -0,0 +1,35 @@
1
+ module Growth
2
+ module Model::RewardIncome
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ attribute :reward_amount, :decimal, precision: 10, scale: 2, default: 0
7
+
8
+ belongs_to :reward, counter_cache: :incomes_count
9
+ belongs_to :user, optional: true
10
+
11
+ validates :reward_amount, numericality: { greater_than_or_equal_to: 0 }
12
+ after_create :sync_to_reward, if: -> { saved_change_to_reward_amount? }
13
+ after_update :reset_to_reward, if: -> { saved_change_to_reward_amount? }
14
+ end
15
+
16
+ def sync_to_reward
17
+ reward.reload
18
+ reward.income_amount += self.reward_amount
19
+ compute_amount = reward.compute_income_amount
20
+ if reward.income_amount == compute_amount
21
+ reward.save!
22
+ else
23
+ reward.errors.add :reward_amount, "#{reward.income_amount} not equal #{compute_amount}"
24
+ logger.error "#{self.class.name}/Reward: #{reward.errors.full_messages.join(', ')}"
25
+ raise ActiveRecord::RecordInvalid.new(reward)
26
+ end
27
+ end
28
+
29
+ def reset_to_reward
30
+ reward.income_amount = reward.compute_income_amount
31
+ reward.save!
32
+ end
33
+
34
+ end
35
+ end
@@ -0,0 +1,72 @@
1
+ # 给作者分成
2
+ module Growth
3
+ module Model::RoyaltyCompute
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ after_save :sync_to_royalty_account, if: -> { saved_change_to_royalty_amount? }
8
+ after_create_commit :sync_royalty_log, if: -> { saved_change_to_royalty_amount? }
9
+ end
10
+
11
+ def sync_to_royalty_account
12
+ if RailsGrowth.config.gift_purchase == 'Coin'
13
+ sync_to_royalty_coin
14
+ else
15
+ sync_to_royalty_wallet
16
+ end
17
+ end
18
+
19
+ def sync_to_royalty_coin
20
+ coin = earner.coin.reload
21
+
22
+ coin.income_amount += self.royalty_amount
23
+ compute_amount = coin.compute_income_amount
24
+ if coin.income_amount == compute_amount
25
+ coin.save!
26
+ coin.to_cash(coin_amount: royalty_amount)
27
+ else
28
+ coin.errors.add :income_amount, "Royalty: #{coin.income_amount} not equal #{compute_amount}"
29
+ logger.error "#{self.class.name}/Coin: #{coin.errors.full_messages.join(', ')}"
30
+ raise ActiveRecord::RecordInvalid.new(coin)
31
+ end
32
+ end
33
+
34
+ def sync_to_royalty_wallet
35
+ wallet = earner.wallet.reload
36
+
37
+ wallet.income_amount += self.royalty_amount
38
+ if wallet.income_amount == wallet.compute_income_amount
39
+ wallet.save!
40
+ else
41
+ wallet.errors.add :income_amount, 'not equal'
42
+ logger.error "#{self.class.name}/Wallet: #{wallet.errors.full_messages.join(', ')}"
43
+ raise ActiveRecord::RecordInvalid.new(wallet)
44
+ end
45
+ end
46
+
47
+ def sync_royalty_log
48
+ if RailsGrowth.config.gift_purchase == 'Coin'
49
+ sync_royalty_coin_log
50
+ else
51
+ sync_royalty_wallet_log
52
+ end
53
+ end
54
+
55
+ def sync_royalty_wallet_log
56
+ wl = self.royalty_wallet_logs.build
57
+ wl.title = I18n.t('wallet_log.income.praise_income.title')
58
+ wl.tag_str = I18n.t('wallet_log.income.praise_income.tag_str')
59
+ wl.amount = self.royalty_amount
60
+ wl.save
61
+ end
62
+
63
+ def sync_royalty_coin_log
64
+ cl = self.royalty_coin_logs.build
65
+ cl.title = I18n.t('coin_log.income.praise_income.title')
66
+ cl.tag_str = I18n.t('coin_log.income.praise_income.tag_str')
67
+ cl.amount = self.royalty_amount
68
+ cl.save
69
+ end
70
+
71
+ end
72
+ end
@@ -0,0 +1,21 @@
1
+ module Growth
2
+ module Model::User
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ has_many :aim_users, dependent: :destroy
7
+ has_many :aim_entities, dependent: :nullify
8
+ has_many :aims, through: :aim_users
9
+ has_many :aim_logs
10
+ has_many :reward_expenses
11
+ end
12
+
13
+ def reward_amount
14
+ self.reward_expenses.sum(:amount)
15
+ end
16
+
17
+ def xx
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,7 @@
1
+ module Growth
2
+ class PraiseIncome < ApplicationRecord
3
+ include Model::PraiseIncome
4
+ include Model::PraiseCompute
5
+ include Model::RoyaltyCompute
6
+ end
7
+ end
@@ -0,0 +1,5 @@
1
+ module Growth
2
+ class PraiseUser < ApplicationRecord
3
+ include Model::PraiseUser
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ module Growth
2
+ class Reward < ApplicationRecord
3
+ include Model::Reward
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ module Growth
2
+ class RewardExpense < ApplicationRecord
3
+ include Model::RewardExpense
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ module Growth
2
+ class RewardIncome < ApplicationRecord
3
+ include Model::RewardIncome
4
+ end
5
+ end
@@ -0,0 +1,11 @@
1
+ module Growth
2
+
3
+ def self.use_relative_model_naming?
4
+ true
5
+ end
6
+
7
+ def self.table_name_prefix
8
+ 'growth_'
9
+ end
10
+
11
+ end
@@ -0,0 +1,12 @@
1
+ <div class="<%= active_helper(modules: 'growth/admin', active: 'menu ex-accordion is-active', item: 'menu ex-accordion') %>" data-controller="menu">
2
+ <%= content_tag :div, class: 'menu-list' do %>
3
+ <%= link_to '任务管理', admin_aims_path, class: active_helper(controllers: 'aims', active: 'is-active') %>
4
+ <%= link_to '赏金管理', admin_rewards_path, class: active_helper(controllers: 'rewards', active: 'is-active') %>
5
+ <%= link_to '打赏管理', admin_gifts_path, class: active_helper(controllers: 'gifts', active: 'is-active') -%>
6
+ <% end %>
7
+ <a class="menu-label" data-action="menu#toggle">
8
+ <i class="fas fa-calendar-check"></i>
9
+ <span><%= t('growth.admin.title') %></span>
10
+ <i class="fas dropdown"></i>
11
+ </a>
12
+ </div>
@@ -0,0 +1,10 @@
1
+ <%= form_with theme: 'search', model: AimEntity.new do |f| %>
2
+ <div class="fields">
3
+ <%= f.text_field :ip %>
4
+ <%= f.text_field :entity_type %>
5
+ <%= f.text_field :entity_id %>
6
+ <%= f.submit 'Search' %>
7
+ </div>
8
+ <% end %>
9
+
10
+