bridgetownrb / bridgetown

A next-generation progressive site generator & fullstack framework, powered by Ruby
https://www.bridgetownrb.com
MIT License
1.13k stars 114 forks source link

NameError when using bridgetown-activerecord with Roda #844

Open alvincrespo opened 7 months ago

alvincrespo commented 7 months ago

I'm trying to create simple signup form on the homepage of the site:

  <form name="signup-for-updates" method="POST" action="/signup">
    <input type="hidden" name="form-name" value="signup-for-updates">
    <input aria-label="Email" type="email" name="email" placeholder="Enter your email">
    <button type="submit">Notify me</button>
  </form>

However, I'm running into this NameError:

NameError: uninitialized constant Routes::Signup::Signup
# server/routes/signup.rb

class Routes::Signup < Bridgetown::Rack::Routes
  route do |r|
    # route: POST /hello/:name
    r.post "signup" do |email|
      Signup.create!(email: request.params["email"])
      r.redirect "/success"
    end
  end
end

I've run through the setup process as per the documentation from bridgetown-activerecord:

$ bin/bridgetown apply https://github.com/bridgetownrb/bridgetown-activerecord

I've also verified this works as expected in the console:

bin/bridgetown console                 
          Starting: Bridgetown v1.3.2 (codename "Kelly Butte") console…
       Environment: development
   Reading files... 
                    done!
Running generators... 
        Pagination: disabled. Enable in site config with pagination:\n enabled: true
                    done!
           Console: Your site is now available as site
                    You can also access collections or perform a reload!
irb(main):001> Signup
Signup (call 'Signup.connection' to establish a connection) < ApplicationRecord

When I do try to manually require ApplicationRecord and Signup, I get the following:

bin/bridgetown start
[Bridgetown]           Starting: Bridgetown v1.3.2 (codename "Kelly Butte")
[Server] * Puma version: 6.4.2 (ruby 3.2.2-p53) ("The Eagle of Durango")
[Server] * PID: 7502
[Server] * Listening on http://0.0.0.0:4000
[Server] Use Ctrl-C to stop
[Frontend] yarn run esbuild-dev
[Frontend] yarn run v1.22.21
[Frontend] $ node esbuild.config.js --watch
[Bridgetown]        Environment: development
[Bridgetown]             Source: /Users/alvincrespo/workspace/jardim/jardim-website/src
[Bridgetown]        Destination: /Users/alvincrespo/workspace/jardim/jardim-website/output
[Bridgetown]     Custom Plugins: /Users/alvincrespo/workspace/jardim/jardim-website/plugins
[Bridgetown]         Generating…
[Bridgetown]         Pagination: disabled. Enable in site config with pagination:\n enabled: true
[Frontend] esbuild: frontend bundling started...
[Frontend] esbuild: frontend bundling complete!
[Frontend] esbuild: entrypoints processed:
[Frontend]          - index.S2XEIG4A.js: 251B
[Frontend]          - index.KMAMCTPH.css: 13.61KB
[Bridgetown]             Done! 🎉 Completed in less than 0.25 seconds.
[Bridgetown]
[Bridgetown]     Now serving at: http://localhost:4000
[Bridgetown]                     http://192.168.1.155:4000
[Bridgetown]
[Server] 127.0.0.1 - - [19/Feb/2024:10:00:51 -0500] "GET / HTTP/1.1" 200 3517 0.0078
[Server] 127.0.0.1 - - [19/Feb/2024:10:00:51 -0500] "GET /_bridgetown/static/index.KMAMCTPH.css HTTP/1.1" 200 13939 0.0006
[Server] 127.0.0.1 - - [19/Feb/2024:10:00:51 -0500] "GET /_bridgetown/static/index.S2XEIG4A.js HTTP/1.1" 200 251 0.0003
objc[7502]: +[__NSCFConstantString initialize] may have been in progress in another thread when fork() was called.
objc[7502]: +[__NSCFConstantString initialize] may have been in progress in another thread when fork() was called. We cannot safely call it or ignore it in the fork() child process. Crashing instead. Set a breakpoint on objc_initializeAfterForkError to debug.

