topics
| id |
|
title bumped_at |
posts
| id topic_id(fk) |
| content |
has_many
Topic
Post
Post
Post
多住戶架構
moral of the rewrite #1
TopicController#create
(for creating new topic)
PostController#create
(for replying)
<%= form_for(@topic, format:'json', remote:true) do |f| %>
<%= f.hidden_field :board_id %>
<%= f.fields_for :posts, @post do |pf| %>
<div class="field">
<%= pf.label :author %>
<%= pf.text_field :author %>
</div>
<div class="field">
<%= pf.label :email %>
<%= pf.text_field :email %>
</div>
<%= render_cell :post, :image_upload_control, pf %>
<%= pf.label :content %>
<%= pf.text_area :content %>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %><%= form_for(@post, format:'json', remote:true) do |f| %>
<%= f.hidden_field :topic_id %>
<div class="field">
<%= f.label :author %>
<%= f.text_field :author %>
</div>
<div class="field">
<%= f.label :email %>
<%= f.text_field :email %>
</div>
<%= render_cell :post, :image_upload_control, f %>
<%= f.label :content %>
<%= f.text_area :content %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>TWO SETS OF _form.html.erb
TWO SETS OF create action
TWO SETS OF strong parameter
TWO SETS OF CSS selector
TWO SETS OF error handling
TWO SETS OF JS DOM manipulation
TWO SETS OF tests
kekeke
New Topic
Reply
○(#‵︿′ㄨ)○ that's it
Combine them will save brain-power,
making it easier to reuse code,
less potential bugs
清爽
所以每次看到這些重複的時候就十分讓我不爽
class PostForm
include ActiveModel::Model
attr_accessor :topic, :post
def attributes(params)
if new_topic?
@topic.assign_attributes(topic_params(params))
end
@post.assign_attributes(post_params(params))
@post.images << build_images_from_params(params)
end
delegate :title,
:board_id, to: :topic
delegate :author,
:content,
:email,
:topic_id,
:images, to: :post def valid?
validity = true
errors.clear
[post, topic].each do |object|
if !object.valid?
validity = false
object.errors.each do |key, values|
errors[key] = values
end
end
end
validity
end
def save
return false if !valid?
ActiveRecord::Base.transaction do
@post.save! if @post.changed?
@topic.save! if new_topic?
end
true
rescue ActiveRecord::RecordInvalid => invalid
false
endBoth forms are now from the same erb view,
and points to same PostController#create \⊙▽⊙/
ALL ROADS LEAD TO ROME
Framework's Way can't always help you.
morale of the rewrite #2
def show
@books = [
"三体",
"Spin",
"アイの物語",
]
end<% @books.each do |b| %>
<%= b %>
<% end %>def show
end<% @books.each do |b| %>
<%= b %>
<% end %>ERROR
if you forget to prepare it,
view will error out
<%= render partial: "ad",
locals: {var: var} %>_ad.html.erb
AD1
<%= var.get_ad() %><%= render_cell :ad, :show, var %>app/cells/ad/show.html.erb
AD1
<%= @var.get_ad() %>class AdCell < Cell::Rails
def show(var)
@var = var
render
end
end準備資料
show.html.erb
<% @text = "el psy congroo" %>
<%= render partial: :foo %>partial
<%= @text %>show.html.erb
<% @text = "el psy congroo" %>
<%= render_cell :foo, :bar, @text %>partial
<%= @text %>No @var contamination
封裝
partial
<% beers = if foo?
Beer.where("name like ?", b)
elsif bar?
Beer.where("name like ?", c)
end
%>
<% beers.each do |b| %>
<%= b.name %>
<% end %>cell
def show
@beers = if foo?
Beer.where("name like ?", b)
elsif bar?
Beer.where("name like ?", c)
end
render
end
<% @beers.each do |b| %>
<%= b.name %>
<% end %>partial
<% cache("#{@foo}-#{@foo.replies.last.updated_at}", expires_in: 60.seconds) do %>
<%= @foo.title %><br />
<%= @foo.body %><br />
<% end>cell
def show(foo)
@foo = foo
render
end
cache :show, expires_in: 60.seconds do |cell, foo|
[@foo, @foo.replies.last.updated_at]
endcell view
<%= @foo.title %><br />
<%= @foo.body %><br />
very long cache key logic
helper
module FooHelper
def foo_body
# if only used in foo partial
end
endcell
def show(foo)
@foo = foo
render
end
private
def body
endcell view
<%= body %>
partial
<%= foo_body %>For now I recommend cells version 3.11
instead of 4.x
sorry nick don't hit me
Last change:
if you forget to prepare it,
view will error out
To re-iterate
def update
@book = Book.find(params[:id])
if @book.update(book_params)
redirect_to @book, notice: 'Good!'
else
render :edit
end
end def edit
@book = Book.find(params[:id])
@obscure_var = "52" # which is easy to forget
endremote: trueform_for(@post_form) do |f|form_for(@post_form,
remote:true,
format:'json',
data:{type: :json}) do |f|remotipart gem
Many iterations until I got out of the pitfall
now what?
Part III
$boardQuery = prepare("SELECT COUNT(1) AS
'boards_total', SUM(indexed) AS 'boards_public', SUM(posts_total) AS 'posts_total' FROM ``boards``");
$boardQuery->execute() or error(db_error($tagQuery));
$boardResult = $boardQuery->fetchAll(PDO::FETCH_ASSOC)[0];
$boards_hidden = number_format( $boardResult['boards_total'] - $boardResult['boards_public'], 0 );
$boards_omitted = (int) $searchJson['omitted'];
$posts_total = number_format( $boardResult['posts_total'], 0 );I was reminded that why I started learning Rails 3 years ago
1. Ruby aims to make programmers happy
2. Rails framework guides and help me to make decisions
and FAQ time
thank you
﹨(╯▽╰)∕