How to use Hotwire in Rails Discussion
Can you please provide the repository for this also?
hotwire-rails repo: https://github.com/hotwired/hotwire-rails
lesson repo: ?
I had a problem running the repo, I got an error: ActionView::Template::Error (The asset "importmap.json" is not present in the asset pipeline.
):
I had to create the folder "libraries" in app/assets/javascripts and then it ran fine.
PRO TIP: If you are having issues with Turbo frames not working, make sure you remove/comment out the following from the packs/application.js
// Rails.start()
// Turbolinks.start() <-- This will break stuff
Thanks Michael!
Can we make DHH get rid of turbolinks.... nothing but problems
Thanks Michael. This worked for me.
For those who might have Turbolinks.start, comment out - 'ActiveStorage.start'.
Just curious on what is the app would looks like when we got js disable. I got a feeling that it might still work
What is the thinking behind moving the javascript components back to the asset pipeline?
I'd also like the answer to that :)
It seems strange to me that Turbo has the same problem out of the box that Turbolinks has when it comes to validation errors. Turbo takes over your forms by default and doesn't render a HTML response unless you use a Turbo Frame (judging from this video). So a standard Rails scaffold won't work with form errors straight away?
Read somewhere: 'Rails 6 defaults to using Webpacker for Javascript instead of the asset pipeline'
Turbolinks is dead. Rails 6.1, few hours later hotwire and one can manage javascript via the asset pipeline. Turbo [something]. A Phoenix was sighted.
Wait!
So what happens when one migrates an app from 5 to 6, then realizes this is hot and loads the gem.
What conflicts could arise?
Errant tangential thought:
God forbid Jack has a remote control over Chris's fan when he invokes editing a tweet.
This works with either the asset pipeline or webpacker. The point of showcasing it in the asset pipeline and not with the use of webpacker, I think, is to underline the fact that this is supposed to be minimizing the javascript needed to be written for these features. Why use something as overwhelming as webpack if you aren't going to use it for much (rhetorical)? But it works in either case. Check out the readme: https://github.com/hotwired/turbo-rails (hotwire-rails just packages up turbo-rails and stimulus-rails together for you).
I love how clearly excited Chris is about this, trying not to crack a huge smile every other minute! There's nothing like listening to someone talk about what they're passionate about :)
Can someone help me? I'm confused about Hotwire and some of the latest stuff that came out.
1) What is exactly Hotwire does?
2) And how can be it compared to StimulusJS, Stimulus Reflex and Actioncable?
I'm just having dificulties to understand what each of those are and how each can be used.
Thanks in advance.
Hotwire: the umbrella project for Turbo, StimulusJS, and Strada
Turbo: the sucessor to turbolinks, it provides frames and mechanisms updating them over ajax or websockets. The entire video is about Turbo's integration with rails via the turbo-rails gem.
SitmulusJS: a minimal javascript framework that's been around for a few years. It provides mechanisms to link javascript class instances to blocks of DOM, register event handlers, and keeps everything in sync via the MutationObserver API. It's a very good match for sites using Turbolinks/Turbo
Actioncable: Rails' built-in websocket implementation. Used behind the scenes by both StimulusReflex and Hotwire.
StimulusReflex: an independent project for doing HTML-over-the-wire in Rails that has been around for a few years and gained a lot of attention this year. Built with StimulusJS, ActionCable, and CableReady, it uses websockets for everything and uses fast DOM diffing to update the page. Not as tightly integrated with the standard Rails' scaffold patterns, it offers more flexibility for apps that break out of CRUD patterns.
CableReady: sister project to StimulusReflex, it provides a variety of tools for pushing updates to the client via websocket.
Fantastic, Rafe! Thanks so much!
so when i try to broadcast the creation of an item i get actioncable error not able to connect to redis
rescue in establish_connection': Error connecting to Redis on localhost:6379 (Redis::TimeoutError) (Redis::CannotConnectError)
Are you running an installed version of redid on your development machine?
I am facing the same error when trying to create new tweet. Don't know what to try and fix. Never heard of redis before and never used action_cable before this. What might be the problem?
You may need to install Redis. See this section https://hixonrails.com/ruby-on-rails-tutorials/ruby-on-rails-redis-installation-and-configuration/#redis-installation
Same problem here. I thought redis was installed on mac but it wasn't.
brew install redis
brew services start redis
https://gist.github.com/tomysmile/1b8a321e7c58499ef9f9441b2faa0aa8
thanks Caroline, it helps me! (reinstall redis and run "brew services start redis")
Thanks for the vid, Chris!
Didn't actually get one thing. For some reason, I can't afford broadcasting with a model callback (like it's shown in the lesson), and I therefore need to broadcast from the controller action.
I checked the docs, and here's how I made it:
...
if @tweet.save
format.turbo_stream do
render turbo_stream: turbo_stream.prepend(:tweets, partial: "tweets/tweet",
locals: { tweet: @tweet })
end
format.html { redirect_to tweets_url, notice: 'Tweet was successfully created.' }
format.json { render :show, status: :created, location: @tweet }
else
...
This approach works pretty much like the original from the lesson, but! The new tweets don't appear in another browser tab! New tweet does show up on the author's tab, but on any other tab/browser/device -- it simply doesn't.
Frankly, I didn't really spend much time digging in the docs, did I miss anything maybe?
Best.
Where is the broadcast? I don't see one in the controller. You will still need to perform a broadcast somewhere to send the new HTML down the ActionCable pipe to other browsers. Currently, you are only responding to the request using Turbo. That is not the same as broadcasting. I hope this helps.
Yeah, I REALLY don't like that in this implementation. IMO, a Model should be about validation and data management, not causing things to happen on a front-end. I feel like these types of broadcasts should always be coming from the controller. It feels icky to put that in there when we've been working on separation of concerns for so long.
I guess the benefit is that you are sure it happens on every save, and you don't forget to send a broadcast from one controller action to the next. But it still feels wrong to me.
Only 2 more major changes and Rails is back to good old days: swap Webpack for Snowpack and ActionCable for AnyCable
Has anyone tried to tet a deployment of this with Heroku? I have been getting the "Precompiling assets failed." error,
The trace starts with.
Errno::ENOENT: No such file or directory @ dir_initialize - /tmp/build_00ed1b07/app/assets/javascripts/libraries
Any help before I move to stack overflow?
Same! Has anyone figured out how to deploy yet?
It's because the "libraries" folder is empty thus not committed to Git. You can add an empty .keep file to the folder to avoid the problem.
Thanks figured it out! You can also run this.
echo > app/assets/javascripts/libraries/.gitkeep
git add app/assets/javascripts/libraries
git commit -m "Adding app/assets/javascripts/libraries
do you have a /assets/javascripts/libraries folder? installed it for asset pipeline or webpack?
Yeah.
but it is an empty folder, what should be there?
HAHA, I got it to work. I added the libraries folder to a .gitkeep file. all good now!
How we can make it works with modals? 🤔
I mean, share feedback to the element (like close it after created tweet)
You'd have to wire it up with StimulusJS controller to close the form on submission. Or roll your own JS function for that.
Has anyones destroy action for an object stopped working? And when clicked, it redirects to the show page without destroying the object?
Try a button_to instead of a link_to (still using method: :delete)
Thanks Bryce! - I managed to get link_to working after re-adding rails@ujs. Button_to also works too.
Thanks Bryce, button_to works perfectly!
Hotwire is amazing. I tired different mini-apps to using Hotwire feature. While I know I can edit a form, could i edit an attribute (such as an email) on its own without editing/submitting the whole form?
You probably have to create a separate controller to handle the editing/updating of that attribute and then wrap that attribute in hotwired form. Or use regular CRUD controller but still wrap each field in a separate form. Or do some javascripting.
Hi guys, has anyone tried broadcasting from a model (or a background Active Job worker, in my case using Shoryuken) for a resource that is nested.
broadcast_replace_to is complaining about /project/:project_id/files/:id missing keys (e.g. project_id) for the resources show route
solved: my issue was a link_to in the partial being rendered by broadcast_replace_to
Chris spotted my issue right away, i switched the offending instance variables to locals - all working super well now.
rails s crashes and throws this error "Error connecting to Redis on localhost:6379 (Errno::ECONNREFUSED) (Redis::CannotConnectError)" after I add the turbo_stream_from. Only way I'm able to get it to run is by running redis-server in a separate command line. Is this intended? Anyway around it?
The gem foreman will help you here. It helps get your multiple processes started in one command
I have a datepicker in my form, and it's broken when the form is replaced. How to solve that issue?
It seems that upgrading past turbo-rails version 0.5.3 is an issue. Using tips from this episode, form submission is now submitting as html again instead of TURBO_STREAM. This causes an issue when create needs to re-render on save failure as seen in this path - https://github.com/gorails-screencasts/hotwire-twitter-clone/blob/master/app/controllers/tweets_controller.rb#L35
Anyone else have issues when using turbo-rails 0.5.4 and up? The change seems to be around this commit https://github.com/hotwired/turbo-rails/commit/b3fab95cc3e73b1a2960f0ea4a3509e0d490a16a#diff-a6c9ea9b91a99345ff04b9597b41369bc2552724c7c00135db376ff782aaf7ab
I ended up having to update my test project to only use loading of turbo-rails through the tag helper...after I did that it worked as it did before https://gitlab.com/doug.stull/turbo_modal/-/commit/ce17a5208fb175f3ffe8c5e40ed4031f18ca9f08
I had the same issue - updated to turbo-rails 0.5.9 and links / forms stopped submitting as turbo_streams. Moved back to 0.5.3 and it went back to normal. Wtf! Thanks for pointing me to the heart of the issue though!
I have an issue when I submit an empty for the second time. If I submit the empty field for the first time, the validation displays, then if I submit again with empty field, the submit button is then disabled. How to solve that?
When I cloned this from GitHub I was pleasantly surprised to not see webpacker or Node.Js stuff, the project folder for this Hotwire project is around 13MB rather than 124MB for a new Rails 6 project.
Can anybody tell me how to setup a new Rails 6 project using Hotwire WITHOUT Webpacker and Node.js?
You can pass in 'Rails new my_app --skip-webpack-install' to create the app framework and skip Webpacker altogether.
I saw that suggestion by "chrisma" on a Stack Overflow answer https://stackoverflow.com/questions/64466331/is-it-possible-advisable-to-run-rails-6-without-webpacker but it seems to still have some webpack bits around. Do I just have to accept this and delete them manually?
You can safely delete the files if you are not going to use Webpacker at all.
Has anyone been able to get hotwire to work with authorization when adding/updating data on an index page. For example if I have an index page with a table and each row on the table has an Edit button on it which is wrapped in a pundit policy check.
Check this out: https://blog.cloud66.com/making-hotwire-and-devise-play-nicely-with-viewcomponents/
I realize this example is using devise and you mentioned Pundit, but I think it might at least send you down the right path. Hope it helps!
Have you noticed that every time you click 'Cancel' from edit, it results in a new nested turbo_frame_tag with the same dom id? It doesn't seem to break anything and it's obvious why it's happening, but it still seems weird to me. I was trying to avoid the same behavior in my own project, but things got messy quickly. I can't figure out how you would call 'show' without the corresponding turbo_frame_tag.
Edit for visual: https://paste.pics/de3344e3cf09a81522d992b37f6edb80
Edit part 2: To be super clear, the above image is of this project, not mine.
Can't tell you why it's happening, I looked at the code and it seems ok. Nothing wrong with.
I suspect the whole concept of turbo_frame_tags is a bit confusing to many. We're not used to the idea of navigation within a frame, it sort of remind me of how iframes work.
Maybe there is confusion with how turbo_streams should work with turbo_frames.
I hear you. I think iframes were a little more intuitive because the most complicated operation involved targeting in and out of them.
With the cancel link here, it's a bit tricky--for me, anyway--because unlike the CRUD operations, which you can broadcast to from the model (as was done here), what should be a straightforward operation seems to have no real recourse to things like turbo_stream.replace. Calling 'show' means invoking that turbo_frame_tag, whether you want it or not. You could render a partial without it, but then you lose the Turbo functionality for the next operation.
It's probably a conceptual problem, but for me the rather austere docs don't do a great job of wedding streams and frames (to say nothing of linking them with Stimulus).
Hi Chris, any solution to nested HTML's ? or is it the way it works ? Pls explain. Looks confusing.
I have to the best of my ability followed the code - but for some reason, the only two things that don't broadcast is the like and retweet updates. Can anyone else verify this is the case?
Tried to implement it with a user model & devise. Devise is working ok but on error on creating an user the form is rendered ok, second time when I’m trying to resubmit with an error the user is not passed and on inspection the turbo frame is empty? What might be the issue?
solved it, I had it misconfigured
I can't get any of my delete links to work, has this happened to anyone else?
You using link_to or button_to ?
Hi, I was trying that also, I think I was able to make it work:
on _tweet.html.erb
I added
<%= link_to "Delete", tweet_path(tweet), method: :delete, data: { turbo_method: "delete" } %>
on tweets_controller
:
format.turbo_stream { render turbo_stream: turbo_stream.replace(@tweet, partial: "tweets/form", locals: { tweet: @tweet}) }
Not sure if is the correct way to make it work, but worked for me.
It seems strange to me that Turbo has the same problem out of the box that Turbolinks has when it comes to validation errors.
hi chris , i'm trying to implement comment feature without refresh in my rails app using hotwire , but when i run the server , i find this error : Sprockets::Rails::Helper::AssetNotFound in Posts#index , The asset "importmap.json" is not present in the asset pipeline. (Extracted source (around line #16): <%= stimulus_include_tags %>
How do you unit test hotwire? only system tests with capybara? i wonder if we can easily unit test it with request specs?
BTW, were you guys using this with Rails 7?
i am planning to use Rails7 in my new project that i will start in few days
Awesome!
I think this tutorial's a little outdated. Was trying to do it with Rails 7, and some things are configured differently.
How to get the likes and retweets counter updated? When opening two separate tabs it is the only one that is not reflected in both
To whom it may concern, make sure your redis-server is running and the you update the development adapter to redis with the URL in cable.yml if turbo is not working as expected. Thanks for the lesson Chris!
OMG.
Rails 7.2.2
A lesson learnt. Next time any problem with the Tuts, check this comment section.
It took me 2 days and praying my subconscious mind (even chatGPT didn't help point out to run Redis :( to help figure out I wasn't running Redis on the local machine as the cause for Browser not updating when record change in Rails console. Then I came to report this in comments and someone had found the solution a year ago.