My guess is that I'm missing some configuration here.

Bridgetown Version: 1.3.2

To Reproduce

Sample Repo: https://github.com/alvincrespo/bridgetown-ar-roda-issue

Current behavior

Currently receiving a NameError by default. However, when manually requiring the files, I run into an __NSCFConstantString error.

Expected behavior

I was hoping that I could create a signup record in the DB with a custom POST route.

Computing environment (please complete the following information):

Additional context

image Screenshot 2024-02-19 at 10 37 42 AM
alvincrespo commented 7 months ago

btw - more than happy to help here! Any ideas on where to start would be fantastic, otherwise I'm still digging through the source to see if I can track down the issue.

alvincrespo commented 7 months ago

Just to rule out module naming conflicts, I did rename the route to SignupRequest, but ran into the same issue:

[Server]   Exception raised: NameError
[Server] uninitialized constant Routes::SignupRequest::Signup
[Server]                  1: /Users/alvincrespo/workspace/jardim/mysite/server/routes/signup_request.rb:7:in `block (2 levels) in <class:SignupRequest>'
[Server]                  2: /Users/alvincrespo/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/roda-3.77.0/lib/roda/plugins/_optimized_matching.rb:140:in `block in _is1'
[Server]                  3: /Users/alvincrespo/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/roda-3.77.0/lib/roda/request.rb:536:in `always'
[Server]                  4: /Users/alvincrespo/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/roda-3.77.0/lib/roda/plugins/_optimized_matching.rb:140:in `_is1'
[Server]                  5: /Users/alvincrespo/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/roda-3.77.0/lib/roda/plugins/_optimized_matching.rb:126:in `_verb'
[Server]          Backtrace: Use the --trace option for complete information.
[Server] 127.0.0.1 - - [19/Feb/2024:10:40:57 -0500] "POST /signup_request HTTP/1.1" 500 51678 0.1104
[Bridgetown]          Reloading… 1 file changed at 2024-02-19 10:41:06
[Bridgetown]                     - server/routes/signup_request.rb
[Server]   Exception raised: NameError
[Server] uninitialized constant Signup
[Server]                  1: /Users/alvincrespo/workspace/jardim/mysite/server/routes/signup_request.rb:7:in `block (2 levels) in <class:SignupRequest>'
[Server]                  2: /Users/alvincrespo/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/roda-3.77.0/lib/roda/plugins/_optimized_matching.rb:140:in `block in _is1'
[Server]                  3: /Users/alvincrespo/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/roda-3.77.0/lib/roda/request.rb:536:in `always'
[Server]                  4: /Users/alvincrespo/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/roda-3.77.0/lib/roda/plugins/_optimized_matching.rb:140:in `_is1'
[Server]                  5: /Users/alvincrespo/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/roda-3.77.0/lib/roda/plugins/_optimized_matching.rb:126:in `_verb'
[Server]          Backtrace: Use the --trace option for complete information.
[Server] 127.0.0.1 - - [19/Feb/2024:10:41:09 -0500] "POST /signup_request HTTP/1.1" 500 51662 0.0562
alvincrespo commented 7 months ago

Did some more research and found that I can use the sequel gem in the roda routes:

From: /Users/alvincrespo/workspace/jardim/mysite/server/routes/signup_request.rb:9 :

     4:
     5: class Routes::SignupRequest < Bridgetown::Rack::Routes
     6:   route do |r|
     7:     # route: POST /hello/:name
     8:     r.post "signup_request" do |email|
 =>  9:       binding.pry
    10:       ::Signup.create!(email: request.params["email"])
    11:       r.redirect "/success"
    12:     end
    13:   end
    14: end

