by

Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Activity
  • 11:31
    depfu[bot] labeled #214
  • 11:31
    depfu[bot] opened #214
  • 11:28
    antstorm commented #584
  • 11:28

    depfu[bot] on update

    Update rubocop to version 0.91.1 (compare)

  • 11:24
    depfu[bot] labeled #384
  • 11:24
    depfu[bot] opened #384
  • 11:22

    depfu[bot] on update

    Update rubocop to version 0.91.1 (compare)

  • 08:40
    solnic commented #584
  • 00:44
    DiegoOrejuela starred hanami/controller
  • Sep 23 22:22
    antstorm opened #584
  • Sep 23 20:25
    swcarlosrj starred hanami/hanami
  • Sep 23 12:16
    maikelcoke starred hanami/hanami
  • Sep 23 10:32

    timriley on unstable

    (compare)

  • Sep 23 10:32

    timriley on unstable

    Reintroduce CSRFProtection modu… (compare)

  • Sep 23 10:32
    timriley closed #327
  • Sep 22 22:13
    clsource starred hanami/hanami
  • Sep 22 10:41

    jodosha on unstable-rubocop-hanami-dry-rb-rules

    (compare)

  • Sep 22 10:41

    jodosha on unstable

    Rubocop Hanami dry-rb rules (2.… (compare)

  • Sep 22 10:41
    jodosha closed #117
  • Sep 22 10:33
    jodosha milestoned #117
Kai Kuchenbecker
@kaikuchn
I've avoided OpenStructs myself for believing that they impact performance negatively.. The fact that a new syntax for constructing anonymous Structs is being introduced makes me think that this is still valid.
François Beausoleil
@francois

Hi again! This time, I'm having issues with expecting changed values in the session after an action has completed. I'm spec'ing a regular email/password authentication flow. In the success path of the action, the code executes session[:user_id] = person.id. This is my spec:

let(:session) { Hash.new.freeze }
let(:params)  { Hash["rack.session" => session.freeze, session: { email: "baden", password: "powell" }] }

it "records the user in the session" do
  action.call(params)
  expect(session[:user_id]).to eq(31)
end

Notice that I added freeze to the session object above, but apparently, Hanami makes a copy of the session because I never get a FrozenObjectError. I also checked #object_id: everywhere in the spec I have one object ID, but in the action, I see another one:

# calling p [session.object_id, session.frozen?, session] from the spec and the action results in different object IDs
[70338224558660, true, {}]
[70338224556300, false, {:user_id=>31}]

The Session Testing section of the guide doesn't explain how to assert against the session after the action has completed.

I'm still on Hanami 1.3.3. Thanks in advance!

Kai Kuchenbecker
@kaikuchn
@francois have a look at the exposures of the action, session should be among them. I.e., action.exposures[:session].
François Beausoleil
@francois

Hello again!

This time around, I'm trying to implement a plain old file upload to import CSV files. In the action, the file upload's key appears as a string, in all cases I have tried.

I believed that calling #to_h or #validate and using #output from the result would return symbolized keys, but alas, that wasn't so:

(byebug) params.to_h
{:_csrf_token=>"c21e7616006db2729c88938a7108e621d9f94d1be071f55b4253c7910bf1b2a0", :import=>{"file"=>{:filename=>"a.csv", :type=>"text/csv", :name=>"import[file]", :tempfile=>#<Tempfile:/var/folders/1s/2rf_zh1970sdvk9w6yg2cyqm0000gn/T/RackMultipart20200813-85842-hj5evv.csv>, :head=>"Content-Disposition: form-data; name=\"import[file]\"; filename=\"a.csv\"\r\nContent-Type: text/csv\r\n"}}}
(byebug) params.validate
#<Dry::Validation::Result output={:_csrf_token=>"c21e7616006db2729c88938a7108e621d9f94d1be071f55b4253c7910bf1b2a0", :import=>{"file"=>{:filename=>"a.csv", :type=>"text/csv", :name=>"import[file]", :tempfile=>#<Tempfile:/var/folders/1s/2rf_zh1970sdvk9w6yg2cyqm0000gn/T/RackMultipart20200813-85842-hj5evv.csv>, :head=>"Content-Disposition: form-data; name=\"import[file]\"; filename=\"a.csv\"\r\nContent-Type: text/csv\r\n"}}} errors={}>
(byebug) params.validate.output
{:_csrf_token=>"c21e7616006db2729c88938a7108e621d9f94d1be071f55b4253c7910bf1b2a0", :import=>{"file"=>{:filename=>"a.csv", :type=>"text/csv", :name=>"import[file]", :tempfile=>#<Tempfile:/var/folders/1s/2rf_zh1970sdvk9w6yg2cyqm0000gn/T/RackMultipart20200813-85842-hj5evv.csv>, :head=>"Content-Disposition: form-data; name=\"import[file]\"; filename=\"a.csv\"\r\nContent-Type: text/csv\r\n"}}}

The form is declared with the minimal amount of fuss:

form_for :import, routes.import_people_path, enctype: "multipart/form-data" do
  file_field :file, required: true
end

The params declarations are done in-line, in the action:

params do
  required(:import).filled.schema do
    required(:file).filled.schema do
      required(:filename).filled(:str?)
      required(:tempfile).filled(size?: 1 .. 1_048_576)
      required(:type).filled(:str?, included_in?: %w(text/csv))
    end
  end
end

And the action's implementation is a simple:

def call(params)
  if params.valid?
    upload = @transaction_manager.transaction do
      # Hmmm, things that make you go "hmmm"...
      # Notice that we don't have a
      @upload_repository.create_upload_for_people_import(
        data: params[:import]["file"][:tempfile].read,
        name: params[:import]["file"][:filename],
        size: params[:import]["file"][:tempfile].size,
        type: params[:import]["file"][:type],
      )
  else
    self.status = 422
  end
end

The Hanami Guide is silent on the issue of file uploads. The only mention of the word "upload" is on the validations page, and then it is only a passing reference. Otherwise, "multipart" is mentionned in the mailer section, which isn't what I'm looking for.

I'm not interested in pre-packaged solutions for now, as I'm learning Hanami and how things are built on the inside. This is a learning opportunity, not a production implementation.

Thanks a bunch!

Paweł Świątkowski
@katafrakt
@francois which version are you using? I have upload fields as symbols in 1.3.3
Paweł Świątkowski
@katafrakt
[1] pry(#<Web::Controllers::Upload::Create>)> params.to_h
=> {:_csrf_token=>"46dd20e5456f20ec428b854d229c07c24d3fd34ca1f77d482ba4ba183927f005",
 :import=>
  {:file=>
    {:filename=>"vyzsu6q.png",
     :type=>"image/png",
     :name=>"import[file]",
     :tempfile=>#<File:/tmp/RackMultipart20200813-20764-1blofxp.png>,
     :head=>"Content-Disposition: form-data; name=\"import[file]\"; filename=\"vyzsu6q.png\"\r\nContent-Type: image/png\r\n"}}}
oh, now I see you're on 1.3.3 too
Paweł Świątkowski
@katafrakt
adding params block changes it, so this is clearly a bug
François Beausoleil
@francois
@katafrakt that is correct, I am on 1.3.3. If you point me in the right direction, I should be able to have a failing test as well as a fix.
Sebastjan Hribar
@sebastjan-hribar
Not really a Hanami question, but still, I'm getting strange errors with feature test using MiniTest and Capybara. Sometimes the page element is not found. The thing is, I use the same assertions as elsewhere. Even the save_and_open_page shows the elements and their respective content, in most cases text fields.
François Beausoleil
@francois

@sebastjan-hribar I had success with taking a screenshot before and after the failing assertion. Is it as simple as calling #save_screenshot in the context of the Capybara spec? #save_screenshot expects a filename as an argument.

Another thing that is useful is to get the JS error logs:

page.driver.browser.manage.logs.get("browser")

Hope this helps!

Sebastjan Hribar
@sebastjan-hribar
@francois Thank you, will try that.
François Beausoleil
@francois

I'm searching for the options available for the hanami-model (1.3.3) associations DSL. Over on Rubydoc, I'm being told that the methods are part of a private API: https://www.rubydoc.info/gems/hanami-model/Hanami/Model/Associations/Dsl#belongs_to-instance_method

The Hanami guide has information about associations, but only the has_many through section references aliasing: https://guides.hanamirb.org/associations/has-many-through/

Specifically, I am modeling prerequisites for awards. An award is more general than a course: it can be a decoration or a course. Before being eligible to receive decoration X, you need to have succeeded at courses Y and Z. I am modeling this as a has_many through, where the middle table has two belongs_to, but both link back to the same table.

As described in the guide, I tried the as option:

class AwardPrerequisiteRepository < Hanami::Repository
  associations do
    belongs_to :award
    belongs_to :award, as: :prerequisite
  end
end

Unfortunately, I received the following error message:

$ bin/hanami console
key not found: :prerequisites
Did you mean?  :award_prerequisites
/Users/francois/.rvm/gems/ruby-2.6.6/gems/hanami-model-1.3.2/lib/hanami/model/configuration.rb:161:in `rescue in load!'

When I flip the belongs_to args around, I still get an error:

#     belongs_to :prerequisite, as: :award
$ bin/hanami console
key not found: :prerequisites
Did you mean?  :award_prerequisites
/Users/francois/.rvm/gems/ruby-2.6.6/gems/hanami-model-1.3.2/lib/hanami/model/configuration.rb:161:in `rescue in load!'

When I add the prerequisites to the AwardRepository, I get a different error:

class AwardRepository < Hanami::Repository
  associations do
    has_many :awardships
    has_many :award_prerequisites, :prerequisites
    has_many :people, through: :awardships
  end
end

class AwardPrerequisiteRepository < Hanami::Repository
  associations do
    belongs_to :award
    belongs_to :award, as: :prerequisite
  end
end
$ bin/hanami console
no implicit conversion of Symbol into Integer
/Users/francois/.rvm/gems/ruby-2.6.6/gems/hanami-model-1.3.2/lib/hanami/model/configuration.rb:161:in `rescue in load!'

Where are the docs on how to use associations, including aliasing?

Thanks in advance!

Sebastjan Hribar
@sebastjan-hribar

@francois at the first glance it looks like something similar I've tried.

RE self-referential assoc: it turns out the current hanami-model doesn't support it yet. https://rom-rb.zulipchat.com/#narrow/stream/191800-general/topic/self-referential.20association

François Beausoleil
@francois
Oh, that sucks :( Thanks for the reply, @sebastjan-hribar!
François Beausoleil
@francois

Another day, another question!

I'm trying to add a rule to a params block that will assert that a given slug exists in the database. The Rules section of the Hanami Guide mentions some syntax to achieve that, but there are no examples where one accesses the database.

Over on dry-rb's site, the High-Level Rules documentation also show how to have a rule that works against multiple values, but nothing to validate against the database either.

In hanami-validations' README, I found Context of Execution which explicitly mentions that arbitrary code cannot be executed. After reading this, I suspect that I cannot write a rule, but must instead write a predicate, since predicates can execute arbitrary code.

I remember, but can't find it, reading about passing parameters to dry-validations's schema so that we could pass-in the repository, for example.

At this point, this is what I have written:

module Web
  module Controllers
    module Awardships
      class AwardshipValidator < Web::Action::Params
        include Hanami::Validations::Form

        def initialize(hash, award_repository: AwardRepository.new, person_repository: PersonRepository.new)
          super(hash)
          @award_repository = award_repository
          @person_repository = person_repository
        end

        predicate :award_exists?, message: "must be an existing award" do |slug|
          byebug
          !!@award_repository.find_by_slug(slug)
        end

        predicate :person_exists?, message: "must be an existing person" do |slug|
          byebug
          !!@person_repository.find_by_slug(slug)
        end

        validations do
          required(:awardship).schema do
            required(:person_id).filled(:str?)#, :person_exists?)
            required(:award_id).filled(:str?, :award_exists?)
            required(:awarded_on).maybe(:date?)
          end
        end
      end
    end
  end
end

Given the above, I get NoMethodError #find_by_slug because the repositories are nil.

Can someone point me in the right direction, please? Thanks again!

Kai Kuchenbecker
@kaikuchn
Is this discussion helpful for you? hanami/controller#209
Shalil Awaley
@krazedkrish

Hi Guys,
Can someone help me with Hamani 1.3, database config.
I want to set pool_timeout: and after_connect: proc

I cannot find any example in the internet, can some some give me an example like:

Hanami::Model.configure do
  adapter :sql, ENV['DATABASE_URL']

  #something like
  #build({ pool_timeout: 15,
    after_connect: proc { |c| c.execute("SET statement_timeout = '#{ENV['STATEMENT_TIMEOUT'] || '10s'}'") })

  migrations 'db/migrations'
  schema     'db/schema.sql'
end.load!
Kai Kuchenbecker
@kaikuchn
@krazedkrish Since Hanami uses Sequel, I believe you can specify pool_timeout and statement_timeout via the DATABASE_URL. See https://sequel.jeremyevans.net/rdoc/files/doc/opening_databases_rdoc.html
Shalil Awaley
@krazedkrish
@kaikuchn , thanks a lot.
Artem Rashev
@mgpnd
Hey guys, do you have any note about how and why Hanami wraps Entity around ROM relations?
Sebastjan Hribar
@sebastjan-hribar

Hi all, I have a question related to our setup involving the unique constraint on a column. When I rescue the UniqueConstraintValidationError, is it possible to get the ID of the entity that caused the error? Here is the background and is related to a few time mentioned translation app.


Create source sentence
Create target sentence
Create translation record using IDs of the sentences above as FKs.


It can often happen one of the sentences will and should be used again. For example, same target language, but different source language. In that case, I would like to reuse the target sentence. To avoid rescuing the unique error by searching again the DB for the sentence (there will only be one table for sentences, so this could become resource intensive), I need the ID and have the new translation record use it.

I currently don't see this information in the error details.

rudy
@unixc3t
hello
I want to resposne xml , I need to config someting?
rudy
@unixc3t
self.format = :xml in the call method of the action
Paweł Świątkowski
@katafrakt
@sebastjan-hribar I doubt that, as database do not expose this information in their error message (I checked sqlite and postgres) so it would have to perform a query internally anyway.
Kai Kuchenbecker
@kaikuchn

What you could do is write an upsert statement that effectivly does nothing on conflict by updating the conflicting identical value but returns the id. I.e., insert into foo (id, bar) values (2, 'unicorn') on conflict (bar) do update set bar = EXCLUDED.bar returning (id) Would give you either the ID of the inserted record or the id of the existing record.

But it would write to the table every time.. so depending on your use it may be better to query for existence first. If you think round trip time is going to kill your performance, you could also write this statement which effectively always does two queries on insert: WITH inserted AS (insert into foo (id, bar) values (2, 'unicorn') on conflict do nothing returning id) select id from foo where bar = 'unicorn';

In the end you need to look at your database and check how often this happens. It may be best to just try to insert first and query if it fails, when this rarely happens.
Architecturally this isn't a huge design decision.. it's a low level detail so you can easily just go ahead with the simple solution and gather some data.
Sebastjan Hribar
@sebastjan-hribar
@katafrakt @kaikuchn Thank you both. I'll go with performing the query for now. I needed to verify this, since my research (a.k.a. googling) hasn't returned anything promising and I haven't dealt with it before. Also, I plan to have the table indexed and that should help the performance as well. However, I'm not that far yet.
crokobit
@crokobit

Hi all, can I map query results with different table names to child entity value?
e.g.
user has roles but the table name is legacy_roles.

I will get data by
UserRepository.new.aggregate(legacy_roles: nil).map_to(User).to_a

User entity is like this

class Action < Hanami::Entity
  attributes do
    attribute :roles, Types::Collection(Role)
  end
end

can I map query results of users with roles attribute using the result of legacy_roles???

Edouard
@inouire_twitter
New project using Hanami -> hanami/hanami.github.io#510 :)
Klaus Heissler
@claudiug
hello for hanami-api, i do have some questions. If the project production ready? also, there is any api documentation?
Alan Ridlehoover
@aridlehoover
Hello from smoky San Francisco, California! I love the work the Hanami team has done! I am particularly impressed with Hanami Router 2.0 Alpha 3. And, I'm wondering what the timeframe is for releasing it. Is this the right place to ask that type of question? Thanks!
Sven Schwyn
@svoop
Hi from Sweden! I second @aridlehoover, great work! I'm sketching a new project for Q1/2021 and I'm inclined to give Hanami 2 a shot instead of Rails, so some insight on how you forsee the next few months would be great. Not necessarily for a production release, but maybe a sufficiently working alpha/beta to get started with.
Kai Kuchenbecker
@kaikuchn
@aridlehoover @svoop I'm asking the team what they think about that and will get back to you about it when I have an answer. But I'm assuming that it's still in its very early stages, i.e. expect lack of documentation, etc.
Sven Schwyn
@svoop
Thanks a bunch, @kaikuchn !
Kai Kuchenbecker
@kaikuchn

Ok, so this is the road map for hanami 2.0: https://trello.com/b/lFifnBti/hanami-20 You can follow @timriley's blog (https://timriley.info/) if you want to have a more detailed view on his personal progress with items from the road map. You can also check out his application template if you want to get started with hanami 2.0 now (https://github.com/timriley/hanami-2-application-template) he's using hanami 2.0 right now at the company he's working for, but warns that there's gonna be some degree of disruption. They do use it for 3 production apps though. But be warned, @parndt tried to get started and struggles with it a lot. He's promised to work on a getting started guide as a result of his struggles, but there is none yet!

People think that 2.0 is gonna be a 2021 Release but no promises. Stable versions of usable pieces may be released gradually, e.g. hanami-api or hanami-model.

Your continued interest has triggered the intent to finally write up a blog post about the status, goals, etc. probably with a Q&A, I'll let you folks know here when that happens. :)

Sven Schwyn
@svoop
@kaikuchn This is very helpful news, thank you! I'll keep an eye on the resources you've mentioned. I understand the changes from Hanami 1 to 2 are pretty major, so since I'm Rails senior but new to Hanami, what's your opinion on the following question: Does it make sense to study the Hanami 1 guides and code in depth now and then take it from there as parts of 2 become stable? Or are the differences so profound, it'd be a better idea to just skim over the Hanami 1 guides and wait for the new guides before diving into the code?
Kai Kuchenbecker
@kaikuchn
I think that familiarity with the dry-rb gems will be most helpful (https://dry-rb.org/). I suspect that many concepts from dry-rb will be present in hanami 2.0 since dry-rb, rom and hanami folks are working closely together on this. I know that the framework itself will be using dry-rb/container for instance, will it be helpful to have an understanding of dry-rb/container when using hanami 2.0? Maybe not for usual tasks but if you're debugging something, or encounter a limitation of the framework I'm sure it will help.
Other things like dry-validation will definitely be helpful to know. I suspect that it will be present again in hanami 2.0 since it's just a very good way to define and perform validations.
Apart from that looking over the getting started guide from hanami 1.0 may give you a glimpse of where we came from and some concepts are likely to stay. Although I cannot say with certainty which.
Sebastjan Hribar
@sebastjan-hribar

I have a question about designing a REST API endpoint that would accept post requests.
We're building a middleware (call it M for brevity) that seats between a data provider (call it A) and data consumer (call it B). Here is the workflow:

  1. A user enters an ID in M and triggers the process.
  2. M calls A and gets the data.
  3. M sends the data to B.
  4. B uses the data to create an entity.

So the middleware might be used by a variety of B apps that all need to get the data from A. Due to constraints we need M and can't setup direct communication between A and B.

For the POC we need a test B app. My question is how to approach this. My high level picture is a REST endpoint in B that calls an interactor to create an entity. If this is correct, can someone help with some guidelines for the endpoint?

Sebastjan Hribar
@sebastjan-hribar
What is the correct way of whitelisting a param, that is optional? If I follow the simplest example of required(:some_param).filled it will not pass it through. And omitting .filled results in nil if the param contains a value.
Kai Kuchenbecker
@kaikuchn
use optional I guess? See Usage in this section of the guide https://guides.hanamirb.org/actions/parameters/#validations-coercion
Regarding your other question I have reservations about calling another services synchronously during a http request cycle, especially on every request. Do you own that other service? Otherwise do you have any guarantees on response times? Or will you timeout after 100ms?
Kai Kuchenbecker
@kaikuchn
I'm not saying "don't do it" since it's pretty normal to call services (e.g., your database, or cache) within a request cycle, but it needs to be fast.
Sebastjan Hribar
@sebastjan-hribar
@kaikuchn Thank you for both inputs. I don't know how optional escaped me, I'll try to forget I've asked as soon as possible :smile_cat: . As for calling another service synchronously I'll discuss it with the team, but I don't see any other option given the circumstances. Right now, error/exception handling seems our best bet. So, assuming we will do it, how should we go about it? Like I described above?
Sebastjan Hribar
@sebastjan-hribar
To add to the explanation, we already have the first two points in the workflow setup and calls to A and its responses are really fast.