manage_cache 0.0.2 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/manage_cache/version.rb +1 -1
- data/lib/manage_cache.rb +70 -13
- data/test/dummy/app/controllers/shoes_controller.rb +9 -0
- data/test/dummy/app/models/shoe.rb +5 -1
- data/test/dummy/app/models/user.rb +2 -1
- data/test/dummy/app/views/shoes/index.html.erb +31 -0
- data/test/dummy/app/views/users/index.html.erb +32 -31
- data/test/dummy/db/development.sqlite3 +0 -0
- data/test/dummy/log/development.log +637 -0
- data/test/dummy/log/test.log +28824 -0
- data/test/dummy/test/controllers/shoes_controller_test.rb +32 -0
- data/test/dummy/test/controllers/users_controller_test.rb +27 -8
- data/test/dummy/test/models/shoe_test.rb +22 -0
- data/test/dummy/test/models/user_test.rb +1 -1
- data/test/dummy/tmp/cache/A4A/A50/spec%3Dshoe_color-shoe_id%3D1 +1 -0
- data/test/dummy/tmp/pids/server.pid +1 -1
- metadata +12 -102
- data/test/dummy/tmp/cache/2CC/2D0/views%2F +0 -2
- data/test/dummy/tmp/cache/527/491/views%2Fspec-row_name%2Fuser-1%2Fupdated_at-2016-01-14+10%3A20%3A57+UTC +0 -2
- data/test/dummy/tmp/cache/528/731/views%2Fspec-row_name%2Fuser-2%2Fupdated_at-2016-01-14+10%3A20%3A57+UTC +0 -2
- data/test/dummy/tmp/cache/529/781/views%2Fspec-row_name%2Fuser-2%2Fupdated_at-2016-01-14+10%3A20%3A58+UTC +0 -2
- data/test/dummy/tmp/cache/52D/8B1/views%2Fspec-row_name%2Fuser-1%2Fupdated_at-2016-01-14+10%3A19%3A28+UTC +0 -2
- data/test/dummy/tmp/cache/96B/891/views%2Fspec-users_shoes%2Fuser-1%2Flast_updated_shoe-2016-01-14+10%3A15%3A40+UTC +0 -2
- data/test/dummy/tmp/cache/96F/8B1/views%2Fspec-users_shoes%2Fuser-1%2Flast_updated_shoe-2016-01-14+10%3A20%3A57+UTC +0 -2
- data/test/dummy/tmp/cache/970/901/views%2Fspec-users_shoes%2Fuser-1%2Flast_updated_shoe-2016-01-14+10%3A20%3A58+UTC +0 -2
- data/test/dummy/tmp/cache/sprockets/v3.0/09_lxM-eb2oUZWnlGLaq4F_i5h92ZObg36ae6gKq1i4.cache +0 -1
- data/test/dummy/tmp/cache/sprockets/v3.0/2sW6NMnj6fqDuDeMj9N8u0O_kfcyACbGT_bxWVLBSZ0.cache +0 -1
- data/test/dummy/tmp/cache/sprockets/v3.0/5Lly_CA8DZvPhQV2jDQx-Y6P_y3Ygra9t5jfSlGhHDA.cache +0 -2
- data/test/dummy/tmp/cache/sprockets/v3.0/8Lqz2M_JZndvJcmnZET75uPOyo75Jv4B3i0ZQImFJlM.cache +0 -0
- data/test/dummy/tmp/cache/sprockets/v3.0/9MxgZ11k1FnO5lx1r1HHNz5GnkAF3P5DOpS8p2oMyZQ.cache +0 -1
- data/test/dummy/tmp/cache/sprockets/v3.0/9d-nHTd-aCK04uRrii3hSfpYzj5iP2Ob1d-_qWKjCek.cache +0 -1
- data/test/dummy/tmp/cache/sprockets/v3.0/CRKJnPJGBJ_Dy0-QfKhF5WPh6Gj5skuy0TXmBjMTSnQ.cache +0 -2
- data/test/dummy/tmp/cache/sprockets/v3.0/DSOLSc6A5RVSmvM415eEWAWG_AgOvZcLZOXQjsXyWQA.cache +0 -2
- data/test/dummy/tmp/cache/sprockets/v3.0/Dl-NUisCUKKISrWE7M2oFXVpPFicurw2Va50_nNMy3k.cache +0 -0
- data/test/dummy/tmp/cache/sprockets/v3.0/DmmfrCpXtt74Hr6NO54lxyOCDv6klnDyBqeDFR7oDU8.cache +0 -2
- data/test/dummy/tmp/cache/sprockets/v3.0/GYYAJ3FkbQM0cLSTLqUzVyuWYL1B1AWg4FCEmXXUG9U.cache +0 -0
- data/test/dummy/tmp/cache/sprockets/v3.0/GkLvvxrkyX0_w9FNcSslwfEV_JzAAtRlVKM3dZAxI18.cache +0 -0
- data/test/dummy/tmp/cache/sprockets/v3.0/IcrjOgrUk68EJPgCdByEHzKfEKryUjeyKSWq-PEGf2E.cache +0 -0
- data/test/dummy/tmp/cache/sprockets/v3.0/K1DTLxe-bgF1wVbSJm2QUY_CMGj5J3FUTtHsoxl1EQc.cache +0 -1
- data/test/dummy/tmp/cache/sprockets/v3.0/K4HSx9qgV9xEpmTXd6xgKL4fYHWKC4MU_RY6n7TFk9Q.cache +0 -1
- data/test/dummy/tmp/cache/sprockets/v3.0/NwJZbK1pDbU-pMc7IsK2Rx1MwN4EaXyDMUKuzQCHPCw.cache +0 -1
- data/test/dummy/tmp/cache/sprockets/v3.0/OI6uxGcnsKavdWTtwDAasU3wPx8QXhzBgV0X2n1KjMQ.cache +0 -2
- data/test/dummy/tmp/cache/sprockets/v3.0/SXVHiwpmgcQmM4FyGzKKwKiM3jCMr8EGhSJpQiC9wcQ.cache +0 -1
- data/test/dummy/tmp/cache/sprockets/v3.0/UBbOS5C2oSAcdKvW_Z-oEtU6_8rnuMx9M2G3o_5QN6s.cache +0 -1
- data/test/dummy/tmp/cache/sprockets/v3.0/Uviw7jE916HhqccasMRdQ5CTXoBqH7dxweEg_bsm3K0.cache +0 -1
- data/test/dummy/tmp/cache/sprockets/v3.0/VPOhaapUo-sv4VGkt6by3qUT2B4T2kSjaHb89uicvYU.cache +0 -0
- data/test/dummy/tmp/cache/sprockets/v3.0/a9sNeDvMqAwAX-rnnfZrdNjSIz_Ak1KVT1kNS8SeGas.cache +0 -1
- data/test/dummy/tmp/cache/sprockets/v3.0/eZXj2eM6sa6zSFHhekBC5TX_Pddob3sO7hyhYVAb0fg.cache +0 -2
- data/test/dummy/tmp/cache/sprockets/v3.0/evilMWS_uDxgvUtMe_HRyK3ZfZo7bBegojhsvLdjcKw.cache +0 -0
- data/test/dummy/tmp/cache/sprockets/v3.0/eyQ1Iet2dzYcWDsu5qBemC0D5l3jdLLgchA4fkh5nnc.cache +0 -0
- data/test/dummy/tmp/cache/sprockets/v3.0/g5ekayFy2lyNSg0qaf9pHIi9AUYJ8eKcPfhsV0yqkPU.cache +0 -1
- data/test/dummy/tmp/cache/sprockets/v3.0/gZp3uXMHuYQC4hzCr7bQfetKNdJAtbQmg3so2KpW1Dw.cache +0 -2
- data/test/dummy/tmp/cache/sprockets/v3.0/hZi1k6tpxxCGYxRe7zY74ItcOI8gZrREOpGuA8JSpGg.cache +0 -2
- data/test/dummy/tmp/cache/sprockets/v3.0/iDTnVSbZnIij5Xm4jkwCyIXAPDn8RwaRe5Ja8YPKibw.cache +0 -2
- data/test/dummy/tmp/cache/sprockets/v3.0/iHYDh87b9nTCgd6e7YCtB9CqNPhoxyyqir0EhBx1-Rk.cache +0 -1
- data/test/dummy/tmp/cache/sprockets/v3.0/kyugOtp1okMz23E1fAOMqsyMHj1vAxVX-UWy0S4ZEAg.cache +0 -2
- data/test/dummy/tmp/cache/sprockets/v3.0/mXy3FNW22ItExIRbbqYnT6XBDj9QYoqBC8ZzyFWncGs.cache +0 -2
- data/test/dummy/tmp/cache/sprockets/v3.0/oiA-NPgVz4-xBX3Ri3o3lAS3l-EKuTmQ7OdbfrVdtAc.cache +0 -2
- data/test/dummy/tmp/cache/sprockets/v3.0/ovnZOq_jVOpE2KrlsIEIX-KoxHk-acnpn9KcSJbfkfw.cache +0 -0
- data/test/dummy/tmp/cache/sprockets/v3.0/pEhaat2KBd5SrT7szC_8R1_6hK17FTpvoRFkmCRSD3M.cache +0 -2
- data/test/dummy/tmp/cache/sprockets/v3.0/r-A0ga7LeDzW9Vsra2ECnPQdYszihD4iU_kddis_m9c.cache +0 -2
- data/test/dummy/tmp/cache/sprockets/v3.0/rtcJ_islohXm8x0bqaTIpW2nOttNweCIQw0qzQkEabo.cache +0 -1
- data/test/dummy/tmp/cache/sprockets/v3.0/tI6TANdxXMulmZuDkMCGk02plL26Vj9VGCuNvCZ8SyY.cache +0 -1
- data/test/dummy/tmp/cache/sprockets/v3.0/tbLteZ12v3ZDVzL-ACWn314an41wFJYQx3GCldsqR-w.cache +0 -1
- data/test/dummy/tmp/cache/sprockets/v3.0/vftuHuDXEagG2jsCk15VnJkFiSbkIBPZ59tyv5e0XRo.cache +0 -0
- data/test/dummy/tmp/cache/sprockets/v3.0/ydw-EtO01i7QnaD3kHyY0f5ol82z0etd9JYXcNRT0SA.cache +0 -2
- data/test/dummy/tmp/cache/sprockets/v3.0/zehql4552SVo4rZUU8Bpz_cxFIk74U7tZNmhhxX89ew.cache +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8c6b89b1174e6e8de32dd2c4377c0a7c8310667b
|
|
4
|
+
data.tar.gz: a63333addfe87c886664560ebb213593ca801747
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ac15c9377dd6b2f8aeaa0eb75425f061c5898751f8d0ef857a23c48d3f8cfdb25ff4d9d9ac0fb3cb8fa9728de0f0b43e1edcfa591a66f28d185033b94ac2e87b
|
|
7
|
+
data.tar.gz: ca9c366286f894fbce112fd34cfef6e8c194046e385ffe49492aa0e4f5be4a5fdaae9db836c93157c4dcf81fbb342de19b5d528ac1b6989a284ecc6a64eb5ba0
|
data/lib/manage_cache/version.rb
CHANGED
data/lib/manage_cache.rb
CHANGED
|
@@ -22,36 +22,43 @@ module ManageCache
|
|
|
22
22
|
|
|
23
23
|
module LocalInstanceMethods
|
|
24
24
|
def dump_cache!
|
|
25
|
-
self.class.cache_keys_specs.each do |
|
|
25
|
+
self.class.cache_keys_specs.each do |key_name, key_specs|
|
|
26
26
|
# the rails helper method 'cache (name, opts) do ...'
|
|
27
27
|
# adds some extras to the cache key.
|
|
28
28
|
# To run with this gem, you have to add 'skip_digest: true'.
|
|
29
29
|
# Any other options will prevent correct cache deletion!!
|
|
30
30
|
#
|
|
31
|
-
[cache_key_for(
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
31
|
+
[cache_key_for(key_name), "views/#{cache_key_for(key_name)}"].each do |key|
|
|
32
|
+
if !key_specs[:regexp].blank?
|
|
33
|
+
delete_cache_w_regexp(key, key_specs)
|
|
34
|
+
else
|
|
35
|
+
Rails.cache.delete(key)
|
|
36
|
+
end
|
|
37
|
+
instance_variable_set("@cache_key_for_#{key_name}", nil)
|
|
38
|
+
end if delete_cache?(key_specs)
|
|
36
39
|
end
|
|
37
40
|
end
|
|
38
41
|
|
|
39
|
-
def cache_key_for(spec)
|
|
42
|
+
def cache_key_for(spec, opts={})
|
|
40
43
|
instance_variable_get("@cache_key_for_#{spec}") ||
|
|
41
|
-
instance_variable_set("@cache_key_for_#{spec}", prepare_cache_key(spec))
|
|
44
|
+
instance_variable_set("@cache_key_for_#{spec}", prepare_cache_key(spec, opts))
|
|
42
45
|
end
|
|
43
46
|
|
|
44
47
|
private
|
|
45
48
|
|
|
46
|
-
def prepare_cache_key(spec)
|
|
49
|
+
def prepare_cache_key(spec, opts={})
|
|
47
50
|
cache_key = {}
|
|
48
51
|
|
|
49
52
|
key_specs = self.class.cache_keys_specs[spec]
|
|
50
53
|
|
|
54
|
+
if key_specs.blank?
|
|
55
|
+
raise "The specification for cache_key '#{spec}' is missing in manage_cache in #{self.class.name}."
|
|
56
|
+
end
|
|
57
|
+
|
|
51
58
|
# some extra specification like :show or :index_row
|
|
52
59
|
# defaults to the spec-key
|
|
53
60
|
#
|
|
54
|
-
cache_key[:spec] =
|
|
61
|
+
cache_key[:spec] = spec
|
|
55
62
|
|
|
56
63
|
# named values from some method calls
|
|
57
64
|
# the easiest case would be updated_at e.g.:
|
|
@@ -73,7 +80,7 @@ module ManageCache
|
|
|
73
80
|
# and this cache_key could be used somewhere where the user`s shoes are shown e.g. :show or :index
|
|
74
81
|
#
|
|
75
82
|
# e.g.
|
|
76
|
-
# <% cache user.shoes.last.try
|
|
83
|
+
# <% cache user.shoes.last.try(:cache_key_for, :users_shoes), skip_digest: true do %>
|
|
77
84
|
# ....
|
|
78
85
|
#
|
|
79
86
|
# it is enough to take one of the users` shoes for the cache_key here
|
|
@@ -82,11 +89,61 @@ module ManageCache
|
|
|
82
89
|
#
|
|
83
90
|
key_specs[:instance_eval].each do |name, cmd|
|
|
84
91
|
cache_key[name] = self.instance_eval(cmd.to_s)
|
|
85
|
-
end
|
|
92
|
+
end if key_specs[:instance_eval]
|
|
86
93
|
|
|
87
|
-
|
|
94
|
+
key_specs[:class_eval].each do |name, cmd|
|
|
95
|
+
cache_key[name] = self.class.class_eval(cmd.to_s)
|
|
96
|
+
end if key_specs[:class_eval]
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
# merge static values from manage_cache_for sth: { static: 'static' }
|
|
100
|
+
#
|
|
101
|
+
# and opts from cache_key_for, like:
|
|
102
|
+
# <% cache cache_key_for(:sth, page: params[:page]) %>
|
|
103
|
+
#
|
|
104
|
+
[key_specs[:static], opts].each do |hash|
|
|
105
|
+
cache_key.reverse_merge!(hash) if hash
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
cache_key.inject([]){ |mem, (k,v)| mem << "#{k}=#{v}" }.join('-')
|
|
88
109
|
end
|
|
89
110
|
|
|
111
|
+
#
|
|
112
|
+
# Opts added to cache_key_for will be suffixed to the rest of
|
|
113
|
+
# the cache_key.
|
|
114
|
+
# For these opts to take effect on cache management (e.g. deletion)
|
|
115
|
+
# use `regexp: { opts_key: "matcher_string" , .... }
|
|
116
|
+
# e.g.:
|
|
117
|
+
#
|
|
118
|
+
# in the paginated index view:
|
|
119
|
+
#
|
|
120
|
+
# <% cache @users.last.try(:cache_key_for, :users_index, page: params[:page]) do %>
|
|
121
|
+
#
|
|
122
|
+
# in the model:
|
|
123
|
+
#
|
|
124
|
+
# class User < ActiveRecord::Base
|
|
125
|
+
# manage_cache_for users_index: {
|
|
126
|
+
# class_eval: { max_up: "maximum(:updated_at)"}
|
|
127
|
+
# regexp: { page: "\\d+" }
|
|
128
|
+
# }
|
|
129
|
+
#
|
|
130
|
+
# be aware, that the matcher_string has to be escaped (e.g. "\\d+" instead of "\d+")!
|
|
131
|
+
#
|
|
132
|
+
def delete_cache_w_regexp(key, specs)
|
|
133
|
+
regexp = specs[:regexp].inject([]){|m, (k,v)| m << "#{k}=#{v}" }.join('-')
|
|
134
|
+
Rails.cache.delete_matched(/^#{Regexp.escape(key)}-#{regexp}$/)
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
# if some attributes are specified in :if_changed
|
|
138
|
+
# check whether they changed
|
|
139
|
+
# and delete cache only if they changed
|
|
140
|
+
#
|
|
141
|
+
# if not specified delete cache
|
|
142
|
+
#
|
|
143
|
+
def delete_cache?(key_specs)
|
|
144
|
+
!key_specs[:if_changed] or
|
|
145
|
+
self.changed.length > (self.changed - key_specs[:if_changed].map(&:to_s)).length
|
|
146
|
+
end
|
|
90
147
|
end
|
|
91
148
|
end
|
|
92
149
|
|
|
@@ -3,7 +3,11 @@ class Shoe < ActiveRecord::Base
|
|
|
3
3
|
belongs_to :user
|
|
4
4
|
validates :user_id, presence: true
|
|
5
5
|
|
|
6
|
-
manage_cache_for users_shoes: { instance_eval: { user: "user.id", last_updated_shoe: "user.shoes.maximum(:updated_at)" } }
|
|
6
|
+
manage_cache_for users_shoes: { instance_eval: { user: "user.id", last_updated_shoe: "user.shoes.maximum(:updated_at)" } },
|
|
7
|
+
users_index: { instance_eval: { max_up: "user.class.maximum(:updated_at)"} },
|
|
8
|
+
shoes_index: { class_eval: { max_up: "maximum(:updated_at)" }, regexp: { page: "\\d*" } },
|
|
9
|
+
shoe_color: { instance_eval: { shoe_id: :id}, if_changed: [:color] }
|
|
10
|
+
|
|
7
11
|
|
|
8
12
|
def name_with_color
|
|
9
13
|
"#{name}: #{color}"
|
|
@@ -3,7 +3,8 @@ class User < ActiveRecord::Base
|
|
|
3
3
|
has_many :shoes
|
|
4
4
|
|
|
5
5
|
manage_cache_for show: { instance_eval: { user: :id, updated_at: :updated_at } },
|
|
6
|
-
row_name: { instance_eval: { user: :id, updated_at: :updated_at } }
|
|
6
|
+
row_name: { instance_eval: { user: :id, updated_at: :updated_at } },
|
|
7
|
+
users_index: { class_eval: { max_up: "maximum(:updated_at)"} }
|
|
7
8
|
|
|
8
9
|
def nice_name
|
|
9
10
|
"nice name is #{name}"
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
<p id="notice"><%= notice %></p>
|
|
2
|
+
|
|
3
|
+
<% cache @shoes.last.try(:cache_key_for, :shoes_index, page: params[:page] || 1), skip_digest: true do %>
|
|
4
|
+
<h1>Listing shoes</h1>
|
|
5
|
+
|
|
6
|
+
<table>
|
|
7
|
+
<thead>
|
|
8
|
+
<tr>
|
|
9
|
+
<th>Name</th>
|
|
10
|
+
<th>Color</th>
|
|
11
|
+
<th colspan="3"></th>
|
|
12
|
+
</tr>
|
|
13
|
+
</thead>
|
|
14
|
+
|
|
15
|
+
<tbody>
|
|
16
|
+
<% @shoes.each do |shoe| %>
|
|
17
|
+
<tr>
|
|
18
|
+
<td> <%= shoe.name %> </td>
|
|
19
|
+
<td> <%= shoe.color %> </td>
|
|
20
|
+
<td><%= link_to 'Show', shoe %></td>
|
|
21
|
+
<td><%= link_to 'Edit', edit_shoe_path(shoe) %></td>
|
|
22
|
+
<td><%= link_to 'Destroy', shoe, method: :delete, data: { confirm: 'Are you sure?' } %></td>
|
|
23
|
+
</tr>
|
|
24
|
+
<% end %>
|
|
25
|
+
</tbody>
|
|
26
|
+
</table>
|
|
27
|
+
|
|
28
|
+
<br>
|
|
29
|
+
|
|
30
|
+
<%= link_to 'New shoe', new_shoe_path %>
|
|
31
|
+
<% end %>
|
|
@@ -1,38 +1,39 @@
|
|
|
1
1
|
<p id="notice"><%= notice %></p>
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
<% cache @users.last.try(:cache_key_for, :users_index), skip_digest: true do %>
|
|
4
|
+
<h1>Listing Users</h1>
|
|
4
5
|
|
|
5
|
-
<table>
|
|
6
|
-
|
|
7
|
-
<tr>
|
|
8
|
-
<th>Name</th>
|
|
9
|
-
<th>Shoes</th>
|
|
10
|
-
<th colspan="3"></th>
|
|
11
|
-
</tr>
|
|
12
|
-
</thead>
|
|
13
|
-
|
|
14
|
-
<tbody>
|
|
15
|
-
<% @users.each do |user| %>
|
|
6
|
+
<table>
|
|
7
|
+
<thead>
|
|
16
8
|
<tr>
|
|
17
|
-
<
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
<% end %>
|
|
21
|
-
</td>
|
|
22
|
-
<td>
|
|
23
|
-
<% cache user.shoes.last.try(:cache_key_for, :users_shoes), skip_digest: true do %>
|
|
24
|
-
<%= user.shoes.map(&:name_with_color).join(',') %>
|
|
25
|
-
<%#= user.shoes.map{|shoe| "#{shoe.name}:#{shoe.color}"}.join(',') %>
|
|
26
|
-
<% end %>
|
|
27
|
-
</td>
|
|
28
|
-
<td><%= link_to 'Show', user %></td>
|
|
29
|
-
<td><%= link_to 'Edit', edit_user_path(user) %></td>
|
|
30
|
-
<td><%= link_to 'Destroy', user, method: :delete, data: { confirm: 'Are you sure?' } %></td>
|
|
9
|
+
<th>Name</th>
|
|
10
|
+
<th>Shoes</th>
|
|
11
|
+
<th colspan="3"></th>
|
|
31
12
|
</tr>
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
13
|
+
</thead>
|
|
14
|
+
|
|
15
|
+
<tbody>
|
|
16
|
+
<% @users.each do |user| %>
|
|
17
|
+
<tr>
|
|
18
|
+
<td>
|
|
19
|
+
<% cache user.cache_key_for(:row_name), skip_digest: true do %>
|
|
20
|
+
<%= user.nice_name %>
|
|
21
|
+
<% end %>
|
|
22
|
+
</td>
|
|
23
|
+
<td>
|
|
24
|
+
<% cache user.shoes.last.try(:cache_key_for, :users_shoes), skip_digest: true do %>
|
|
25
|
+
<%= user.shoes.map(&:name_with_color).join(',') %>
|
|
26
|
+
<% end %>
|
|
27
|
+
</td>
|
|
28
|
+
<td><%= link_to 'Show', user %></td>
|
|
29
|
+
<td><%= link_to 'Edit', edit_user_path(user) %></td>
|
|
30
|
+
<td><%= link_to 'Destroy', user, method: :delete, data: { confirm: 'Are you sure?' } %></td>
|
|
31
|
+
</tr>
|
|
32
|
+
<% end %>
|
|
33
|
+
</tbody>
|
|
34
|
+
</table>
|
|
35
35
|
|
|
36
|
-
<br>
|
|
36
|
+
<br>
|
|
37
37
|
|
|
38
|
-
<%= link_to 'New User', new_user_path %>
|
|
38
|
+
<%= link_to 'New User', new_user_path %>
|
|
39
|
+
<% end %>
|
|
Binary file
|