23 Jun 2023
Philosophy
- Views are for presentation.
- There should be no
ActiveRecord
queries in views.
- Most logic (
if
statements) should be excluded from views.
Why Not Helpers?
Helpers are better to use if you have a global formatting method that you re-use in different views.
Things like:
- rendering markdown
- showing dates in a specific format
- removing specific words from text
Helpers are not great to overuse because they lack organization and are difficult to reuse across your app.
Using Presenter Objects
- create
app/presenters
.
- name after model,
app/presenters/post_presenter.rb
.
class PostPresenter
def initialize(post)
@post = post
end
def title_without_forbidden_words
@post.title.gsub("forbidden word", "")
end
def css_color
@post.draft? ? "orange" : "green"
end
end
<% presenter = PostPresenter.new(post) %>
<p>
Post title: <%= presenter.title_without_forbidden_words %>
<%= link_to "Read post", post, class: "w-75 p-3 text-#{presenter.css_color} border-#{presenter.css_color}" %>
</p>
This accomplishes a few things:
- it removes logic from views
- creates meaningful names for methods and logic
- allows logic to more easily be reused in other views and mailers
Rails Design Patterns: Presenter & Service Objects
22 Jun 2023
TIL something weird.
I expected this to print “Integer”, but it doesn’t:
mystery_class = Integer
case mystery_class
when Integer
p "Integer"
else
p "Unknown"
end
# => "Unknown"
This was weird because a similar example appears to behave differently:
mystery_instance = 0
case mystery_instance
when 0
p "Y"
else
p "N"
end
# => "Y"
Apparently this is because []case
uses ===
under the hood](https://stackoverflow.com/a/3908411) and ===
has kind of silly behavior when comparing classes.
For example:
Array === Array # false
0 === 0 # true
Class === Array # true
apparently case
also works different with ActiveRecord
classes, since they’ll use is_a?
instead which might also behave differently??? 😱
Anyway, if you want to use case
with classes for ActiveRecord
object you need to do this:
mystery_class = User.last
case mystery_class
when User
p "User"
else
p "Unknown"
end
# => "User"
22 Jun 2023
Occassionally, when working on an app with a lot of active branches that affect the database I run into an issue where I can’t rollback.
I’ll get an error like this:
rails aborted!
ActiveRecord::UnknownMigrationVersionError:
No migration with version number 20230620205505.
This usually happens when I switch to another branch and I want to rollback a change I made to update/remove the migration. I assume the migration referenced in database doesn’t exist on the current branch.
If this happens, you can roll back to the last migration on the branch with:
rails db:migrate:down VERSION=n
where n
is the timestamp from the latest migration (something like 20230607135355
).
This is only applicable for non-sqlite3 databases, since the database doesn’t live in the project directory.
02 Jun 2023
The server won’t work out of the box if you run the generate command with npm
version < 7.1
.
In particular, with < 7.1
, you have to add the build commands to the package.json
scripts yourself.
See this SO answer for more details.
I had mistakenly generated an app with a npm v6.8 b/c I used n
to switch NodeJS versions to debug a student assignment and apparently never switched back.
I sure hope that hasn’t been the cause of other issues I ran into 😅
26 May 2023
Normally if you run a file from inside another script, it can be tricky to get get error message sometimes.
For example:
3.2.1 :001 > `ruby test.rb`
test.rb: --> test.rb
Unmatched `(', missing `)' ?
> 4 p("{}"
test.rb:4: syntax error, unexpected end-of-input, expecting ')' (SyntaxError)
p("{}"
^
=> ""
3.2.1 :002 >
The error message still is displayed in the shell, but it’s missing from the return value, which is the important thing if we’re running this inside another script/app.
The output is being displayed through stderr
and not stdout
.
There’s a trick you can do to merge stderr
into stdout
.
ruby test.rb 2>&1
which looks a little silly.
but now you get the error in the return value:
3.2.1 :004 > `ruby test.rb 2>&1`
=> "test.rb: --> test.rb\nUnmatched `(', missing `)' ?\n> 4 p(\"{}\"\ntest.rb:4: syntax error, unexpected end-of-input, expecting ')' (SyntaxError)\np(\"{}\"\n ^\n\n"
A breakdown of how it works:
File descriptor 1 is the standard output (stdout
).
File descriptor 2 is the standard error (stderr
).
At first, 2>1
may look like a good way to redirect stderr
to stdout
. However, it will actually be interpreted as “redirect stderr
to a file named 1
”.
&
indicates that what follows and precedes is a file descriptor, and not a filename. Thus, we use 2>&1
. Consider >&
to be a redirect merger operator.