[1] pry(#<Routes::SignupRequest>)> DB
=> #<Sequel::Postgres::Database: {:adapter=>:postgres, :extensions=>:activerecord_connection}>
[2] pry(#<Routes::SignupRequest>)> DB.tables
[Bridgetown]   Sequel (1.0ms)  SELECT CAST(current_setting('server_version_num') AS integer) AS v
[Bridgetown]   Sequel (25.8ms)  SELECT "relname" FROM "pg_class" INNER JOIN "pg_namespace" ON ("pg_namespace"."oid" = "pg_class"."relnamespace") WHERE (("relkind" IN ('r', 'p')) AND ("pg_namespace"."nspname" = any(current_schemas(false))))
=> [:schema_migrations, :ar_internal_metadata, :signups]
[3] pry(#<Routes::SignupRequest>)> DB[:signups]
=> #<Sequel::Postgres::Dataset: "SELECT * FROM \"signups\"">
[4] pry(#<Routes::SignupRequest>)> DB[:signups].insert(email: request.params["email"])
[Bridgetown]   Sequel (65.3ms)  SELECT "pg_attribute"."attname" AS "pk" FROM "pg_class", "pg_attribute", "pg_index", "pg_namespace" WHERE (("pg_class"."oid" = "pg_attribute"."attrelid") AND ("pg_class"."relnamespace" = "pg_namespace"."oid") AND ("pg_class"."oid" = "pg_index"."indrelid") AND ("pg_index"."indkey"[0] = "pg_attribute"."attnum") AND ("pg_index"."indisprimary" = 't') AND ("pg_class"."oid" = CAST(CAST('"signups"' AS regclass) AS oid))) LIMIT 1
[Bridgetown]   Sequel (8.8ms)  INSERT INTO "signups" ("email") VALUES ('some.email@example.com') RETURNING "id"

This is probably because the DB module is defined in the initializer, lib/bridgetown-activerecord/initializer.rb, in bridgetown-activerecord. I'm still not sure why the model isn't loaded or being found though when it's being autoloaded. I still need to understand the flow of the initializers in bridgetown-core.

As for the __NSCFConstantString error, that has to do with M1 and Ruby. ref https://github.com/rails/rails/issues/38560

jaredcwhite commented 7 months ago

@alvincrespo Hey, I took a quick look at your example repo (thank you for providing that!), and I don't actually see the Signup model in the models folder. Did it somehow get deleted by accident? I think your original issue was indeed a naming conflict between Signup the model and Signup the route, although using ::Signup when referencing the model would resolve that (but perhaps better to rename the route class, as you ended up doing).

alvincrespo commented 7 months ago

@jaredcwhite oh, sorry about that! I thought I had included it in the sample repo. I just added it. Double checked if I would get the same error and I did unfortunately:

From: /Users/alvincrespo/workspace/jardim/mysite/server/routes/signup_request.rb:9 :

     4:
     5: class Routes::SignupRequest < Bridgetown::Rack::Routes
     6:   route do |r|
     7:     # route: POST /hello/:name
     8:     r.post "signup_request" do |email|
 =>  9:       binding.pry
    10:       ::Signup.create!(email: request.params["email"])
    11:       r.redirect "/success"
    12:     end
    13:   end
    14: end

[1] pry(#<Routes::SignupRequest>)> ::Signup.create!(email: request.params["email"])
NameError: uninitialized constant Signup
from (pry):1:in `block (2 levels) in <class:SignupRequest>'
[2] pry(#<Routes::SignupRequest>)> Signup.create!(email: request.params["email"])
NameError: uninitialized constant Routes::SignupRequest::Signup
from (pry):2:in `block (2 levels) in <class:SignupRequest>'
jaredcwhite commented 6 months ago

@alvincrespo That's a weird one to be sure. One other idea for troubleshooting:

If you run bin/bridgetown console --server-config, can you type in Signup and see if it's available? And compare that to just a regular bin/bridgetown console?